今天,小程序正式支持 SVG

今天,小程序正式支持 SVG

写在前面

经过腾讯 Omi 团队的努力,今天你可以在小程序中使用 Cax 引擎高性能渲染 SVG!

SVG 是可缩放矢量图形(Scalable Vector Graphics),基于可扩展标记语言,用于描述二维矢量图形的一种图形格式。它由万维网联盟制定,是一个开放标准。SVG 的优势有很多:

SVG 使用 XML 格式定义图形,可通过文本编辑器来创建和修改

SVG 图像可被搜索、索引、脚本化或压缩

SVG 是可伸缩的,且放大图片质量不下降

SVG 图像可在任何的分辨率下被高质量地打印

SVG 可被非常多的工具读取和修改(比如记事本)

SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性、可编程星更强

SVG 完全支持 DOM 编程,具有交互性和动态性

而支持上面这些优秀特性的前提是 - 需要支持 SVG 标签。比如在小程序中直接写:

<svg> <rect bindtap="tapHandler"> </rect> </svg>

上面定义了 SVG 的结构、样式和点击行为。但是小程序目前不支持 SVG 标签,仅仅支持加载 SVG 之后 作为 background-image 进行展示,如 background-image: url("data:image/svg+xml.......),或者 base64 后作为 background-image 的 url。

那么怎么办呢?有没有办法让小程序支持 SVG? 答案是有的!需要下面这些东西(站在巨人的肩膀上):

JSX,史上最强 UI 表达式,支持书写 XML-Hyperscript 互转的 JS 语言

小程序内置 Canvas 渲染器

Cax 最新渲染引擎

HTM,Hyperscript Tagged Markup,可能是 JSX 的替代品或者另一种选择,使用ES标准的模板语法实现的 Hyperscript 运行时/编译时生成,preact 作者(也是google工程师)打造

这里稍微解释下 Hyperscript:

比如 JSX 中的

<div> Hello {this.props.name} </div>

或者 js 中的 htm:

html`<div> Hello {this.props.name} </div>`

最后都会被编译成:

h( "div", null, "Hello ", this.props.name );

嵌套的 div 也会变编译成 h 嵌套 h,比如

<div> <div>abc</div> </div>

编译后:

h( "div", null, h( "div", null, "abc" ) )

而 h 函数的定义也是相当简洁:

function h(type, props, ...children) { return { type, props, children } }

通过 h 的执行可以 js 中拿到结构化的数据,也就是所谓的虚拟 dom。需要注意的是 htm 有轻微的运行时开销,jsx 没有。

一句话总结:

使用小程序内置的 Canvas 渲染器, 在 Cax 中实现 SVG 标准的子集,使用 JSX 或者 HTM 描述 SVG 结构行为表现

直接看在小程序种使用案例:

import { html, renderSVG } from '../../cax/cax' Page({ onLoad: function () { renderSVG(html` <svg> <rect bindtap="tapHandler" transform="translate(100 50) rotate(45 50 50)"> </rect> </svg>`, 'svg-a', this) }, tapHandler: function () { console.log('你点击了 rect') } })

其中的 svg-a 对应着 wxml 里 cax-element 的 id:

<view> <cax-element></cax-element> </view>

声明组件依赖

{ "usingComponents": { "cax-element":"../../cax/index" } }

小程序中显示效果:

今天,小程序正式支持 SVG

可以使用 width,height,bounds-x 和 bounds-y 设置绑定事件的范围,比如:

<path bounds-x="50" bounds-y="50" />

需要注意的是,元素的事件触发的包围盒受自身或者父节点的 transform 影响,所以不是绝对坐标的 rect 触发区域。

再来一个复杂的例子,用 SVG 绘制 Omi 的 logo:

renderSVG(html` <svg> <g transform="translate(50,10) scale(0.2 0.2)"> <circle fill="#07C160" cx="512" cy="512" r="512"/> <polygon fill="white" points="159.97,807.8 338.71,532.42 509.9,829.62 519.41,829.62 678.85,536.47 864.03,807.8 739.83,194.38 729.2,194.38 517.73,581.23 293.54,194.38 283.33,194.38 "/> <circle fill="white" cx="839.36" cy="242.47" r="50"/> </g> </svg>`, 'svg-a', this)

小程序种显示效果:

今天,小程序正式支持 SVG

在 omip 和 mps 当中使用 cax 渲染 svg,你可以不用使用 htm。比如在 omip 中实现上面两个例子:

renderSVG( <svg> <rect bindtap="tapHandler" transform="translate(100 50) rotate(45 50 50)"> </rect> </svg>, 'svg-a', this.$scope)

renderSVG( <svg> <g transform="translate(50,10) scale(0.2 0.2)"> <circle fill="#07C160" cx="512" cy="512" r="512"/> <polygon fill="white" points="159.97,807.8 338.71,532.42 509.9,829.62 519.41,829.62 678.85,536.47 864.03,807.8 739.83,194.38 729.2,194.38 517.73,581.23 293.54,194.38 283.33,194.38 "/> <circle fill="white" cx="839.36" cy="242.47" r="50"/> </g> </svg>, 'svg-a', this.$scope)

需要注意的是在 omip 中传递的最后一个参数不是 this,而是 this.$scope。

在 mps 中,更加彻底,你可以单独创建 svg 文件,通过 import 导入。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/92bbe9e0b1a6b2547a8bb2734dde486c.html