添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

html2canvas样式丢失

为了弄清楚 html2canvas 在处理 svg 时样式丢失的问题,先需要弄清楚 html2canvas 的处理机制。
####html2canvas 实现机制####
html2canvas 的实现机制是通过遍历分析指定节点以及子节点的样式,然后通过 canvas API 在 canvas 中绘制出来,具体如下:
为了避免对当前页面的影响,将当前页面的所有节点拷贝到一个 iframe 中
从 ownerDocument 开始递归,拷贝节点 如果节点是 script,则忽略,如果节点命中了 ignoreElements 则忽略。记录指定节点对应的拷贝节点,动态创建 iframe,将拷贝的节点写入到 iframe 中。
####调用 onclone 方法####
通过内部的 parseTree 方法遍历拷贝解析节点及子节点,生成对应的 container,如:ImageElementContainer,SVGElementContainer,CanvasElementContainer 等。最后通过 CanvasRenderer 或 ForeignObjectRenderer 类来渲染这些节点。从上面的流程中可以知道,svg 节点是通过 SVGElementContainer 来处理的。通过代码发现 svg 的处理非常简单粗暴:

export class SVGElementContainer extend elementContainer {
svg: string;
intrinsicWidth: number;
intrinsicHeight: number;
constructor(img: SVGSVGElement) {
super(img);
const s = new XMLSerializer();
this.svg = ;
this.intrinsicWidth = img.width.baseVal.value;
this.intrinsicHeight = img.height.baseVal.value;
CacheStorage.getInstance().addImage(this.svg);

也就是说,对于 svg,是直接将 svg 序列化,然后转成图片来处理的。这样一来,定义在外部的样式序列化时无法携带,自然也就丢失data:image/svg+xml,${encodeURIComponent(s.serializeToString(img))} ####修复 svg 的样式问题####
知道了 svg 是序列化后转成图片来处理的,只要保证在序列化时携带上样式,生成的图片后就没有问题了。样式直接定义在节点上。最简单的办法就是,将原本定义在外层的样式写在 svg 节点上,DEMO:svg text 内容 这样处理虽然能解决问题,但比较麻烦,尤其是 svg 是放在数据库/文件等地方存储时。动态将外层定义的样式重新赋值到节点上除了手工把样式写在 svg 节点上外,也可以在生成截图前解析节点的样式,然后把样式重新设置到节点上,这样 svg 序列化时携带这些信息,生成的图片就会有这些样式了。

  •