Html2Canvas踩坑笔记

简介

Html2canvas主要是将Dom 节点转换成canvas工具库。利用canvas 转换为DataURL 的接口可以实现纯客户端的图片生成以及下载。适用场景主要是一些商品和活动之类的分享海报。
github 仓库
官方文档

1. 优劣

1.1 优势

  1. 生成图片的过程在客户端,高并发的场景下减少服务器的压力。
  2. 方案简单开发成本低,

1.2 劣势

客户端的设备各式各样,各种浏览器内核,包括APP 内打开会有很多的兼容性问题。
Html

  1. Canvas 的兼容问题
  2. DataUrl的兼容问题

CSS 不支持一下属性
在这里插入图片描述

再者Html2canvas 还是预览版,不是很稳定,官方文档上不推荐使用在生产环境
不推荐在生产版本使用

2 . 常见问题

2.1 IOS 13.4 之后无法使用问题

   1.0.0 rc 5 版本有问题,需要降级使用1.0.0 rc4
   [github issues](https://github.com/niklasvh/html2canvas/issues/2188)

2.2 滚动顶部空白问题

两个解决方案,我使用的第一种,第二种需要滚动页面,体验不好。

  1. 通过配置设置scroll 位置
{
    scrollX: 0,
    scrollY: -window.scrollY
}
  1. 生成图片时,记录下位置,将屏幕滚动到顶部,生成后并恢复到原来位置
window.scrollTo(0, 0)

还有其他方案为实践,比如说降级到1.0.0-alpha.12 ,可能会引起其他bug 不推荐

github issues

2.3 图片跨域问题

移动端一般只用开启配置项的useCORS(库会给image添加crossOrigin: Anonymous),即可解决

{
  useCORS: true,
}

需要兼容低版本的浏览器的 使用 proxy 配置

2.4 图片加载不全问题

在生成canvas 的时候,html2canvas 会重新加载当前页面的所有静态资源。在网络不好的情况下很容易出现网络图片无法正常生成,在IOS上表现最为明显。原因在于canvas 绘图时,HTTP请求过多,图片未加载完毕。
解决方案: 网络图片转换为Blob本地数据。相当于先把图片下载下来。转换完成后再生成canvas

// 返回图片Blob地址
const toBlobURL = (function () {
  const urlMap = {};
  // @param {string} url 传入图片资源地址
  return function (url: string) {
    // 过滤重复值
    if (urlMap[url]) return Promise.resolve(urlMap[url]);

    return new Promise((resolve, reject) => {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const img = document.createElement('img');
      img.setAttribute('crossOrigin', 'Anonymous');
      img.src = url;
      img.onload = () => {
        canvas.width = img.width;
        canvas.height = img.height;
        ctx?.drawImage(img, 0, 0);
        // 关键
        canvas.toBlob((blob) => {
          const blobURL = URL.createObjectURL(blob);
          resolve(blobURL);
        });
      };
      img.onerror = (e) => {
        reject(e);
      };
    });
  };
})();

// 批量处理
function convertToBlobImage(targetNode: Element | NodeList, timeout: number) {
  if (!targetNode) return Promise.resolve();

  let nodeList:
    | Element[]
    | NodeList
    | HTMLCollectionOf<HTMLImageElement> = targetNode;

  if (targetNode instanceof Element) {
    if (targetNode.tagName.toLowerCase() === 'img') {
      nodeList = [targetNode];
    } else {
      nodeList = targetNode.getElementsByTagName('img');
    }
  } else if (!(nodeList instanceof Array) && !(nodeList instanceof NodeList)) {
    throw new Error('[convertToBlobImage] 必须是Element或NodeList类型');
  }

  if (nodeList.length === 0) return Promise.resolve();

  // 仅考虑<img>
  return new Promise((resolve) => {
    let resolved = false;

    // 超时处理
    if (timeout) {
      setTimeout(() => {
        if (!resolved) resolve();
        resolved = true;
      }, timeout);
    }

    let count = 0;

    // 逐一替换<img>资源地址
    for (let i = 0, len = nodeList.length; i < len; ++i) {
      const v: any = nodeList[i];
      let p = Promise.resolve();

      if (v.tagName.toLowerCase() === 'img') {
        p = toBlobURL(v.src).then((blob) => {
          v.src = blob;
        });
      }

      p.finally(() => {
        if (++count === nodeList.length && !resolved) resolve();
      });
    }
  });
}

export default convertToBlobImage;

2.5 图片下载问题

最简单的方式就是拿到html2canvas的返回结果canvas 转换为DataURL

const imgData = canvas.toDataURL('image/jpeg')

2.5.1 a 标签下载

可以动态的设置文件名称。
base64长度过长会引起下载失败(解决方案是转为blob 对象,待验证)
根据之前的经验blob 也会存在一些兼容问题。
第一是 大文件的blob,这个可以忽略(500M - 800M) 图片来源filesave.js
在这里插入图片描述

第二个 就是Html API 的一些兼容问题

2.5.2 长按下载

imgData 的 赋值给img标签的src 属性,下方添加长按保存图片文案提示
默认名称为下载.jpg

下载兼容性测试

浏览器平台长按a标签
UCIOSx
UC安卓x
360 极速IOSxx
360安卓x
QQ浏览器IOSx
QQ浏览器安卓x
SafraiIOS
夸克IOS-
夸克安卓-
搜狗IOSx
搜狗安卓x
ChromeIOS
Chrome安卓
samsung安卓

参考

高质量前端快照方案:来自页面的「自拍」

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JavaScript HTML renderer The script allows you to take "screenshots" of webpages or parts of it, directly on the users browser. The screenshot is based on the DOM and as such may not be 100% accurate to the real representation as it does not make an actual screenshot, but builds the screenshot based on the information available on the page. How does it work? The script renders the current page as a canvas image, by reading the DOM and the different styles applied to the elements. It does not require any rendering from the server, as the whole image is created on the clients browser. However, as it is heavily dependent on the browser, this library is not suitable to be used in nodejs. It doesn't magically circumvent any browser content policy restrictions either, so rendering cross-origin content will require a proxy to get the content to the same origin. The script is still in a very experimental state, so I don't recommend using it in a production environment nor start building applications with it yet, as there will be still major changes made. Browser compatibility The script should work fine on the following browsers: Firefox 3.5+ Google Chrome Opera 12+ IE9+ Safari 6+ As each CSS property needs to be manually built to be supported, there are a number of properties that are not yet supported. Usage Note! These instructions are for using the current dev version of 0.5, for the latest release version (0.4.1), checkout the old readme. To render an element with html2canvas, simply call: html2canvas(element[, options]); The function returns a Promise containing the <canvas> element. Simply add a promise fullfillment handler to the promise using then: html2canvas(document.body).then(function(canvas) { document.body.appendChild(canvas); }); Building The library uses grunt for building. Alternatively, you can download the latest build from here. Clone git repository with submodules: $ git clone --recursive git://github.com/niklasvh/html2canvas.git Install Grunt and uglifyjs: $ npm install -g grunt-cli uglify-js Run the full build process (including lint, qunit and webdriver tests): $ grunt Skip lint and tests and simply build from source: $ grunt build Running tests The library has two sets of tests. The first set is a number of qunit tests that check that different values parsed by browsers are correctly converted in html2canvas. To run these tests with grunt you'll need phantomjs. The other set of tests run Firefox, Chrome and Internet Explorer with webdriver. The selenium standalone server (runs on Java) is required for these tests and can be downloaded from here. They capture an actual screenshot from the test pages and compare the image to the screenshot created by html2canvas and calculate the percentage differences. These tests generally aren't expected to provide 100% matches, but while commiting changes, these should generally not go decrease from the baseline values. Start by downloading the dependencies: $ npm install Run qunit tests: $ grunt test Examples For more information and examples, please visit the homepage or try the test console. Contributing If you wish to contribute to the project, please send the pull requests to the develop branch. Before submitting any changes, try and test that the changes work with all the support browsers. If some CSS property isn't supported or is incomplete, please create appropriate tests for it as well before submitting any code changes.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值