某些场景需要通过 canvas 绘制一些图片, 其中包含一些文字、可能的二维码等等。 然后实现时如果完全手动的去定位元素在 canvas 中的位置,结果就会产生大量不能复用和难以维护的代码。(使用背景图可能会模糊,可以使用img,结合定位)

html2canvas

1.安装

npm install --save html2canvas

  也可以直接官网下载js文件 然后引用

  2. 使用

//按自己的文件位置引用
import html2canvas from "../../utils/html2canvas.js";

canvasfun() {
      //把你需要转为图片的标签放在一个根元素内 直接获取根元素
      let save2 = document.getElementsByClassName('list')[0];
      html2canvas(save2,{
        useCORS: true  //很重要支持跨域图片,否则需要自己将线上图片转为本地图片(转base64)
      }).then((canvas) => {
        //利用a标签实现下载(浏览器环境)
        let url = canvas.toDataURL("image/png");
        let aLink = document.createElement("a");
        aLink.style.display = "none";
        url.replace(/^data:image\/png/, "data:application/octet-stream")
        aLink.href = url;
        aLink.download = "截图.png";
        document.body.appendChild(aLink);
        aLink.click();
        document.body.removeChild(aLink);
        console.log(canvas)

//***********************************************************
        //小程序webview页面
        let url = canvas.toDataURL("image/png");
        url.replace(/^data:image\/png/, "data:application/octet-stream")
        console.log(canvas)
        wx.miniProgram.postMessage({
          data: { 
            base64: url
          }
        });
        //触发 wx.miniProgram.postMessage的bindmessage
        wx.miniProgram.redirectTo({
          url: '此页面路径',
        })



      });
    },

 3.属性

属性名默认值描述
allowTaintfalse是否允许跨域图像。会污染画布,导致无法使用canvas.toDataURL 方法
backgroundColor#ffffff画布背景色(如果未在DOM中指定)。设置null为透明
canvasnull现有canvas元素用作绘图的基础

foreignObjectRendering

false如果浏览器支持,是否使用ForeignObject渲染
imageTimeout15000加载图像的超时时间(以毫秒为单位)。设置0为禁用超时。
ignoreElements(element) => false谓词功能,可从渲染中删除匹配的元素
loggingtrue启用日志以进行调试
onclonenull克隆文档以进行渲染时调用的回调函数可用于修改将要渲染的内容,而不会影响原始源文档。
proxynull代理将用于加载跨域图像的网址。如果保留为空,则不会加载跨域图像。
removeContainertrue是否清除html2canvas临时创建的克隆DOM元素
scale

window.devicePixelRatio

用于渲染的比例。默认为浏览器设备像素比率。(图片清晰控制)
useCORSfalse是否尝试使用CORS从服务器加载图像
widthElement widthcanvas的宽度
heightElement heightcanvas的高度
xElement x-offset裁剪画布X坐标
yElement y-offset裁剪画布y坐标
scrollXElement scrollX渲染元素时要使用的x滚动位置(例如,如果Element使用position: fixed)
scrollYElement scrollY呈现元素时要使用的y-scroll位置(例如,如果Element使用position: fixed)
windowWidthWindow.innerWidth渲染时使用的窗口宽度Element,这可能会影响媒体查询之类的内容
windowHeightWindow.innerHeight

渲染时要使用的窗口高度Element,这可能会影响媒体查询之类的内容

如果应用在小程序webview中,需要将base64传到小程序端通过 wx.miniProgram.postMessage(小程序后退、组件销毁、分享、复制链接才会触发)传,然后再web-view标签上绑定bindmessage="callback",通过wx.miniProgram.redirectTo重新打开此页面触发(看着最合适的方式)

//接上面webview的代码
<web-view src="{{srchtml}}"  bindmessage="callback"/>




callback(e){
      var data = e.detail.data
      console.log(data)

      let img =  e.detail.data[data.length-1].base64
      let imgname = new Date().getTime()

      wx.getFileSystemManager().writeFile({
      filePath: wx.env.USER_DATA_PATH + '/'+ imgname + '.png',  //这里先把文件写到临时目录里. 
      data: img.slice(22), //****************
      encoding: 'base64',
      success: res => {
        console.log('success')
        wx.saveImageToPhotosAlbum({
          filePath: wx.env.USER_DATA_PATH + '/'+ imgname + '.png', //这是把临时文件 保存到 相册
          success: res => {
            wx.showToast({ title: '保存成功!' })
          },
          fail: error => { console.log(error) }
        })
      },
      fail: error => { console.log(error) }
    })
    },

wxml2canvas

有的github上的文件有点问题

这里拷js文件,把demo下载下来跑一遍

分析一下

 drawCanvas() {
    wx.showLoading()
    const that = this
    const query = wx.createSelectorQuery().in(this);
    query.select('#wrapper').fields({ // 选择需要生成canvas的范围
        size: true,
        scrollOffset: true
    }, data => {
        let width = data.width;
        let height = data.height;
        that.setData({
            width,
            height
        })
        setTimeout(() => {
            that.startDraw()
        }, 1500);
   }).exec()
},
startDraw() {
    let that = this
     
    // 创建wxml2canvas对象
    let drawMyImage = new wxml2canvas({
      element: 'canvas-map', // canvas的id,
      obj: that, // 传入当前组件的this
      width: that.data.width * 2,
      height: that.data.height * 2,
      background: '#141415', // 生成图片的背景色
      progress(percent) { // 进度
        // console.log(percent);
      },
      finish(url) { // 生成的图片
        wx.hideLoading()
        console.log(url)
        that.savePoster(url)
      },
      error(res) { // 失败原因
        console.log(res);
        wx.hideLoading()
      }
    }, this);
    let data = {
        // 获取wxml数据
        list: [{
            type: 'wxml',
            class: '.draw .draw1',  // draw要绘制的wxml元素根类名, draw1单个元素的类名(所有所有所有要绘制的单个元素都要添加该类名)
            limit: '.draw', // 要绘制的wxml元素根根根类名
            x: 0,
            y: 0
        }]
    }
    // 绘制canvas
    
    drawMyImage.draw(data, this)
},
savePoster() {
    const that = this
    wx.saveImageToPhotosAlbum({
        filePath: that.data.imgUrl,
        success: function() {
            wx.showToast({
                title: '保存成功',
                icon: 'none',
                duration: 1500
            });
        },
        fail(err) {
          if (err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || err.errMsg === "saveImageToPhotosAlbum:fail auth deny" || err.errMsg === "saveImageToPhotosAlbum:fail authorize no response") {
            wx.showModal({
              title: '提示',
              content: '需要您授权保存相册',
              showCancel: false,
              success: modalSuccess => {
                wx.openSetting({
                  success(settingdata) {
                    if (settingdata.authSetting['scope.writePhotosAlbum']) {
                        wx.saveImageToPhotosAlbum({
                            filePath: that.data.imgUrl,
                            success: function () {
                              wx.showToast({
                                title: '保存成功',
                                icon: 'success',
                                duration: 2000
                              })
                            },
                        })
                    } else {
                        wx.showToast({
                            title: '授权失败,请稍后重新获取',
                            icon: 'none',
                            duration: 1500
                        });
                    }
                  }
                })
              }
            })
          }
        }
      })
  },

还有 wxml-to-canvas(小程序官方) 等插件

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐