Creator + SVG 解析渲染扩展组件

0x00 About && 关于

SVG 全称是 Scalable Vector Graphics。中文是 可缩放的矢量图形

SVG 是用 XML 来描述二维图形的语言。

SVG 图形对象可被组化、样式化、变形和重组,包括图象嵌套、变形处理、剪辑路径、Alpha蒙板、滤镜特效和模板对象。

SVG 的矢量特性可以让移动设备清楚地浏览 SVG 图像信息,在放大后不会出现模糊的情况。


大约在7年前,我第一次接触 svg,出于好奇,就用 cocos2d-html5 v2.x 写了一个 SVG 解析渲染 的演示程序。当然其中的实现功能非常的有限而且问题也很多,比如只支持画轮廓,无法填充图形,大部分的命令没有解析。

cocos2d_html5_svg

然后在5年前,用 cocos2d-js v3.9把程序重写了一下,把渲染方式升级到了 v3 的风格然后加入了颜色填充的功能。

cocos2d_js_svg

最近在论坛搜索一些关于 cc.Graphics 帖子的时候,偶然看到有一些便朋友提到了 svg 这个东西在 creator 中的使用可能性。

于是就有了下面的这个,大幅度升级的 creator 版的 svg 扩展。

PS: 插件已经通过审核,下载地址戳这里

0x01 Pitfalls && 坑

用一句话来描述一下这个组件的作用: 读取 svg 文件,解析,使用 creator 的方式 进行渲染

看描述可能会觉得,这不是什么特别复杂的事情,但是如果有尝试做过相同事情的朋友,可能才会了解,这里面的 实在是太多了。

svg 标签属性

svg 在对 path 之类路径的表述上非常的自由,一个 M 表达式的参数可能有各种奇怪的写法:

M 1.23 -4.56
M 1.23-4.56
M1.23 -4.56
M 1.23,-4.56
M1.23,-4.56
M 1,23 -4,56
M1,23.-4,56
M 1.2.3.4.5.6
M 1e23-4e56

svg 分组结构

svg 在整体结构上也是非常的自由,比如一个 path 标签,可能被使用在各种层级中:

svg["g"]["g"][index]["path"]["d"]
svg["g"]["g"]["path"][index]["d"]
svg["g"]["g"]["path"]["d"]
svg["g"]["path"][index]["d"]

svg 填充规则

另一个相当麻烦的东西,就是 winding rule (缠绕规则),用来控制 svg 里面的 fill rule (填充规则)。比如两个包含关系的矩形,顶点描述顺序的不同,填充的结果也不同。

cc.Graphics

上面这些坑都是来自 svg 一方的,这里的问题是来自 creator 内部的。

cc.Graphicscreator 里的绘图组件。但是其提供的绘图接口还是非常有限的。此外,cc.Graphics 在对一些曲线绘制的图形填充的时候,也有 bug

取决于 svg 对象的复杂程度,cc.Graphics. 可能会被很重度的使用,但是这在 native 平台会有报错出现。不过这个问题就在最近,已经被官方解决了: 解决方案请看这里


上面列出的是一些主要的坑,还有无数的小坑,无数的细节调试,这里推荐一个很棒的在线 svg 路径调试工具 svg-path-editor ,在调试解析器的时候,有很多细节,都是对着这个编辑器同步单步调试来寻找问题的并解决的。

要解决这些大的问题,而且还要尽量的不修改引擎,同时支持 Web Android iOS 平台,还是很有挑战性的。

0x02 Demo && 演示程序

在细说组件的功能之前,先来直接看下演示程序,看下目前这个组件已经 实现了哪些功能能做这些什么

下面的部分 gif 画质略低,帧数略低,实际效果是没有任何图像模糊和卡顿的。

Shapes

基础的测试用例,这里绘制的是 svg 所有支持的基础图像类型。

Paths

基础的测试用例,这里绘制的图形都是由 svg 支持的一个重要标签 path 所内置的命令组成的。

FillRule

进阶的测试用例,演示了组件所支持的 svg 内置的 填充规则 的实际渲染结果,包括了 非零填充奇偶填充。演示的例子包括了 自相交多边形带洞的图形不同路径走向的图形

Icons

进阶用例,所有图标都来自开源网站 game-icons.net,用于进一步验证解析库的正确性。

Cat

压力测试用例,加载解析大小达到 12M 笔画数达到 29000+ 的小猫图片,主要用于测试极大文件情况下,解析库是否仍然能够完成任务以及渲染是否会出现报错的情况。(该例子不建议在手机上运行,毕竟太暴力了,但是我已经跑过,验证过渲染结果的正确性了)

Scalability

实用测试用例,svg 最多的用处之一,就是无论怎么放大,都不会像 Sprite 一样变得模糊不清。

Hanzi

实用测试用例,演示了如何通过组件提供的一些内置属性,实现汉字书写的过程渲染演示。

Tiger

实用测试用例,演示了如何通过组件提供的一些内置属性,实现复杂图像的绘制过程渲染演示。

Yoga

实用测试用例,演示了如何通过组件提供的一些内置属性,实现图像的触摸填色功能演示。

Toucan

实用测试用例,演示了如何通过组件配合 cc.RenderTexture && FBO 实现 cc.Graphics纹理化 并对其使用 shader 特效的演示。

0x03 Data Structure && 数据格式

这里介绍一下,目前解析后的 svg 对象对应的数据结构。

ssr.SVG.Data.Root

对应整个 svg 文件的根节点,目前简单的保存了 svg 文件相关的一些全局信息。

// 对应 svg 中的 width 属性
width: cc.Float
// 对应 svg 中的 height 属性
height: cc.Float
// 对应 svg 中的 x 属性
x: cc.Float
// 对应 svg 中的 y 属性
y: cc.Float
// 对应 svg 中的 viewBox 属性
viewBox: cc.rect
// 对应 svg 中的 version 属性
version: cc.String
// svg 解析后的命令数组,详见下面的 Command 解释
commandArray: [ssr.SVG.Data.Command]

ssr.SVG.Data.Command

对应 svg 中的基础图形命令,路径命令,如 <rect> <circle> <path> 标签的内容信息。

// 命令类型枚举,详见下面的说明
type: ssr.SVG.Const
// 对应 svg 中的 fill
fillColor: cc.Color
// 对应 svg 中的 stroke
strokeColor: cc.Color
// 对应 svg 中的 stroke-width
strokeWidth: cc.Float
// svg 中命令的原生参数,解析后的字典结果,对于不同类型,其内容会不同,先下面的说明
params: cc.Object
// 当前 command 下包含的 area 数组,详见下一节的 Area 解释
areaArray: [ssr.SVG.Data.Area]
// 当前 command 下进行 FillRule 检测后,Tess2 三角化后的结果
areaTess2: [cc.Vec2]
// 当前 command 下包含的 area 数量
areaCount: cc.Integer
// 当前 command 下包含的 stroke 总数量
strokeCount: cc.Integer
// 当前命令是否已经完成渲染,前提是其包含的所有区域已经完成渲染
isFinished: cc.Boolean

/**************/
ssr.SVG.Const
// 路径命令类型
PATH
	// params 内容为 <path d=""> d 属性中的原始字符串
	params: cc.String
// 椭圆形状命令类型
ELLIPSE
	// params 内容为 {cx cy rx ry}
	params: cc.Object
// 折线命令类型
POLYLINE
	// params 内容为 <polyline points=""> points 属性中的原始字符串
	params: cc.Object
// 多边形命令类型
POLYGON
	// params 内容为 <polygon points=""> points 属性中的原始字符串
	params: cc.Object
// 直线令类型
LINE
	// params 内容为 {x1 y1 x2 y2}
	params: cc.Object
// 圆形命令类型
CIRCLE
	// params 内容为 {cx cy r}
	params: cc.Object
// 矩形命令类型
RECT
	// params 内容为 {x y width height}
	params: cc.Object

ssr.SVG.Data.Area

上述的 Command 对象,在 path 的情况下,通常会有一个 PathCommand 中包含多个闭合或非闭合区域的情况,这里的 Area 就是对应这些数据的。

// 当前 Area 下包含的 Stroke 数组,详见下一节的 Stroke 解释
strokeArray: [ssr.SVG.Data.Stroke]
// 当前 Area 下包含的 Stroke 总数量
strokeCount: cc.Integer
// 当前 Area 所表示的多边形(闭合或不闭合)的顶点数组,用于做触摸检测用
polygonArray: [cc.Vec2]
// 当前区域是否已经完成渲染,前提是其包含的所有笔画命令已经完成渲染
isFinished: cc.Boolean
// 当前区域是否已经完成填色,主要用于填色模式
isPainted: cc.Boolean

ssr.SVG.Data.Stroke

上述的每个 Area 对象,都会包含至少一条完整的绘图指令,在 path 的情况下,一个 Area 会包含 M, c, t, z 等这些命令,每一个命令都会被作为一个 Stroke 对象存储,这也是渲染的最小单元。

// 命令类型枚举,PATH 以外命令的值同 Command.Type,Path 命令会被更细的分解,详见下面的说明
commandType: ssr.SVG.Const
// 渲染类型枚举,详见下面的说明
renderType: ssr.SVG.Const
// 渲染用数据,根据渲染类型的不同,会被以不同的方式渲染
dataArray: [cc.Vec2]
// 记录原生的指令,对于 path 中常见的连写命令,这里记录的是拆分后的结果
instrunction: cc.String
// 对每一个指令,解析后的字典结果,对于不同类型,其内容会不同,先下面的说明
params = cc.Object
// 当前笔画是否已经被渲染过
isFinished: cc.Boolean

/**************/
// 对应 path 中的 z/Z 指令
PATH_END
// 对应 path 中的 m/M 指令
PATH_MOVE
// 对应 path 中的 l/L 指令
PATH_LINE
// 对应 path 中的 c/C 指令
PATH_CURVE_C
// 对应 path 中的 s/S 指令
PATH_CURVE_S
// 对应 path 中的 q/Q 指令
PATH_CURVE_Q
// 对应 path 中的 t/T 指令
PATH_CURVE_T
// 对应 path 中的 a/A 指令
PATH_CURVE_A

// 对应 cc.Graphics.moveTo 函数
RENDER_MOVE
// 非闭合图形用,不会调用 fill,可能调用 stroke
RENDER_END
// 对应 cc.Graphics.lineTo 函数
RENDER_LINE
// 对应 cc.Graphics.moveTo / lineTo 函数
RENDER_POLYLINE
// 对应 cc.Graphics.close 函数 可能调用 stroke / fill 函数
RENDER_CLOSE

0x04 Features && 功能

File && 文件

svgxml 格式的文件,而在 creator 中,json 是比较推荐的使用格式,这里为了运行效率,并没有在组件中进行 xmljson 的格式转换,或是 xml 格式的解析,而是通过直接读取转换好的 json 格式文件来直接进行解析。

xmljson 的工具,网上有很多,这里随便贴一个 XML to JSON and JSON to XML converter online

转换好的 json 文件,就可以直接在 creator 插件中使用了。

Parser && 解析器

svg 中的标签,属性是非常多的,目前版本所支持的一些标签和属性主要有下面这些。

Shapes && 图形

基本图形标签,和他们的一些属性。

可以看到,基本图形和属性都是支持的,目前没有实现的是:

  • 一个不太常用的 <rect> 中的圆角矩形属性
  • <text> 标签
// 矩形
[OK] <rect>
	[OK] x
  [OK] y
  [OK] width
  [OK] height
  [NG] rx
  [NG] ry
// 圆形
[OK] <circle>
  [OK] x
  [OK] y
  [OK] r
// 椭圆
[OK] <ellipse>
  [OK] cx
  [OK] cy
  [OK] rx
  [OK] ry
// 直线
[OK] <line>
  [OK] x1
  [OK] y1
  [OK] x2
  [OK] y2
// 折线
[OK] <polyline>
  [OK] points
// 多边形
[OK] <polygon>
  [OK] points
// 文字
[NG] text

Path && 路径

路径命令主要有如下这些,目前已经全部支持。

// 移动命令
[OK]    M    moveto                              (x y)+
// 闭合路径命令
[OK]    Z    closepath                           (none)
// 直线命令
[OK]    L    lineto                              (x y)+
// 平行线命令
[OK]    H    horizontal lineto                   x+
// 垂直线命令
[OK]    V    vertical lineto                     y+
// 三次贝塞尔曲线命令
[OK]    C    curveto                             (x1 y1 x2 y2 x y)+
// 简版三次贝塞尔曲线命令
[OK]    S    smooth curveto                      (x2 y2 x y)+
// 二次贝塞尔曲线命令
[OK]    Q    Quadratic Bézier curveto            (x1 y1 x y)+
// 简版二次贝塞尔曲线命令
[OK]    T    smooth quadratic Bézier curveto     (x y)+
// 弧形曲线命令
[OK]    A    elliptical arc                      (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+

虽然 cc.Graphics 中提供了一些看似对应的接口,如 bezierCurveToquadraticCurveToarc 等接口,但是在实际测试后发现,使用这些接口连续绘图,形成闭合图形后填充,会发生问题,比如对凹凸、自交多边形,带孔图形的支持。

因此,解析库采用了将所有命令 Segmentation 线段化的统一处理。组件中的 ssr.SVG.Util.Polyline 就是负责处理这个的:

Polyline.FromCubicBezier(px, py, cx1, cy1, cx2, cy2, x, y, segments)
Polyline.FromQuadBezier(px, py, cx1, cy1, x, y, segments)
Polyline.FromEllipticArc(x1, y1, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x2, y2, segments)
Polyline.FromEllipse(cx, cy, rx, ry, segments)
Polyline.FromLine(x1, y1, x2, y2, segments)
Polyline.FromCircle(cx, cy, r, segments)

这些解析后的数据,就被作为 ssr.SVG.Data.Stroke 中的核心数据,用作后续对的渲染。所有命令的解析由 ssr.SVG.Util.Path 负责:

Path.M(index, lastM, cmd, terms, configuration, outArray)
Path.L(index, cmd, terms, configuration, outArray)
Path.H(index, cmd, terms, configuration, outArray)
Path.V(index, cmd, terms, configuration, outArray)
Path.C(index, cmd, terms, configuration, outArray)
Path.S(index, cmd, terms, configuration, outArray)
Path.Q(index, cmd, terms, configuration, outArray)
Path.T(index, cmd, terms, configuration, outArray)
Path.A(index, cmd, terms, configuration, outArray)
Path.Z(index, lastM, cmd, terms, configuration, outArray)
Path.Ellipse(term, configuration, outArray)
Path.Circle(term, configuration, outArray)
Path.Line(term, configuration, outArray)
Path.Polyline(term, configuration, outArray)
Path.Polygon(term, configuration, outArray)
Path.Rect(term, configuration, outArray)

Properties && 属性

目前支持的属性不多,但是已经涵盖了一些和渲染相关的主流属性:

// 填充色
[OK]	fill
// 画线颜色
[OK]	stroke
// 画线宽度
[OK]	stroke-width
// 填充透明度
[OK]	fill-opacity
// 填充规则
[OK]	fill-rule

Global && 全局

目前支持的属性不多,但是已经涵盖了一些和渲染相关的主流属性:

[OK]	width
[OK]	height
[OK]	x
[OK]	y
[OK]	version
[OK]	viewBox
// 分组标签
[OK]	g
[NG]	clip-path
[NG]	mask
[NG] 	transform

其中,width / height / x / y 有解析但没有实际的使用,解析器通过动态计算图像的实际大小,然后将其反映到 cc.Nodewidth / height / x / y ,使得渲染后的对象的所见大小和属性值完全吻合。

transform 属性暂时也没有解析,不过通过测试已经知道,cc.Node 中的所有形变属性,都能够准确的反映在组件上。

Editor Support && 编辑器支持

Editor 中支持所见即所得,大部分的属性,都可以在编辑器中实时调试,查看效果。

0x05 API && 函数接口

这里列出的,是 ssr.SVG.Component 中的一些主要属性和接口。

// SSRSVGComponent Properties
// svg json 文件
svgJSONFile: cc.JsonAsset
// 是否开启 强制分段 功能,主要用于一些绘图过程演示,可以展现出平滑的绘图效果
segmentationOn: cc.Boolean
// 是否开启 触摸 功能,主要用于配合填色功能使用
enableTouch: cc.Boolean
// 是否开启 填色 功能,需要 enableTouch 开启
enablePaintMode: cc.Boolean
// 是否开启 合并划线 功能,对于不需要演示绘图渲染过程的使用场景,开启后可以大大减少 cc.Graphics 渲染调用次数,大幅提高性能
enableMergeStroke: cc.Boolean
// 是否开启 FillRule检测 功能,开启后,会进行强制的填充规则检测,并对区域三角化,可以先在编辑器中尝试关闭,查看效果,有需要再打开
enableFillRuleCheck: cc.Boolean
// 是否开启 全局填充色 功能,开启后无视 svg 中实际的填充色
enableGlobalFillColor: cc.Boolean
// 全局填充色 配合 enableGlobalFillColor 使用
globalFillColor: cc.Color
// 是否开启 全局划线色 功能,开启后无视 svg 中实际的划线色
enableGlobalStrokeColor: cc.Boolean
// 全局划线色 配合 enableGlobalStrokeColor 使用
globalStrokeColor: cc.Color
// 是否开启 全局划线宽度 功能,开启后无视 svg 中实际的划线宽度,可以配合填色功能使用,强制画出图像的轮廓
enableGlobalStrokeWidth: cc.Boolean
// 全局划线色 配合 enableGlobalStrokeWidth 使用
globalStrokeWidth: cc.Float
// 设置曲线的分段数,数字越大曲线越平滑但越耗性能,需要设置合适的值
segments: cc.Float
// 是否需要对绘制的图像进行水平翻转
flipX: cc.Boolean
// 是否需要对绘制的图像进行垂直翻转 (svg 中坐标系统 Y 轴向下)
flipY: cc.Boolean
// 获取当前加载,解析后的 svg 对象
getSVGObject: ssr.SVG.Data.Root

// 单步绘图时使用,获取当前绘制的命令索引(下标从 1 开始)
getCommandIndex: cc.Integer
// 单步绘图时使用,获取解析后的 svg 图像的命令数量
getCommandCount: cc.Integer
// 单步绘图时使用,获取当前绘制的命令对象
getCommandObject: ssr.SVG.Data.Command

// 单步绘图时使用,获取当前绘制命令下的,区域的索引(下标从 1 开始)
getAreaIndex: cc.Integer
// 单步绘图时使用,获取当前绘制的命令下,包含区域的数量
getAreaCount: cc.Integer
// 单步绘图时使用,获取当前绘制的区域对象
getAreaObject: ssr.SVG.Data.Area

// 单步绘图时使用,获取当前绘制的命令+区域下,笔画的索引(下标从 1 开始)
getStrokeIndex: cc.Integer
// 单步绘图时使用,获取当前绘制的区域下,包含笔画的数量
getStrokeCount: cc.Integer
// 单步绘图时使用,获取当前绘制的笔画对象
getStrokeObject: ssr.SVG.Data.Stroke

// 根据给定的触摸点坐标 (getLocation),返回所有包含触摸点的区域对象
getTouchedAreaArray(cc.Vec2 pos): [ssr.SVG.Data.Area]
// 根据给定的触摸点坐标 (getLocation),填充触摸的区域对象
fillTouchedArea(cc.Vec2 pos)

// 重置组件对象,清空已绘制区域,已加载数据
reset
// 重置当前已绘制状态,清空已绘制区域,保留加载数据,保留设置数据
resetRender
// 内部调用 resetRender 后调用 drawAll,主要用于修改解析相关配置后,重新解析并渲染
redrawAll
// 内部循环调用 draw 直至渲染结束
drawAll
// 更定索引值,绘制指定明命令
drawCommand(int commandIndex)
// 内部循环调用 draw 直至渲染结束
drawArea(int commandIndex, int areaIndex)
// 内部循环调用 draw 直至渲染结束
drawStroke(int commandIndex, int areaIndex, int strokeIndex)
// 分部调用绘图,会自动计算,以 stroke 为单位,进行一次绘图渲染,如果图像渲染结束,会返回 false,否则返回 true
draw: cc.Boolean

0x06 How to Use && 使用方法

插件的使用方式,十分的简单:

  1. 新建一个 cc.Node

  2. 挂载 ssr.SVG.Component 插件

  3. json 格式的 svg 拖放到 svgJsonFile 属性上即可

  4. 如果需要在原生环境进行复杂图形渲染的,记得要自己合并一下官方最近修复的这个 bug

  5. 如果需要进行 FillRule 检测的,需要将 ssr/svg/util/tess2.js 文件作为插件导入

接下来就只需要修改一些属性配置,在编辑器中查看效果即可。

0x07 Platform Support && 平台支持

目前测试过的平台,设备,相关信息。

从测试结果来看,所有功能在所有测试的平台和设备上都可以正常运行 (但是记得在 native 上运行,要自己合并一下上面提到的,官方修复的 cc.Graphics bug )。

引擎版本

Creator v2.4.3

测试设备

Model.1

2018 产

MacBook Pro (13-inch)

macOS Catalina 10.15.6

Google Chrome 版本 85.0.4183.83(正式版本)(64 位)

Firefox 80.0.1 (64 位)

Safari 版本13.1.2 (15609.3.5.1.3)

Model.2

2014 产

iPhone 6 11.3.1 MG4H27P/A

Model.3

2017 产

iPhone X 13.3.1 MQA92CH/A

Model.4

2017 产

Huawei Honor 7X BND-AL10 Android 9.0 EMUI 9.1.0

Model.5

2018 产

Huawei Mate20 Pro LYA-AL00 Android 10.1 EMUI v10.1.0

发布平台 / 测试结果

所有测试用例,在所有平台上,设备上,所有的测试用例都可以正常的运行,并且运行,渲染结果完全一致。

即使在几百元的安卓手机上,目前相对复杂的测试用例(比如老虎的用例),则能有着不错的表现。在开启 mergeStroke 以后,内存方面有了很大的提高。

下图为 tiger 用例在 iPhoneX 上渲染结束后的结果,运行前内存值在 150 左右

enableMergeStroke Off 的情况渲染结束后

enableMergeStroke On 的情况渲染结束后

0x08 Summary && 总结

可以看到,目前这个组件对于 svg解析 渲染 控制 应用 上已经做到了一个比较令人满意的程度。

当然 svg 还有一些十分有趣,值得去挖掘和实现的功能,比如 <clip-path><mask><text> 标签。另外还有 svg animation 矢量图动画。请注意这些功能在目前 1.0.0 版本中还不支持,因此有些网上找来的 svg 文件,如果其中包含这类标签,就会造成渲染结果和实际不同。

这些功能想要在 cocos creator中合理的实现,可能都不会是一件简单的事情,但是应该也不会是一件不可能的事,毕竟这一版本组件所实现的有些效果,在制作初期看来,是很难做到的。

目前商店上架的是 v1.0.0 版本,下一版本会更新 顺序播放描边动画和描边练习测试 相关的应用场景,具体内容可以参考 hanziwriter 的文档

有兴趣的朋友可以关注,购买,支持 :nerd_face:

51赞

mark 支持大佬

大佬!!!

大佬牛逼!

太牛逼了,除了牛逼想不到别的形容词

实在是太牛了,佩服佩服,五体投地!

我直接好家伙, 起飞

芜湖起飞~

给大佬递茶

炸裂了,好东西啊

markmark

以前研究过svg, 它最大的问题是内存问题, 这块没有做过测试的数据.

厉害啦,好东西

mark 支持大佬

暂时还没有很细致的做性能测试,还在挖掘一些功能上的可能性。性能方面的话,主要应该是在复杂 svg 渲染时,不停调用 Graphics 会造成内存的负荷。这个最近正在考虑用优于 Graphics 的解决方案来实现性能上的优化

更新一下最近做的一些功能上的挖掘更新,和后面的一些正在做的计划。

  • 基于 SSRSVGComponent 创建 SSRSVGWriterComponent
  • 初步实现汉字笔顺绘制原型


  • 代码开始第一次重构
  • 增加边框显示功能
  • 优化笔顺填充算法


  • 第二次代码重构,重新设计节点结构,填充实现方式
  • 增加网格组件,增加笔顺引导线组件
  • 优化编辑器中,预览,实时编辑


  • 丰富插件接口属性
  • 优化笔画动画实现方式
  • 修改为更合理的字体大小设置方式 (scale 控制,改为 size 控制,防止子节点被缩放)


  • 新增手写识别测试的功能




TODO

  • 笔画动画控制 play resume stop reverse
  • 橡皮擦除
  • 自定义汉字,形状,字母工具 makemeahanzi-tool
  • 汉字部首解析
  • 笔画平滑算法优化
  • 性能优化
  • 增加完整的事件回调机制,方便用户使用,介入渲染流程
  • 手写输入
  • writer 专用,lite 版解析,渲染库
  • binding ?
6赞

好东西 顶一下

但是目前的矢量渲染还是有锯齿的问题 虽然比之前的版本好很多了

transform 属性 可以支持一下吧,svg通用属性

1赞

mark 支持大佬

为楼主打call