html2canvas
- (一)官网下载安装
- (二)基础用法
- (三)生成海报问题
- canvas高分屏下的模糊问题
- html2canvas图片模糊问题
- canvas图片getImageData,toDataURL跨域问题
- 1) 首先,图片服务器需要配置Access-Control-Allow-Origin
- 2) canvas图片getImageData cross-origin跨域问题
- 图片加载导致海报生成不了
- ios的兼容性问题
- ios 生成图片时显示时不显的,大图几乎不显示
(一)官网下载安装
下载:https://html2canvas.hertzen.com/
vue 安装:npm install html2canvas
(二)基础用法
以vue为例子
<div @click="handlePoster()" class="btn">生成海报</div>
<div id="weeklyPoster" ref="weeklyPoster" class="poster"><h1>poster content</h1><img class="poster__logo" src="./assets/img/share-logo.png" alt="" crossOrigin="anonymous">
</div>
<div v-if="sharePoster.show" class="poster__save"><img class="poster__logo" :src="sharePoster.url" alt="">
</div>
<script>
import html2canvas from 'html2canvas';
data () {return {sharePoster: { // 海报内容show: false,url: '',height: 0,width: 0},}
}
methods: {handlePoster() {this.getWeeklyWxCode(()=>{ // 向获取二维码接口发起请求if(!this.sharePoster.url) { // 第一次生成海报// 提示海报生成中...this.$nextTick(() => {setTimeout(()=>{html2canvas(document.querySelector('#myPoster'), {scrollX: 0,scrollY: 0,allowTaint: true,useCORS: true,backgroundColor: null // 解决生成的图片有白边}).then((canvas) => {// 隐藏提示海报生成中let dataURL = canvas.toDataURL('image/jpeg');this.sharePoster.url = dataURL;this.sharePoster.show = true;this.sharePoster.height = canvas.height / 100; // 单位remthis.sharePoster.width = canvas.width / 100;});},600)});} else {this.sharePoster.show = true;}})},
}
</script>
(三)生成海报问题
canvas高分屏下的模糊问题
介绍:
开发手机 canvas 应用,在高分屏下,尤其是手持设备,如搭载高分屏的手机平板等,其显示效果会变得模糊,带给用户的体验很不好。
问题分析:
解决方案:
- 首先我们计算 webkitBackingStorePixelRatio / devicePixelRatio 的比值,这里为了方便称之为倍率 ratio
- 把 canvas 的 width 和 height 设置为 ratio 倍,这样浏览器便会按照 ratio * ratio 倍像素去渲染该 canvas
- 我们在用 CSS 把 canvas 的大小强制再调节为原始大小
- 使用 canvas 画布 context 的 scale 方法把渲染区域扩大 ratio 倍以填充屏幕 ( 后面会有解释 )
// 获取 ratio 比例
function getPixelRatio(context) {// 获取 canvas 的 backingStorePixelRatio 值var backingStore = context.backingStorePixelRatio ||context.webkitBackingStorePixelRatio ||context.mozBackingStorePixelRatio ||context.msBackingStorePixelRatio ||context.oBackingStorePixelRatio ||context.backingStorePixelRatio || 1;// 若 devicePixelRatio 不存在,默认为 1return (window.devicePixelRatio || 1) / backingStore;
}
// 调整 canvas
function adjustCanvas(canvas, context) {var ratio = getPixelRatio(context);// 获取 canvas 的原始大小var oldWidth = canvas.width;var oldHeight = canvas.height;// 按照比例放大 canvascanvas.width = oldWidth * ratio;canvas.height = oldHeight * ratio;// 用 css 将 canvas 再调整成原来大小canvas.style.width = oldWidth + 'px';canvas.style.height = oldHeight + 'px';// 按照比率把 context 再缩放回来context.scale(ratio, ratio);
}// 调用
// 此处默认你的 canvas 已经是你要的实际尺寸
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
adjustCanvas(canvas, ctx);
转载链接
html2canvas图片模糊问题
问题: html2canvas 渲染背景图片 background-image 会不清晰。
解决方法:使用 Img 标签。
canvas图片getImageData,toDataURL跨域问题
1) 首先,图片服务器需要配置Access-Control-Allow-Origin
一般团队都会有一个专门域名放置静态资源,例如腾讯是gtimg.com,百度是bdimg.com;或者很多团队使用的是腾讯云或者阿里云的服务。
而主页面所在域名往往不一样,当需要需要对canvas图片进行getImageData()或toDataURL()操作的时候,跨域问题就出来了,而且跨域问题还不止一层。
eg:PHP添加响应头信息
// *通配符表示允许任意域名
header("Access-Control-Allow-Origin: *");// 指定域名
header("Access-Control-Allow-Origin: www.zhangxinxu.com");
此时,Chrome浏览器就不会有Access-Control-Allow-Origin相关的错误信息了,但是,还会有其他的跨域错误信息。
2) canvas图片getImageData cross-origin跨域问题
对于跨域的图片,只要能够在网页中正常显示出来,就可以使用canvas的drawImage() API绘制出来。但是如果你想更进一步,通过getImageData()方法获取图片的完整的像素信息,则多半会出错。
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');var img = new Image();
img.onload = function () {context.drawImage(this, 0, 0);context.getImageData(0, 0, this.width, this.height);
};
img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';
解决方案:可以试试crossOrigin属性
1)HTML5中,有些元素提供了支持CORS(Cross-Origin Resource Sharing)(跨域资源共享)的属性,这些元素包括<img>,<video>,<script>
等。
<img src="img/png" alt="" crossorigin="anonymous">
- 增加一个img.crossOrigin = ''即可,虽然JS代码这里设置的是空字符串,实际上起作用的属性值是anonymous。
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');var img = new Image();
img.crossOrigin = '';
img.onload = function () {context.drawImage(this, 0, 0);context.getImageData(0, 0, this.width, this.height);
};
img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';
或者这样写:
drawCanvas() {if (!this.isLoadImg) {Promise.all([new Promise((resolve, reject) => {this.saveImgObj = new Image();this.saveImgObj.onload = () => {resolve();};this.saveImgObj.src = this.saveImg;this.saveImgObj.setAttribute("crossOrigin","Anonymous");}),new Promise((resolve, reject) => {this.codeImgObj = new Image();this.codeImgObj.onload = () => {resolve();};this.codeImgObj.src = this.codeImg;this.codeImgObj.setAttribute("crossOrigin","Anonymous");})]).then(() => {this.isLoadImg = true;this.drawHandler();this.posterImg = this.$refs.canvasPad.toDataURL();});} else {this.drawHandler();this.posterImg = this.$refs.canvasPad.toDataURL();}
},
drawHandler () {let canvas= this.$refs.canvasPad;let ctx= cav.getContext("2d");adjustCanvas(canvas, ctx);
}
注意:
crossOrigin兼容性:IE11+(IE Edge),Safari,Chrome,Firefox浏览器均支持,IE9和IE10会报SecurityError安全错误
图片加载导致海报生成不了
用原生的方法等待所有图片加载完成后,在执行绘制
解决方法:
function imgLoad(imgArr, ck) { let imgs = imgArr Promise.all(imgs.map((src, index) => { return new Promise((resolve, reject) => { let img = new Image() img.onload = () => { resolve(img)}img.onerror = () => { reject(src, index) } img.crossOrigin = 'anonymous' img.src = src }) })).then(arr => { ck(arr) }).catch(e => { console.log(e) })
},
ios的兼容性问题
html2canvas: "1.0.0-rc. 5"版本在运行在苹果13.4 系统 iphone7 iphonex iPhone11下都生成不了的时候,安卓没问题,微信内置浏览器不行(真机);
请看看html2canvas的版本,只有1.0.0-rc.4这个版本是可行的,如果你指定下载这个版本在package.json中看到是 ^ 1.0.0-rc.4,则不一定就是1.0.0-rc.4版本,它是指1.0.0-rc.4以上的版本,把^去掉再重新安装依赖就可以了
解决办法:
卸载npm uninstall html2canvas
重新npm i html2canvas@1.0.0-rc.4;
package.json中看到是 ^ 1.0.0-rc.4,^去掉再重新安装依赖
ios 生成图片时显示时不显的,大图几乎不显示
猜测是图片渲染的原因,为了确保能够生成图片
html2canvas库的工作原理:需要我们先提供一段DOM节点,然后它再读取并解析这一段DOM节点生成canvas对象。如果DOM节点中已经使用了<img>标签的话,它也会解析这个<img>标签的src属性,然后重新创建一个Image对象,给它添加crossOrigin="anonymous"属性后尝试以跨域的方式重新读取图片数据。需要注意的是,一般CDN上的图片都是带有缓存响应头并且会在浏览器端缓存的,而且缓存的不仅仅是图片数据,还有HTTP响应头。所以问题的根本原因我们就找到了,当html2canvas尝试以跨域的方式去读取图片数据时,它读取到的是浏览器的缓存数据,而且因为我们没有给DOM节点中的<img>标签添加crossOrigin="anonymous"属性,所以缓存数据是不带Access-Control-Allow-Origin响应头的,进而导致html2canvas库读取到的图片数据污染了生成的canvas对象,最终致使canvas导出数据报错
解决方法:
给DOM节点中的每一个<img>标签都加上crossOrigin="anonymous"属性就可以了
https://segmentfault.com/a/1190000017086056
https://blog.csdn.net/qq_41227106/article/details/106764421