以下基于v1.0.0-rc5
版本(此版本已经解决了一些bug)
为了做一个类似分享海报的demo,方便起见(不会canvas)使用html2canvas将html转为canvas再分享为图片。但是在实际使用中发现了h2c的一些问题,记录在下。
demo说明
此demo基于angular,通过填入数据,再将数据显示在对应位置,在需要时通过点击下载卡片
或者其他形式将图片下载到本地。
项目地址:GitHub/JikeCard
演示链接:Jellow Card 服务器原因,响应较慢
更多说明见项目README
图片效果如下:
导出的图片以下将说明遇到的问题。
box-shadow样式导出后缺失
在v1.0.0-rc2
后h2c加入了导出box-shadow的功能,但是当你同时对一个元素设置了border-radius
和box-shadow
后,导出会出现异常(及样式丢失)
例如:
.avatar {
display: flex;
width: 14%;
border-radius: 50%;
border: solid 4px white;
box-shadow: 0 0.2px 0.5px gainsboro;
}
其中的box-shadow: 0 0.2px 0.5px gainsboro;
在导出结果中丢失。
在html2canvas项目的pull1848下,你可以找到由wangkaiwen提出的解决办法。
该方案对源码(node_modules/html2canvas/dist/html2canvas.js
)做出如下修改(将对应源码做替换):
在line 6500 附近:
CanvasRenderer.prototype.mask = function (paths) {
var x=this.options.x,y=this.options.y;
this.ctx.beginPath();
this.ctx.moveTo(x, y);
this.ctx.lineTo(this.canvas.width+x, y);
this.ctx.lineTo(this.canvas.width+x, this.canvas.height+y);
this.ctx.lineTo(x, this.canvas.height+y);
this.ctx.lineTo(x, y);
this.formatPath(paths.slice(0).reverse());
this.ctx.closePath();
};
在line 6800附近:
_this.ctx.shadowOffsetX = shadow.offsetX.number + maskOffset * window.devicePixelRatio;
图片跨域问题
以下示例来自 html2canvas示例网页
HTML:
<div id="capture" style="padding: 10px; background: #f5da55">
<h4 style="color: #000; ">Hello world!</h4>
</div>
JavaScript:
html2canvas(document.querySelector("#capture")).then(canvas => {
document.body.appendChild(canvas)
});
在js中使useCROS=true
即可,如:
html2canvas(document.querySelector("#capture"),{
useCROS: true
}).then(canvas => {
document.body.appendChild(canvas)
});
导出图片清晰度不高
在v1.0.01-rc5
版本中,不需要通过设置宽度、高度、scale来提高清晰度,使用上面的代码已经可以得到足够清晰的图片。
导出图片高度异常
此异常有两种情况:
- div高度过高时生成图片出现白边
- div在页面上方引起的上半部分丢失
div高度过高时生成图片出现白边
js加入如下参数:
html2canvas(document.querySelector("#capture"),{
useCROS: true,
height: document.getElementById('capture').offsetHeight
}).then(canvas => {
document.body.appendChild(canvas)
});
div在页面上方引起的上半部分丢失
曲线救国,在保存图片前将页面回复到最顶部,即:
document.documentElement.scrollTop = 0;
document.body.scrollTop = 0;
html2canvas(document.querySelector("#capture"),{
useCROS: true,
height: document.getElementById('capture').offsetHeight
}).then(canvas => {
document.body.appendChild(canvas)
});
可能存在更优解。
导出svg(二维码)错误
使用qrcode.js
(实际安装的依赖为angularx-qrcode(1.7.0-beta5)
)生成二维码,因为图片格式清晰度不高,所以采用svg形式。但是svg导出会出现问题(具体说明问题视你的svg图案,总之就是会出现异常)。
异常由svg内未经设置的width引起(应该是,所以下面的解决方案不一定适合非二维码的svg),因此通过设置元素宽度来消除异常:
/**
* 设置元素宽度(消除异常)
*/
function setSvgElementsWidth() {
const svgElements = document.body.querySelectorAll('svg');
svgElements.forEach(item => {
item.setAttribute('width', item.getBoundingClientRect().width.toString());
});
}
在生成二维码前调用此方法即可消除异常。
在此值得一提的是,angularx-qrcode(1.7.0-b5)插件[usesvg]="true"
时直接用html2canvas导出会引发错误,错误原因由旧版本不兼容es2015引起。插件2.x版本虽修复此问题,但因2.x版本去除了svg选项,导出二维码清晰度不高,故将 tsconfig.json
的target 改为 es5。
另一点是,svg生成二维码后,二维码的点之间有间隙(像素视觉差异),可以在GitHub/JikeCard中的qrcode
组件找到对应的css和utils/QRCode.ts
找到css异常的解决方法。
网友评论