小程序 canvas 绘制图片

canvas绘制图片

      • 绘制图片的问题
      • html

绘制图片的问题

1、canvas不能绘制网络图片需要转换成本地图片进行使用
2、多张图片绘制需要调用 img.onload,进行嵌套绘制

html

<view class="overlay-box">
  <view style="margin-top: 20px;"></view>
  <scroll-view class="overlay-wrap" scroll-y="true" style="visibility:{{!canvasonload?'visible':'hidden'}}">
        <canvas id="{{canvasId}}" type="2d" class="share__canvas1" style="width: 100%; height:964rpx;"></canvas>
        <view class="savebtn" bindtap="saveiImg">
            <van-button type="danger" size='large'  round='{{true}}'> 保存</van-button>
        </view>
  </scroll-view>
</view>
    data: {
        canvasId: 'canvasID',
        canvasonload: false, //加载状态
        bg1: config.host + 'volunteer_bg.png',//背景的网络图片
        cachet1: config.host + 'cachet.png',//公章的网络图片
        title_bg1:config.host + 'volunteer_title.png',//标题的网络图片
        bg2: '',
        cachet2: '',
        title_bg2:'',
        codeImg: '',
    },
    onLoad(options) {

        // 请求小程序二维码的接口,加载完毕在执行后续操作
        my.post(my.urls.Code,true).then(res => {
            if (res.code == 200) {
                this.getCanvas([this.data.bg1, this.data.cachet1,this.data.title_bg1,res.msg], 0)
            }
        })
    },
    getCanvas(urlArr, _type) {
        let _this = this
        wx.getImageInfo({
            src: urlArr[_type],
            success: function (res) {
                //res.path是网络图片的本地地址
                if (_type === 0) {
                    _this.setData({
                        bg2: res.path,
                    })
                    _this.getCanvas(urlArr, 1)
                } else if(_type === 1){
                    _this.setData({ 
                        cachet2: res.path,
                    })
                    _this.getCanvas(urlArr, 2)
                }else if(_type === 2){
                    _this.setData({ 
                        title_bg2: res.path,
                    })
                    _this.getCanvas(urlArr, 3)
                   
                }else if(_type === 3){
                    _this.setData({
                        codeImg: res.path,
                    })
                    var query = wx.createSelectorQuery().in(_this);
                    query.select('#' + _this.data.canvasId).fields({
                        node: true,
                        size: true,
                    }).exec(_this.drawImg.bind(_this))
                }

            }
        })
    },
    // 画图
    drawImg(res) {
        const that = this
        const width = res[0].width
        const height = res[0].height
        const canvas = res[0].node
        const ctx = canvas.getContext('2d')
        const dpr = wx.getSystemInfoSync().pixelRatio
        canvas.width = width * dpr
        canvas.height = height * dpr
        ctx.scale(dpr, dpr)
        // 比例 canvas / 设计搞宽度
        const proportion = width / 335
        // 绘制图片
        const img = canvas.createImage();
        const img2 = canvas.createImage();
        const img3 = canvas.createImage();
        const img4 = canvas.createImage();
        // 背景图片
        img.src = this.data.bg2
      
        img.onload = () => {
            ctx.drawImage(img, 0, 0, proportion * 341, proportion * 500)
            // 标题图片
            img2.src = that.data.title_bg2
            img2.onload = () => {
                ctx.drawImage(img2, (width/2)-50, proportion * 40, 100, 100)
                // 绘制公章图片
                img3.src = that.data.cachet2
                img3.onload = () => {
                    ctx.drawImage(img3, proportion * 194, proportion * 365, proportion*100, proportion*100)
                    // 二维码图片
                    img4.src = that.data.codeImg
                    img4.onload = () => {
                        ctx.drawImage(img4, proportion * 23, proportion * 405, proportion *60, proportion *60)
                    }
                }
            }

            
            ctx.fillStyle = "#C84141";
            ctx.font = proportion * 16 + "px  PingFang SC-Medium, PingFang SC";
            drawText(ctx, '小老弟', proportion * 30, proportion * 191, proportion * 290, proportion * 290)
            // 证书内容
            ctx.fillStyle = "#202020";
            ctx.font = proportion * 15 + "px  PingFang SC-Medium, PingFang SC";
            drawText(ctx, '感谢您抽身百忙之中,参加我们的志愿者服务活动。为表达我们由衷的敬意,也为了鼓励更多人士加入我们,特为您颁发此证书,以兹纪念,谢谢。', proportion * 30, proportion * 240, proportion * 284, proportion * 20)

            // 查看二维码
            ctx.fillStyle = "#9D9D9D";
            ctx.font = proportion * 12 + "px  PingFang SC-Medium, PingFang SC";
            drawText(ctx, '长按二维码', proportion * 88, proportion * 430, proportion * 290, proportion * 290)
            ctx.font = proportion * 12 + "px  PingFang SC-Medium, PingFang SC";
            drawText(ctx, '查看更多公益项目', proportion * 88, proportion * 450, proportion * 290, proportion * 290)

            //基金会
            ctx.fillStyle = "#1E2235";
            ctx.font = proportion * 14 + "px  PingFang SC-Medium, PingFang SC";
            drawText(ctx, '基金会',  proportion * 180, proportion * 420, proportion * 284, proportion * 20)
            
            //日期
            ctx.font = proportion * 14 + "px  PingFang SC-Medium, PingFang SC";
            drawText(ctx, '2022-12-16',  proportion * 200, proportion * 450, proportion * 280, proportion * 20)
            wx.hideLoading({
                complete: that.setData({
                    canvasonload: false
                })
            })

        }
        //文本换行 参数:1、canvas对象,2、文本 3、距离左侧的距离 4、距离顶部的距离 5、6、文本的宽度
        function drawText(ctx, str, leftWidth, initHeight, canvasWidth, titleHeight, bool) {
            var lineWidth = 0;
            var lastSubStrIndex = 0; //每次开始截取的字符串的索引
            for (let i = 0; i < str.length; i++) {
                lineWidth += ctx.measureText(str[i]).width;
                if (lineWidth > canvasWidth) {
                    ctx.fillText(str.substring(lastSubStrIndex, i), leftWidth, initHeight); //绘制截取部分
                    // 行高
                    initHeight += proportion * 30; //16为字体的高度
                    lineWidth = 0;
                    lastSubStrIndex = i;
                    titleHeight += proportion * 18;
                }
                if (i == str.length - 1) { //绘制剩余部分
                    ctx.fillText(str.substring(lastSubStrIndex, i + 1), leftWidth, initHeight);
                }
            }
            // 标题border-bottom 线距顶部距离
            titleHeight = titleHeight + proportion * 10;
            return titleHeight
        }
        myCanvas = canvas
    },
    
    // 保存图片
    saveiImg() {
        wx.showLoading({
            title: '图片保存中...',
        })
        wx.canvasToTempFilePath({ // 将canvas生成图片
            canvas: myCanvas,
            success: (res) => {
                wx.saveImageToPhotosAlbum({ //保存图片到相册
                    filePath: res.tempFilePath,
                    success: function (res) {
                        wx.showToast({
                            icon: 'success',
                            title: "保存图片保存成功"
                        })
                    },
                    fail: (err) => {
                        if (err.errMsg) { //重新授权弹框确认
                            wx.showModal({
                                title: '提示',
                                content: '您好,请先授权,在保存此图片。',
                                showCancel: false,
                                success(res) {
                                    if (res.confirm) { //重新授权弹框用户点击了确定
                                        wx.openSetting({ //进入小程序授权设置页面
                                            success(settingdata) {
                                                if (settingdata.authSetting['scope.writePhotosAlbum']) { //用户打开了保存图片授权开关
                                                    wx.saveImageToPhotosAlbum({
                                                        filePath: respath,
                                                        success: function (data) {
                                                            wx.showToast({
                                                                title: '保存成功',
                                                                icon: 'success',
                                                                duration: 2000
                                                            })
                                                        },
                                                    })
                                                } else { //用户未打开保存图片到相册的授权开关
                                                    wx.showModal({
                                                        title: '温馨提示',
                                                        content: '授权失败,请稍后重新获取',
                                                        showCancel: false,
                                                    })
                                                }
                                            }
                                        })
                                    }
                                }
                            })
                        }
                        wx.showToast({
                            icon: 'error',
                            title: "保存图片保存失败"
                        })
                    }
                })
            },
            fail: (err) => {
                console.log(err);
            },
            complete: () => {
                wx.hideLoading()
            }
        })
    },

你可能感兴趣的:(小程序,前端,javascript)