美文网首页微信小程序
微信分享图片组件(小程序 )

微信分享图片组件(小程序 )

作者: BOB_BI | 来源:发表于2020-05-28 12:15 被阅读0次
    效果图.png

    需求:点击分享,弹出遮罩层,可分享给好友,可保存图片分享,canvas中的图片自适应(缩放、裁剪)
    技术:canvas 2,vant-weapp-ui
    思路:计划将整个分享都写成一个自定义组件,由于一些bug,没能实现,部分还是需要写在页面中。

    share组件:
    share.wxml

    <view class="wrapper shareWindow">
        <view class="other">
            <view class="flex_between">
                <button style="line-height: 100rpx;background:unset;" class="shareButton" open-type="share">
                    <image class="share-icon" src="../../images/icon/wechat.png"></image>
                    分享好友
                </button>
                <view class="pointer" catch:tap="savePic">
                    <van-icon name="down" class="share-icon" /> 保存图片
                </view>
            </view>
        </view>
    </view>
    

    share.js 含有canvas绘制白色背景,canvas文本换行,绘制图片,图片原比例缩小裁剪,图片自适应,保存图片等方法

    import {request} from "../../common/httpService"; 
    
    const app = getApp()
    
    Component({
        /**
         * 组件的属性列表
         */
        properties: {
            type: {
                type: String,
                value: ''
            },
            shareWords: {
                type: String,
                value: ''
            },
            imgSrc: {
                type: String,
                value: ''
            },
            title: {
                type: String,
                value: ''
            },
            userName: {
                type: String,
                value: ''
            },
            product: {
                type: Object,
                value: {}
            },
            dec: {
                type: String,
                value: ''
            },
            link: {
                type: String,
                value: ''
            },
            sceneStr: {
                type: String,
                value: ''
            },
            articleName: {
                type: String,
                value: ''
            }
        },
    
        /**
         * 组件的初始数据
         */
        data: {
            showShare: false,
            referrer: wx.getStorageSync('userId'),
            canvas: null
        },
        ready: function () {
            if (this.properties.type === 'article') {
                this.createArticlePic()
            } else if (this.properties.type === 'invited') {
                this.createInvitePic()
            } else if (this.properties.type === 'product') {
                this.createProductPic()
            }
            // this.getCodeImg()
        },
    
    
        /**
         * 组件的方法列表
         */
        methods: {
            initCanvas() {
                return new Promise((resolve, reject) => {
                    const query = wx.createSelectorQuery()
                    query.select('#myCanvas')
                        .fields({
                            node: true,
                            size: true,
                            id: true
                        })
                        .exec((res) => {
                            const canvas = res[0].node
                            const ctx = canvas.getContext('2d')
                            this.setData({
                                canvas: canvas
                            })
                            const dpr = wx.getSystemInfoSync().pixelRatio
                            canvas.width = res[0].width * dpr
                            canvas.height = res[0].height * dpr
                            ctx.scale(dpr, dpr)
                            let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                            console.log('imageData', imageData)
                            for (let i = 0; i < imageData.data.length; i += 4) {
                                if (imageData.data[i + 3] === 0) {
                                    imageData.data[i] = 255;
                                    imageData.data[i + 1] = 255;
                                    imageData.data[i + 2] = 255;
                                    imageData.data[i + 3] = 255;
                                }
                            }
                            ctx.putImageData(imageData, 0, 0);
                            let data = {
                                ctx,
                                canvas: res[0]
                            }
                            return resolve(data)
                        })
                })
            },
            createArticlePic() {
                let that = this
                that.initCanvas().then((data) => {
                    const ctx = data.ctx
                    const canvasInfo = data.canvas
                    const canvas = that.data.canvas
                    let pic = that.properties.imgSrc
                    if (!that.properties.imgSrc) {
                        pic = '../../images/share-article-bg.png'
                    }
                    let cW = canvasInfo.width * 0.91
                    let cH = canvasInfo.height * 0.56
                    console.log('cW', cW)
                    console.log('cH', cH)
                    that.drawArticlePic(ctx, canvas, cW, cH, pic).then(res => {
                        console.log('画入成功')
                        ctx.fillStyle = 'rgba(0,0,0,0.5)'
                        ctx.fillRect(15, 95, cW, cH)
                        ctx.fillStyle = '#333333'
                        ctx.font = '18px PingFang'
                        let title = that.properties.articleName
                        console.log('文章title', title)
                        if (!title) {
                            if (that.properties.dec.length < 10) {
                                title = that.properties.dec
                            } else {
                                title = that.properties.dec.slice(0, 10) + '...'
                            }
                        }
                        ctx.fillText(title, 15, 50)
                        ctx.fillStyle = '#aaa'
                        ctx.font = '14px PingFang'
                        ctx.fillText(`来自${that.properties.userName}的邀请`, 15, 80)
                        ctx.fillStyle = '#ffffff'
                        ctx.font = '14px PingFang'
                        ctx.fillText(`123人已浏览`, 30, 288)
                        wx.canvasToTempFilePath({
                            canvasId: 'myCanvas',
                            canvas: canvas,
                            fileType: 'png',
                            success: function (res) {
                                console.log('canvas生成图片')
                                console.log(res.tempFilePath)
                                that.setData({
                                    canvasPicPath: res.tempFilePath
                                })
                            },
                            fail: function (res) {
                                console.log('canvas生成图片失败')
                                console.log(res);
                            }
                        }, that)
                    })
                })
            },
            createProductPic() {
                let that = this
                that.initCanvas().then(data => {
                    const ctx = data.ctx
                    const canvasInfo = data.canvas
                    const canvas = that.data.canvas
                    let borderW = canvasInfo.width * 0.89
                    let borderH = canvasInfo.height * 0.77
                    let textW = canvasInfo.width * 0.81
                    this.initCanvasBg(canvas, ctx, "../../images/logo.png", 25, 25, 15, 28)
                    ctx.fillStyle = '#333333'
                    ctx.font = '12px PingFang'
                    ctx.fillText('绿植物', 49, 46)
                    ctx.fillStyle = '#8E8E8E'
                    ctx.font = '14px PingFang'
                    ctx.fillText(`${this.properties.userName}给你推荐了一个好东西`, 20, 79)
                    ctx.strokeStyle = '#EEEEEE'
                    ctx.strokeRect(20, 89, borderW, borderH)
                    that.initCanvasBg(canvas, ctx, this.properties.imgSrc, 163, 163, 84, 98)
                    ctx.fillStyle = '#CF1322'
                    ctx.font = '24px PingFang'
                    ctx.fillText('¥' + this.properties.product.vipPrice, 27, 288)
                    ctx.fillStyle = '#AAAAAA'
                    ctx.font = '14px PingFang'
                    ctx.fillText('¥' + this.properties.product.originPrice, 105, 288)
                    //原价删除线
                    ctx.beginPath()
                    ctx.lineWidth = 1;
                    ctx.strokeStyle = "#AAAAAA";
                    ctx.moveTo(103, 283)
                    ctx.lineTo(149, 283)
                    ctx.stroke()
                    ctx.fillStyle = '#333333'
                    ctx.font = '14px PingFang'
                    // ctx.fillText(that.properties.product.name, 27, 318)
                    that.drawText(ctx, that.properties.product.name, 29, 293, textW);
                    ctx.fillStyle = '#AAAAAA'
                    ctx.font = '12px PingFang'
                    // ctx.fillText(that.properties.product.fullDescription, 27, 340)
                    that.drawText(ctx, that.properties.product.fullDescription, 29, 340, textW);
                    // TODO 二维码
                    wx.canvasToTempFilePath({
                        canvasId: 'myCanvas',
                        canvas: canvas,
                        fileType: 'png',
                        success: function (res) {
                            console.log('canvas生成图片')
                            console.log(res.tempFilePath)
                            that.setData({
                                canvasPicPath: res.tempFilePath
                            })
                        },
                        fail: function (res) {
                            console.log('canvas生成图片失败')
                            console.log(res);
                        }
                    }, that)
                })
            },
            createInvitePic() {
                let that = this
                that.initCanvas().then(data => {
                    const ctx = data.ctx
                    const canvasInfo = data.canvas
                    const canvas = that.data.canvas
                    let systemWidth = app.globalData.systemWidth
                    let picWidth = systemWidth * 0.8
                    let picHeight = picWidth * 0.97
                    this.initCanvasBg(canvas, ctx, "../../images/logo.png", 25, 25, 15, 36).then((logoSuc) => {
                        console.log('logoSuc', logoSuc)
                        this.initCanvasBg(canvas, ctx, "../../images/share-img.png", picWidth, picHeight).then((res1) => {
                            console.log('res1', res1)
                            ctx.textAlign = 'left'
                            ctx.fillStyle = '#333333'
                            ctx.font = '14px PingFang'       // 文字字号:22px
                            ctx.fillText('绿植物', 49, 56)
                            ctx.textAlign = 'center'
                            ctx.fillStyle = '#E2A02B'
                            ctx.font = '20px PingFang'       // 文字字号:22px
                            ctx.fillText('邀您成为VIP会员', canvasInfo.width / 2, 137)
                            ctx.textAlign = 'center'
                            ctx.fillStyle = '#ffffff'
                            ctx.font = '14px PingFang'       // 文字字号:22px
                            ctx.fillText(`来自${this.properties.userName}的邀请`, canvasInfo.width / 2, 160)
                            this.roundRectColor(ctx, 119, 250, 92, 22, 16, canvasInfo.width)
                            ctx.textAlign = 'center'
                            ctx.fillStyle = '#E2A02B'
                            ctx.font = '20px PingFang'       // 文字字号:22px
                            ctx.fillText('最高可享3折优惠', canvasInfo.width / 2, 325)
                            wx.canvasToTempFilePath({
                                canvasId: 'myCanvas',
                                canvas: canvas,
                                fileType: 'png',
                                success: function (res) {
                                    console.log('canvas生成图片')
                                    console.log(res.tempFilePath)
                                    that.setData({
                                        canvasPicPath: res.tempFilePath
                                    })
                                },
                                fail: function (res) {
                                    console.log('canvas生成图片失败')
                                    console.log(res);
                                }
                            }, that)
                        })
                    })
                })
            },
            initCanvasBg(canvas, ctx, imgPath, w, h, x, y) {
                return new Promise((resolve, reject) => {
                    let bgPicturePath = imgPath;//图片路径不要出错
                    const img = canvas.createImage()
                    img.src = bgPicturePath
                    let oX = 15
                    let oY = 76
                    if (x) {
                        oX = x
                    }
                    if (y) {
                        oY = y
                    }
                    img.onload = () => {
                        ctx.drawImage(img, oX, oY, w, h);
                        return resolve()
                    }
                })
            },
            drawArticlePic(ctx, canvas, canvas_width, canvas_height, imgPath) {
                return new Promise((resolve, reject) => {
                    wx.getImageInfo({
                        src: imgPath,
                        success: function (res) {
    
                            let img_width = res.width,   //图片宽
                                img_height = res.height;  //图片高
                            let clip_left, clip_top, //左偏移值,上偏移值,
                                clip_width, clip_height, //截取宽度,截取高度
                                dWidth, dHeight,
                                dx, dy;
                            //  ----------------裁剪图片----------------
                            if (img_width > canvas_width && img_height > canvas_height) {    //图片宽高都大于框框
                                if (img_width / img_height > 1 || img_width / img_height === 1) {   //宽图 或正方形
                                    //将图高度自适应
                                    let factor = img_height / canvas_height
                                    clip_width = factor * canvas_width
                                    clip_height = img_height
                                    clip_top = 0
                                    clip_left = (img_width - clip_width) / 2  //clip_left 取中间值
                                } else if (img_width / img_height < 1) {   //长图
                                    let factor = img_width / canvas_width  // 图片宽/框宽= 裁剪长度/框长
                                    // img_width = canvas_width
                                    clip_width = img_width
                                    clip_height = factor * canvas_height
                                    clip_top = (img_height - clip_height) / 2
                                    clip_left = 0  //clip_left 取中间值
                                }
                                dWidth = canvas_width
                                dHeight = canvas_height
                                dx = 15
                                dy = 95
                            } else if (img_width <= canvas_width) {   //宽度小于等于框
                                dWidth = img_width
                                if (img_height >= canvas_height) {
                                    dHeight = canvas_height
                                    clip_top = (img_height - canvas_height) / 2  //裁掉多余的高
                                    dy = 0    //起始位置
                                } else {
                                    dHeight = img_height
                                    dy = (canvas_height - img_height) / 2
                                    clip_top = 0
                                }
                                dx = 0
                                clip_left = 0
    
                            } else if (img_height <= canvas_height) {  //高度小于等于框
                                dHeight = img_height
                                if (img_width >= canvas_width) {
                                    dWidth = canvas_width
                                    dx = 0
                                    clip_left = (img_width - canvas_width) / 2
                                } else {
                                    dWidth = img_width
                                    dx = (canvas_width - img_width) / 2
                                    clip_left = 0
                                }
                                dy = 0
                                clip_top = 0
                            }
                            const img = canvas.createImage()
                            img.src = imgPath
                            img.onload = (res) => {
                                console.log('img_load', res)
                                ctx.drawImage(img, clip_left, clip_top, clip_width, clip_height, dx, dy, dWidth, dHeight);
                                return resolve()
                            }
                        }
                    })
                })
            },
            roundRectColor(context, x, y, w, h, r, canvasWidth) {  //绘制圆角矩形(纯色填充)
                context.save();
                context.fillStyle = '#3B3B3B';
                context.strokeStyle = '#3B3B3B'
                context.lineJoin = 'round';  //交点设置成圆角
                context.lineWidth = r;
                context.strokeRect(x + r / 2, y + r / 2, w - r, h - r);
                context.fillRect(x + r, y + r, w - r * 2, h - r * 2);
                context.stroke();
                context.closePath();
                context.textAlign = 'center'
                context.fillStyle = '#ffffff'
                context.font = '10px PingFang'       // 文字字号:22px
                context.fillText('长按扫码加入', canvasWidth / 2, 265)
            },
            savePic() {
                let canvasPicPath = this.data.canvasPicPath
                console.log('canvasPicPath', canvasPicPath)
                wx.saveImageToPhotosAlbum({
                    filePath: canvasPicPath,
                    success(res) {
                        console.log('保存成功', res)
                        wx.showToast({
                            title: '保存成功'
                        })
                    }
                })
            },
            closeWindow: function () {
                console.log('ad')
                wx.switchTab({
                    url: 'pages/user/user'
                })
            },
            getCodeImg() {
                let link = this.properties.link
                let sceneStr = this.properties.sceneStr
                console.log('link', link)
                console.log('sceneStr', sceneStr)
                let randomStr = this.randomString(32)
                console.log('randomStr', randomStr)
                // return
                request(`/item/share/getVxQRCode?sceneStr=${sceneStr}&url=${link}`, {}).then(res => {
                    console.log('res', res)
                })
            },
            randomString(len) {
                //默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1
                let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
                let tempLen = chars.length, tempStr = '';
                for (let i = 0; i < len; ++i) {
                    tempStr += chars.charAt(Math.floor(Math.random() * tempLen));
                }
                return tempStr;
            },
            drawText(context, t, x, y, w) {    //canvas中文本换行
                let chr = t.split("");
                let temp = "";
                let row = [];
                console.log('chr', chr)
                for (let a = 0; a < chr.length; a++) {
                    if (context.measureText(temp).width < w) {
                        ;
                    } else {
                        row.push(temp);
                        temp = "";
                    }
                    temp += chr[a];
                }
    
                row.push(temp);
                for (let b = 0; b < row.length; b++) {
                    context.fillText(row[b], x, y + (b + 1) * 20);
                }
            }
        }
    })
    

    相关文章

      网友评论

        本文标题:微信分享图片组件(小程序 )

        本文链接:https://www.haomeiwen.com/subject/hmboahtx.html