小程序canvas绘制 文字+图 WN EN WS ES 中心四个方位

原创 63966249 随笔 javaScript 44阅读 15 天前 举报
   前几天项目中出现多张或者一张短图or长图做成分享生成二维码和文字+图片,项目使用的是wepy框架

   // 多张图片以轮播显示
   <block wx:if="{{!onePic}}">
        <swiper class="img-body" style="height:{{bgInfo.height}}rpx" circular="true" current="{{currentIndex}}" @change='onSlideChangeEnd' indicator-dots="true" indicator-color="#fff" indicator-active-color="#7bb1c7">
            <block wx:for="{{allPicInfo.pics}}" wx:key="{{index}}">
                <swiper-item>
                    <image mode="widthFix" class="img-yoga" style="height:{{bgInfo.height}}rpx" src="{{item}}"></image>
                </swiper-item>
            </block>
        </swiper>
    </block>

    // 只有一张图时显示
    <block  wx:if="{{onePic}}"> 
        <view class="img-body">
            <image mode="widthFix" class="img-yoga" style="height:{{bgInfo.height}}px" src="{{allPicInfo.pics[0]}}"></image>
        </view>
    </block>

    // 由于canvas不能直接隐藏,所以外面套了一层css
    <view style='width:0px;height:0px;overflow:hidden;'>
        <canvas canvas-id='share' style="width: 760px;height: {{bgInfo.height}}px;"></canvas>
    </view>

    // 点击保存
    <button class="enjoy-btn " @tap="saveImage">保存图片,分享朋友圈</button>

    // 数据格式
    data = {
        onePic: true,
        allPicInfo: {
          pics: ["http://cdn.50yoga.cn/pics/source/yogaactivity/detail-short.jpg", "http://cdn.50yoga.cn/pics/source/yogaactivity/share_common.png"],
          listInfo: [
              {
                  type: "text", value: "我是中心",
                  fontStyle: {size: "30", color: "#b84343"},
                  position: {gravity: "CENTER", geometry: "10+10"}
              },
              {
                  type: "text", value: "我是西北方",
                  fontStyle: {size: "30", color: "#b84343"},
                  position: {gravity: "WN", geometry: "10+10"}
              },
              {
                  type: "text", value: "我是东北方",
                  fontStyle: {size: "30", color: "#666"},
                  position: {gravity: "EN", geometry: "10+10"}
              },
              {
                  type: "text", value: "我是西南方",
                  fontStyle: {size: "30", color: "#F77A1D"},
                  position: {gravity: "WS", geometry: "10+10"}
              },
              {
                  type: "text", value: "我是东南方",
                  fontStyle: {size: "30", color: "#7bb1c7"},
                  position: {gravity: "ES", geometry: "10+10"}
              },

              {
                  type: "image", value: "http://cdn.50yoga.cn/pics/source/yogaactivity/tao1.png",
                  position: {gravity: "CENTER", geometry: "37x34+20+20"}
              },
              {
                  type: "image", value: "http://cdn.50yoga.cn/pics/source/yogaactivity/turn-btn.png",
                  position: {gravity: "WN", geometry: "74x75+30+30"}
              },
              {
                  type: "image", value: "http://cdn.50yoga.cn/pics/source/yogaactivity/tao1.png",
                  position: {gravity: "EN", geometry: "37x34+30+30"}
              },
              {
                  type: "image", value: "http://cdn.50yoga.cn/pics/source/yogaactivity/tao1.png",
                  position: {gravity: "WS", geometry: "37x34+30+30"}
              },
              {
                  type: "image", value: "http://cdn.50yoga.cn/pics/source/yogaactivity/tao1.png",
                  position: {gravity: "ES", geometry: "37x34+30+30"}
              }
          ]
      },
    }

    // 绘制方法
    method = {
      // 监听轮播tu索引位置
      onSlideChangeEnd: async e => {
          this.currentIndex = e.detail.current
          this.bgInfo = await wepy.getImageInfo({src: this.allPicInfo.pics[this.currentIndex]})
          this.$apply()
      },
     saveImage: async e => {
        try {
            await this.drawSharePic()
            this.$apply()
        } catch (err) {
            this.$parent.errorToast(err.message)
        }
    },

      // 开始绘制的方法
async drawSharePic() {
    try {
        wepy.showLoading({title: '正在绘制图片...'})
        const canvasCtx = wepy.createCanvasContext('share')
        let bgInfo = await wepy.getImageInfo({src: this.allPicInfo.pics[this.currentIndex]})
        canvasCtx.drawImage(bgInfo.path, 0, 0, bgInfo.width, bgInfo.height)

        for (const iterator of this.allPicInfo.listInfo) {
            let geometry = iterator.position.geometry.split('+')
            let picinfo = geometry[0].split('x')
            let picinfo_w = picinfo[0]
            let picinfo_h = picinfo[1]

            let pic_x = geometry[1] // 边距x
            let pic_y = geometry[2] // 边距y

            switch (iterator.type) {
                case 'image':
                    let nowpic = await wepy.getImageInfo({src: iterator.value})
                    switch (iterator.position.gravity) {
                        case 'CENTER':
                            // 背景宽*0.5-绘制宽*0.5  背景高*0.5-绘制高*0.5  
                            canvasCtx.drawImage(iterator.value, bgInfo.width*0.5-picinfo_w*0.5, bgInfo.height*0.5-picinfo_h*0.5, picinfo_w, picinfo_h)
                            break
                        case 'WN':
                            // 0+no_pic_x, 0+no_pic_y  NO是  0, 0
                            canvasCtx.drawImage(iterator.value, 0+pic_x, 0+pic_y, picinfo_w, picinfo_h)
                            break
                        case 'EN':
                            // 0+no_pic_x, 0+no_pic_y  NE是  背景宽 — 绘制图宽, 0
                            canvasCtx.drawImage(iterator.value, bgInfo.width-picinfo_w-pic_x, 0+pic_y, picinfo_w, picinfo_h)
                            break
                        case 'ES':
                            // 0+no_pic_x, 0+no_pic_y  SE是  背景宽 — 绘制图宽, 背景高 — 绘制图高
                            canvasCtx.drawImage(iterator.value, bgInfo.width-picinfo_w-pic_x, bgInfo.height-picinfo_h-pic_y, picinfo_w, picinfo_h)
                            break
                        case 'WS':
                            // 0+no_pic_x, 0+no_pic_y  SE是  0, 背景高 — 绘制图高
                            canvasCtx.drawImage(iterator.value, 0+pic_x, bgInfo.height-picinfo_h-pic_y, picinfo_w, picinfo_h)
                            break
                    }
                    break
                case 'text':
                    canvasCtx.setFontSize(iterator.fontStyle.size)
                    canvasCtx.setFillStyle(`${iterator.fontStyle.color}`)
                    // let text_w = canvasCtx.measureText(iterator.value)
                    switch (iterator.position.gravity) {
                        case 'CENTER':
                            canvasCtx.setTextAlign('center')
                            canvasCtx.fillText(iterator.value, bgInfo.width*0.5, bgInfo.height*0.5+iterator.fontStyle.size/2)
                            break
                        case 'WN':
                            canvasCtx.setTextAlign('left')
                            canvasCtx.fillText(iterator.value, 0, iterator.fontStyle.size)
                            break
                        case 'EN':
                            canvasCtx.setTextAlign('right')
                            canvasCtx.fillText(iterator.value, bgInfo.width, iterator.fontStyle.size)
                            break
                        case 'ES':
                            canvasCtx.setTextAlign('right')
                            canvasCtx.fillText(iterator.value, bgInfo.width, bgInfo.height*0.99)
                            break
                        case 'WS':
                            canvasCtx.setTextAlign('left')
                            canvasCtx.fillText(iterator.value, 0, bgInfo.height*0.99)
                            break
                    }
                    break

            }

        }

        // 绘制二维码(圆形)
        let qrW = bgInfo.width * 0.15 
        let qrX = bgInfo.width *0.8
        let qrY =  bgInfo.height - bgInfo.width * 0.2
        canvasCtx.save()

        canvasCtx.beginPath() // 开始绘制
        // 画圆   前两个参数确定了圆心 (x,y) 坐标  第三个参数是圆的半径  四参数是绘图方向  默认是false,即顺时针
        canvasCtx.arc(qrW / 2 + qrX, qrW / 2 + qrY, qrW / 2, 0, Math.PI * 2, false)

        canvasCtx.fillRect()
        canvasCtx.clip() // 画好了圆 剪切  原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内 这也是我们要save上下文的原因
        const {path: qrcode} = await wepy.getImageInfo({src: this.qrcode})
        canvasCtx.drawImage(qrcode, qrX, qrY, qrW, qrW)
        canvasCtx.restore() // 恢复之前保存的绘图上下文状态,继续绘制
        canvasCtx.draw(true)
        canvasCtx.closePath()

        // 绘制之后加一个延时去生成图片,如果直接生成可能没有绘制完成,导出图片会有问题。
        setTimeout(async () => {
            let ret = await wepy.canvasToTempFilePath({
                fileType:'jpg',
                width: this.bgInfo.width,
                // destHeight: (winW * 0.5),
                height: this.bgInfo.height,
                canvasId: 'share'
            })
            this.tempFilePath = ret.tempFilePath
            if (!ret.tempFilePath) {
                throw new Error('图片绘制中,请稍后再试')
            }
            await wepy.saveImageToPhotosAlbum({
                filePath: this.tempFilePath
            })
            this.$parent.errorModal('保存成功,快把图片分享到朋友圈吧~')
        }, 500)

        wepy.hideLoading()
    } catch (err) {
        console.log('err',err)
        wepy.hideLoading()
        if (err.errMsg != undefined) {
            this.$parent.errorToast(err.errMsg)
        } else {
            this.$parent.errorToast(err.message)
        }
    }
}
    }
评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复