具体场景:

原逻辑:纭毅YMS加注站点信息中有下载二维码的功能,点击后弹出弹窗,原功能下载二维码仅仅下载二维码图片
优化后:业务提出优化需要连同油站以及站点编码一起下载

html2canvas 插件

1. 作用:html2canvas 的作用就是允许让我们直接在用户浏览器上拍摄网页或其部分的“截图”

2. 原理:它的屏幕截图是基于 DOM 的,因此可能不会 100%精确到真实的表示,因为它不会生成实际的屏幕截图,而是基于页面上可用的信息构建屏幕截图。

3. 常见的应用场景就是我们可以使用它在 H5 端生成分享图。

4. 属性

参数名称类型默认值描述
allowTaintbooleanfalseWhether to allow cross-origin images to taint the canvas—允许跨域
backgroundstring#fffCanvas background color, if none is specified in DOM. Set undefined for transparent—canvas的背景颜色,如果没有设定默认透明
heightbooleannullDefine the heigt of the canvas in pixels. If null, renders with full height of the window.—canvas高度设定
letterRenderingbooleanfalseWhether to render each letter seperately. Necessary if letter-spacing is used.—在设置了字间距的时候有用
loggingbooleanfalseWhether to log events in the console.—在console.log()中输出信息
proxystringundefinedUrl to the proxy which is to be used for loading cross-origin images. If left empty, cross-origin images won’t be loaded.—代理地址
taintTestbooleantrueWhether to test each image if it taints the canvas before drawing them—是否在渲染前测试图片
timeoutnumber0Timeout for loading images, in milliseconds. Setting it to 0 will result in no timeout.—图片加载延迟,默认延迟为0,单位毫秒
widthnumbernullDefine the width of the canvas in pixels. If null, renders with full width of the window.—canvas宽度
useCORSbooleanfalseWhether to attempt to load cross-origin images as CORS served, before reverting back to proxy–这个我也不知道是干嘛的

5. 应用

// html
<el-dialog :title="$lang('站点二维码')" :width="'500px'" :visible.sync="QrcodeVisible" @close="close" class="qr-dialog" :close-on-click-modal="false">
   <div ref="qrCode" id="image" style="width:470px;height:340px;box-sizing: border-box;">
      <div class="center">{{stationForm.siteName}}{{stationForm.typeName}}</div>
      <img style="width: 300px;margin-left: 80px;" id="imageSelfPd" crossorigin=“anonymous” alt="站点二维码">
      <div class="center"><span  v-if="stationForm.type !== '3'">{{stationForm.code}}</span><span v-if="stationForm.type === '3'" >{{stationForm.equipId}}</span></div>
   </div>
   <div slot="footer" class="center">
      <el-button @click="close">{{$lang('取消')}}</el-button>
      <el-button type="primary" @click="downLoadQrCode" :loading="keyLoading">{{$lang('下载二维码')}}</el-button>
   </div>
</el-dialog>

5.1 先下载插件

npm i html2canvas -S

5.2 引入html2canvas

import html2canvas from 'html2canvas';

5.3 图片资源为本地可以直接应用;
图片是网络资源,存在canvas画布话的时候会发生空白,解决办法如下:
(1) 将图片放置服务器,通过nginx进行代理资源,前端访问图片便不涉及到跨域问题(后端配置)

(2) 使用base64图片传输,base64太大不便于传输的话,让后端写一个接口,上传图片base64数据返回图片地址(代码入下)

(3) 属性配置:1. img标签的crossorigin=“anonymous” 2. useCORS: true

getBase64(imgUrl) { // 将图片转为base64格式
      window.URL = window.URL || window.webkitURL;
      var xhr = new XMLHttpRequest();
      xhr.open('get', imgUrl, true);
      // 至关重要
      xhr.responseType = 'blob';
      xhr.onload = function () {
        if (this.status === 200) {
          // 得到一个blob对象
          var blob = this.response;
          console.log('blob', blob)
          // 至关重要
          const oFileReader = new FileReader();
          oFileReader.onloadend = function (e) {
            // 此处拿到的已经是 base64的图片了
            const base64 = e.target.result;
            const imgD = document.getElementById('imageSelfPd')
            imgD.src = base64 // 将图片的src属性赋值
            // console.log(imgD,'imgDimgDimgD');
          };
          oFileReader.readAsDataURL(blob);
        }
      }
      xhr.send();
    },

5.4 使用html2canvas插件画出dom节点,且下载。

 downLoadQrCode() {
      if (this.QrcodeUrl) {
        const dom = document.querySelector('#image').getBoundingClientRect()
        const config = {
          allowTaint: false, // 开启跨域
          useCORS: true, // 图片跨域
          width: dom.offsetWidth,
          height: dom.offsetHeight
          scrollX: 0,
          scrollY: 0,
          x: 0,
          y: 0
        }
        html2canvas(document.querySelector('#image'), config).then(canvas => {
          var mA = document.createElement('a');
          mA.href = canvas.toDataURL()
          mA.setAttribute('download', '图片canvas.png');
          mA.click();
        })
      }
    },

5.5 常见的还有滚动条截图不全问题:

window.pageYoffset = 0;

document.documentElement.scrollTop = 0;

document.body.scrollTop = 0;

这种方法本地下载没有问题,构建后有问题,下载的图片是okb的。目前不知道原因。后面使用domtoimage解决了该问题。
移动端使用:

let html2canvas = null;

export default {
  beforeMount() {
    import('html2canvas').then((plugin) => {
      html2canvas = plugin.default;
    });
  },
  methods: {
    // 获取分享图片 base64
    getShareImgBase64() {
      return new Promise((resolve) => {
        setTimeout(() => {
          // #capture 就是我们要获取截图对应的 DOM 元素选择器
          html2canvas(document.querySelector('#capture'), {
            useCORS: true, // 【重要】开启跨域配置
            scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2,
            allowTaint: true, // 允许跨域图片
          }).then((canvas) => {
            const imgData = canvas.toDataURL('image/jpeg', 1.0);
            resolve(imgData);
          });
        }, 300); // 这里加上 300ms 的延迟是为了让 DOM 元素完全渲染完成后再进行图片的生成
      });
    },
  },
};

domtoimage 插件

1. 方法:

  1. domtoimage.toPng(…);将节点转化为png格式的图片
  2. domtoimage.toJpeg(…);将节点转化为jpg格式的图片
  3. domtoimage.toSvg(…);将节点转化为svg格式的图片,生成的图片的格式都是base64格式
  4. domtoimage.toBlob(…);将节点转化为二进制格式,这个可以直接将图片下载
  5. domtoimage.toPixelData(…);获取原始像素值,以Uint8Array 数组的形式返回,每4个数组元素表示一个像素点,即rgba值。这个方法也是挺实用的,可以用于WebGL中编写着色器颜色。

2. 属性:

filter : 过滤器节点中默写不需要的节点;
bgcolor : 图片背景颜色;
height, width : 图片宽高;
style :传入节点的样式,可以是任何有效的样式;
quality : 图片的质量,也就是清晰度;一个介于 0 和 1 之间的数字,表示 JPEG 图像的图像质量(例如 0.92 => 92%)。默认为 1.0 (100%)
cacheBust : 将时间戳加入到图片的url中,相当于添加新的图片;
imagePlaceholder : 图片生成失败时,在图片上面的提示,相当于img标签的alt;
使用:

<!-- 站点二维码 -->
<el-dialog :title="$lang('站点二维码')" :width="'500px'" :visible.sync="QrcodeVisible" @close="close" class="qr-dialog" :close-on-click-modal="false">
   <div ref="qrCode" id="image" style="width:480px;height:380px;box-sizing: border-box;padding-top:20px;">
     <div class="center">{{stationForm.siteName}}{{stationForm.typeName}}</div>
     <img style="display:block;width: 300px;margin: 0 auto;" id="imageSelfPd" :src="QrcodeUrl" crossOrigin="anonymous" alt="站点二维码">
     <div class="center"><span  v-if="stationForm.type !== '3'">{{stationForm.code}}</span><span v-if="stationForm.type === '3'" >{{stationForm.equipId}}</span></div>
   </div>
   <div slot="footer" class="center">
     <el-button @click="close">{{$lang('取消')}}</el-button>
     <el-button type="primary" @click="downLoadQrCode" :loading="keyLoading">{{$lang('下载二维码')}}</el-button>
    </div>
</el-dialog>

3. 应用

  1. 下载domtoimage 插件
npm install dom-to-image -S
  1. 引入插件
import domtoimage from 'dom-to-image';
  1. 方法使用
downLoadQrCode() {
  if (this.QrcodeUrl) {
     var node = document.getElementById('image');
     domtoimage.toPng(node, { bgcolor: '#fff' }).then(dataUrl => {
       var mA = document.createElement('a');
       mA.href = dataUrl
       mA.setAttribute('download', '图片canvas.png');
       mA.click();
     }).catch(error => {
       console.error('oops, something went wrong!', error);
     });
    }
  },

可能存在的问题:

使用toPng,结果:图片较为模糊;ios部分背景图片无法显示

import domtoimg from 'dom-to-image';

const node = document.getElementById('root')
try {
  let dataUrl = await domtoimg.toPng(node)
  // share to app
}catch (){}

使用toJpeg,结果:同toPng
使用toSvg,结果:客户端都显示正常,但友盟不支持svg格式图片分享,将svg转化为png格式后部分背景图片仍然显示异常

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐