Canvas与Svg互转
本文主要以两个库canvg和canvas2svg为例。尝试探寻Svg与Canvas如何实现互转,以及上述两个库的可用性问题。
简单尝试
Svg转Canvas
以一个简单的静态svg图表作为案例,采用canvg
转为canvas
结果如下图所示。其中最顶部的装饰线条不见了,具体原因我们稍后再分析。
Canvas转Svg
原本的期望为将上述转化完的canvas
在由canvas2svg
转回svg
执行报错Attempted to apply path command to node g。说明canvg
在渲染过程中可能存在某些问题导致绘图操作不能被canvas2svg
识别。接下来将以canvas2svg
的示例demo
绘制探究其绘制原理。
小结
Svg
转Canvas
直接基于canvg
来转可能会有些错误(另外,直接基于canvg
做svg
导出可能会遇到svg
中引用的class
、图片等资源不生效的问题,需要先将class
的样式解析成svg
标签中的属性,这里不做展开,详情见saveSvgAsPng)。
canvas
转svg
是通过记录canvas绘图操作,解析操作、基于svg渲染器渲染的方式来实现的。在没有canvas
的context
或者说在没有canvas
的操作记录的情况下canvas
转svg
就会退化成位图转矢量图。由于位图和矢量图存储信息方式的不同,几乎不存在不失真的情况话做转换。另外的确存在一些基于图像识别、图像追踪的位图转矢量图方案,详情见[附录](# 附录)。目前未发现基于NPM生态
的位图转矢量图方案。
Svg转Canvas具体实现
canvg
实现svg
转canvas
的方案为将svg
文件根据标签实别为一个一个单独的元素,每个的元素会有对应的渲染方法。
1 | render(ctx: RenderingContext2D) { |
例:绘制圆形
1 | export default class CircleElement extends PathElement { |
以上,从原理分析canvg
根据svg
绘制canvas
的方案为解析svg
标签及样式、根据根据解析结果调用对应的canvas
绘制对应的元素。至于上文顶部的装饰线条不见
的问题,暂时当作普通bug不做深究。
Canvas转Svg具体实现
canvas2svg
实现canvas
转svg
的方案为重写canvasAPI
在绘制canvas
的同时绘制svg
。
canvas2svg源码,示例代码:
1 | /** |
结论
实现方案
canvg
实现svg
转canvas
的方案为将svg
文件根据标签实别为一个一个单独的元素,每个的元素会有对应的渲染方法。
canvas2svg
实现canvas
转svg
的方案为重写canvasAPI
在绘制canvas
的同时绘制svg
。
本质上均为从svg标签
、canvasAPI
入手在绘制canvas
或svg
的同时记录操作,做镜像绘制。
互转可行性
由于svg
是根据标签自解释的,所以可以实现由svg文件
转png文件
这种操作。但canvas
绘制完毕之后会丢失context
即丢失操作步骤,而且基于位图的数据存储方式无法通过简单的方式直接转换为svg
。
上述两库可用性
canvg
可用,但仍有bug,canvas2svg
未做深入分析,理应可用,需基于canvas context
。另:zRender提供类似解决方案,同时对canvasAPI做了一层封装。
附录
adobe illustrator 的png to svg
演示视频。这种实现方式应该为基于图像追踪的元素实别,会将一些色值相同的块实别成具体的元素。
项目示例:canvas-svg
参考 & 引用
https://elearning.adobe.com/2020/02/convert-your-png-to-svg-images/
https://github.com/canvg/canvg
https://github.com/exupero/saveSvgAsPng
android - Bitmap to SVG Programmatically conversion - Stack Overflow
How to make or convert png to SVG file in Illustrator - Quora