zoukankan      html  css  js  c++  java
  • 小程序canvas生成海报-新旧接口


    ⭐小程序canvas生成海报


    由于 wx.createCanvasContext() 接口不再维护,因此,我们将记录新旧接口生成海报的两种方法。


    先上效果图



    目前展现的是图片等元素组成、以轮播图形式展示的页面。为提高性能,采用按下保存海报按钮,再执行canvas生成海报,保存到本地相册这样一个操作。话不多说,来干!


    ⭐旧接口 wx.createCanvasContext


    接口文档


    ① 写一个canvas对象


    <canvas class="hide" canvas-id="share" style="480px;height:854px;"></canvas>
    

    注意,这里只需给他加上 canvas-id 等下即可获取到该对象。 hide类主要是将 此画布隐掉,让他不要出现在我们的页面中。由于canvas的特殊性,我们采用最最最简单的办法,将它定位到屏幕之外即可。


    .hide{
      position:fixed;
      left:9000px;
    }
    

    ② 图片临时地址准备


    接下来,我们就可以着手准备在画布上画上我们的海报。

    首先、海报上有图片。注意,网络图片地址是不能直接被画上去的,要先转为临时地址。

    当然若是本地图片,直接采用该地址即可,无需进行临时地址获取。

    ImgUrlToTmp方法


    利用微信的 getImageInfo 接口,实现临时地址获取。


     // 获取海报图片和二维码临时地址
      ImgUrlToTmp(){
        var  that = this;
        wx.showLoading({
          title: '拼命生成中...',
        });
        wx.getImageInfo({
          src: that.data.img_url,
          success(res) {
            console.log("模板图片临时路径:" + res.path);
            that.setData({
              hbpath: res.path
            },()=>{
              console.log(that.data.code_url)
              wx.getImageInfo({
                src: that.data.code_url,
                success(res) {
                  console.log("二维码临时路径:" + res.path);
                  that.setData({
                    codepath: res.path
                  },()=>{
                    that.createNewImg()
                  })
                },
                fail(e){
                  console.log(e)
                }
              })
            })
          },
          fail(e){
            console.log(e)
          }
        })
      },
    

    ③ canvas画布


    等我们将图片地址准备好后,接下来,就正式进入我们的绘画阶段,上述可见调用了 createNewImg 方法

    sharePage

     //将canvas转换为图片保存到本地,然后将图片路径传给image图片的src
      createNewImg: function () {
        var that = this;
        // 画画布
        var context = wx.createCanvasContext("share");
        var width = that.data.widths
        var height = that.data.heights
        context.clearRect(0, 0, width , height);
        context.setFillStyle("#fff")
        context.fillRect(0, 0, width, height)
        context.save();
        // 画海报
        var path = that.data.hbpath;
        // console.log(path)
        context.drawImage(path, 0, 0, width, height * 0.8);
        // 画二维码
        var codepath = that.data.codepath;
        context.drawImage(codepath, 15, height * 0.83 , 100 , 100);
        // 画话
        var t1 = "长按扫码";
        var title = "J1ay ' blogs";
        var tishi = "每一個想要學習的念頭,那有可能是未來的你在向你求救。";
        context.setFillStyle('#333');
        context.setFontSize(13)
        context.fillText(t1, 130, height * 0.872);
        context.font = 'normal bold 13px sans-serif';
        context.fillText(title, 130, height * 0.9);
        context.setFillStyle('#999');
        context.font = 'normal 10px sans-serif';
        context.fillText(tishi, 130, height * 0.93);
        context.draw()
        setTimeout(() => {
          that.toSave(); // 需要延迟一下,等待画布绘画完毕,否则将是空白
        }, 500);
    
      },
    

    canvasToTempFilePath转换


    // 打包海报
      toSave() {
        let that = this
        wx.canvasToTempFilePath({
          x : 0,
          y: 0,
          canvasId: 'share',
           that.data.widths,
          height: that.data.heights ,
          destWidth: that.data.widths * wx.getSystemInfoSync().pixelRatio,
          destHeight: that.data.heights * wx.getSystemInfoSync().pixelRatio,
          success: function (res) {
            let canvasToTempFilePath = res.tempFilePath // 返回的图片地址保存到一个全局变量里
            that.saveShareImg(canvasToTempFilePath)
          },
            fail: function (error) {
              console.log(error)
            }
        })
      },
    

    ④ 保存到本地相册


     // 保存到系统相册
       saveShareImg: function (canvasToTempFilePath) {
          wx.getSetting({
            success(res) {
              wx.hideLoading({
                success: (res) => {},
                fail: (res)=>{
                  console.log(res)
                }
              })
              // 无权限
              if (!res.authSetting['scope.writePhotosAlbum']) {
                  wx.authorize({
                      scope: 'scope.writePhotosAlbum',
                      success() {
                        wx.saveImageToPhotosAlbum({
                          filePath: canvasToTempFilePath,
                          success() {
                              wx.showToast({
                                title: '保存成功',
                                icon: 'success',
                                duration: 2000
                              })
                          },
                          fail() {
                            wx.showToast({
                              title: '保存失败',
                              icon: 'none'
                            })
                          }
                        })
                      },
                      fail (){
                        wx.showModal({
                          title: '提示',
                          content: '请设置允许访问相册,否则将无法使用该功能',
                          showCancel: false,
                          success (res) {
                            if (res.confirm) {
                              console.log('用户点击确定')
                              wx.openSetting({
                                success (res) {
                                  // console.log(res.authSetting)
                                  wx.saveImageToPhotosAlbum({
                                    filePath: canvasToTempFilePath,
                                    success() {                      
                                        wx.showToast({
                                          title: '保存成功',
                                          icon: 'success',
                                          duration: 2000
                                        })  
                                    },
                                    fail() {
                                      wx.showToast({
                                        title: '保存失败',
                                        icon: 'error'
                                      })
                                    }
                                  })
                                },
                                fail(err){
                                  console.log(err)
                                }
                              })
                            
                            } else if (res.cancel) {
                              console.log('用户点击取消')
                            }
                          }
                        })
                      }
                    })
                  }
                  else{
                    wx.saveImageToPhotosAlbum({
                      filePath: canvasToTempFilePath,
                      success() {                      
                          wx.showToast({
                            title: '保存成功',
                            icon: 'success',
                            duration: 2000
                          })  
                      },
                      fail() {
                        wx.showToast({
                          title: '保存失败',
                          icon: 'error'
                        })
                      }
                    })
                  }
                },
                fail() {} 
            });
    
      },
    

    ⭐新接口 createSelectorQuery


    接口文档

    ① 挂载一个canvas 对象


    其实是类似的。 首先也是 挂载一个canvas 对象,注意,这里需要 指定 type 属性以及id


    <canvas type="2d" class="hide" id="share" style="480px;height:854px;"></canvas>
    

    下一步也是同旧接口,就不重复阐述了。


    画布方法改变


    重点来了!!如何利用新的接口实现画布绘画。尤其是画图片这部分,踩坑太多。最终顶着血的教训成功了。。


    代码如下:


     //将canvas转换为图片保存到本地,然后将图片路径传给image图片的src
      createNewImg: function () {
        var that = this;
        // 画画布
        wx.createSelectorQuery()
          .select('#share')
          .fields({ 
            node: true,
            size: true, })
          .exec(function (res) {
            console.log(res)
            const canvas = res[0].node
            const context = canvas.getContext('2d')
            const width = res[0].width
            const height = res[0].height
            context.restore();
            const dpr = wx.getSystemInfoSync().pixelRatio
            canvas.width = width * dpr
            canvas.height = height * dpr
            context.scale(dpr, dpr)
            context.clearRect(0, 0, width , height);
            context.fillStyle = 'white'
            context.fillRect(0, 0, width, height)
            context.save();
    
            // 画海报   为什么要这样呢?为了防止该图片还未加载出来就画了图导致画的一片空白!
            // 网上也有很有人采用 onload方法,但是在调试多次失败后,放弃,如下方案可行
            var path = that.data.hbpath;
            const hbPromise = new Promise((resolve, reject) => {
              const hb = canvas.createImage()
              hb.onload = () => {
                resolve(hb)
              }
              hb.onerror = () => {
                reject(new Error(`fail to fetch image form: ${path}`))
              }
              hb.src = path
            })
            hbPromise.then(img => {
              context.drawImage(img, 0, 0, width, height * 0.8)
            })
    
            // 画二维码
            var codepath = that.data.codepath;
            const codePromise = new Promise((resolve, reject) => {
              const code = canvas.createImage()
              code.onload = () => {
                resolve(code)
              }
              code.onerror = () => {
                reject(new Error(`fail to fetch image form: ${codepath}`))
              }
              code.src = codepath
            })
            codePromise.then(img => {
              context.drawImage(img, 15, height * 0.83 , 100 , 100)
            })
            
            // 画话
            var t1 = "长按扫码";
            var title = "J1ay ' blogs";
            var tishi = "每一個想要學習的念頭,那有可能是未來的你在向你求救。";
            context.fillStyle = '#333';
            context.fillText(t1, 130, height * 0.872);
            context.font = 'normal bold 13px sans-serif';
            context.fillText(title, 130, height * 0.9);
            context.fillStyle = '#999';
            context.font = 'normal 10px sans-serif';
            context.fillText(tishi, 130, height * 0.93);
            context.stroke();
            context.save();  
    
            setTimeout(() => {
              that.toSave(canvas);
            }, 1000);
          });
      },
    

    画布保存转为地址


    基本一致,就是多加了个 canvas 属性, 也就是将 canvas 对象传进去即可


    下方利用像素点转化,可以提升海报的高清度


     // 打包海报
      toSave(canvas) {
        console.log(canvas)
        let that = this
        wx.canvasToTempFilePath({
          x : 0,
          y: 0,
          canvasId: 'share',
          canvas: canvas,
           that.data.widths,
          height: that.data.heights ,
          destWidth: that.data.widths * wx.getSystemInfoSync().pixelRatio,
          destHeight: that.data.heights * wx.getSystemInfoSync().pixelRatio,
          success: function (res) {
            let canvasToTempFilePath = res.tempFilePath // 返回的图片地址保存到一个全局变量里
            // console.log(res)
            that.saveShareImg(canvasToTempFilePath)
          },
            fail: function (error) {
              console.log(error)
            }
        })
      },
    

    保存到相册方案也不多说啦。


    来看一下保存海报的效果图



    轮播图实现


    接下来来看一下轮播图实现, 微信开发者工具中直接有个组件 swiper


    接口文档


    这里 利用 currentIndex == index 判断当前选中项,从而改变选中的样式再加个滑动的动画即可


     <view class="main">
          <swiper class="gundong" circular bindchange="changeHB" previous-margin="100rpx" next-margin="100rpx" >
            <block wx:for="{{ shareImgs }}" wx:for-item="item" wx:key="index" >
              <swiper-item class="gundongItem" >
                <view class="Item {{currentIndex == index ? '' : 'smItem'}}">
                  <!-- 海报分享 -->
                  <view class="shareImg">
                    <image style="100%;height:100%" src="{{item.img_url}}" />
                  </view>
                  <!-- 二维码 -->
                  <view class="code">
                      <view class="img">
                        <image style=" 100rpx;height:100rpx;" class="{{currentIndex == index ? '' : 'smCode'}}" src="{{item.code_url}}" />
                      </view>
                      <view class="code_txt">
                        <text>长按扫码</text>
                        <text style="font-weight:bold">J1ay ' blogs</text>
                        <text style="font-size: 14rpx;color: #999999;line-height: 20rpx;">每一個想要學習的念頭,那有可能是未來的你在向你求救。</text>
                      </view>   
                  </view>
                </view>
              </swiper-item>
            </block>
          </swiper>   
        </view>   
    

    具体代码如下:


    github地址


    gitee地址


    图片素材来源网络,侵权删


  • 相关阅读:
    点餐网站学习(EF+MVC)SEO站内结构
    点餐网站学习(EF+MVC)EF工具,自动创建模型并建立数据库映射关系
    个性化定制cms介绍
    EasyUI Munubutton 二级菜单
    程序员也是文艺青年
    EasyUI combobox加入请选择 [.net后台代码]
    LVS配置记录
    查询MYSQL库表使用空间
    python django 数据库操作
    Nginx修改版本信息或隐藏版本号
  • 原文地址:https://www.cnblogs.com/Jlay/p/WeChat-CanvasToHaiBao.html
Copyright © 2011-2022 走看看