个人案例
- MiniProgram模版演示
基于小程序开发模版敏捷快速的开发小程序
小程序开发模版扫码体验
- 番茄博客园
个人博客
个人博客扫码体验
- Skyline 渲染引擎 1.1.0 版本发布
在正式版发布后,有越来越多的小程序使用 Skyline 渲染引擎开发,并且出现了不少体验接近原生的小程序,其中大量运用了 Skyline 渲染引擎提供的新特性,如手势系统、自定义路由等。我们也整理了一些案例,发表在「微信开发者」公众号上,供开发者参考。 同时,过去几个月,我们得到了开发者诸多反馈,Skyline 渲染引擎通过快速迭代去支持或解决这些需求与反馈。现在,1.1.0 版本跟随基础库 3.2.0 发布,以下介绍主要变更点: 增强 WXSS 样式支持度 在之前的版本提供 默认 block 布局 后,从 WebView 迁移过来的成本较之前有较大改善,随后,适配问题更多在 inline 行为和 position fixed 特性上,为此我们着重做了支持。其中 inline 行为主要是对自定义组件节点本身改为默认 display inline,解决了大部分情况。此外,span / text 组件里嵌套的节点也支持了 display inline-block,可以解决文本与 image / view 内联的场景。 另外一项重要更新是,box-sizing 可开启 默认 content-box 盒模型,若没有设置过 box-sizing 的话,会使得节点宽高更符合预期,从而减少适配点。 Swiper 组件增加大量新交互 现有的 swiper 组件提供的默认交互动画较为单调,但为了能够更有效引导用户注意力,在原生 App 中往往能看到各式各样的动效,为了方便开发者使用,并借助于 Skyline 的高效渲染能力,我们在基础库 3.2.0 起内置了一些常见的交互类型,包括 swiper-item 和指示条的切换动效。同时,若开发者有更高的定制要求,也能基于 swiper 提供的事件并结合 worklet 动画机制实现。 以下列举一些支持的类型,更多请查阅 swiper 文档 [图片][图片] [图片][图片] [图片] 新增 draggable-sheet 组件 之前,在 Skyline 下已经能够实现完美的半屏拖拽交互,这得益于 Skyline 的手势协商系统。不过,考虑到半屏拖拽交互是比较常见的,同时也是推荐使用的一种交互,在基础库 3.2.0 起新增 draggable-sheet 半屏拖拽组件,开发者可以省去手势协商相关的代码,使用该组件,并配置容器大小、吸附阈值等即可很方便地实现半屏交互。 同样地,为了方便开发者使用自定义路由,我们也 内置一些页面转场效果,只要一行代码即可实现。 [视频] Scroll-view 组件支持 nested 模式 为了让一个页面内能展示更丰富的信息,在界面设计上,页面中间通常会有个分类导航(如下 demo 所展示),每个分类下都是一个长列表,为了有更好的长列表渲染性能,每个分类都需要用 scroll-view 承载,这就出现了 scroll-view 嵌套 scroll-view 的场景,此时 scroll-view 之间的滚动交替并不能很好地切换。为此,在基础库 3.2.0 起 scroll-view 组件新增 nested 模式,以解决上述场景。 [视频] Input / Textarea 组件优化 在新版本中修复了大量有关 input / textarea 的问题,也包括支持了 hold-keyboard、auto-height、confirm-hold 等原有特性。同时,还添加了诸多特性: ● 支持 cursor-color 属性,可设置光标的颜色。相比于 WebView 的版本在安卓下只能设置 default 和 green,Skyline 的版本则对颜色值的支持度更广泛。 ● 支持 selectionchange 事件,可监听光标移动的事件,并返回光标所在位置。 ● 支持 composing 系列事件,可监听输入草稿状态,包括草稿开始、更新、结束几个状态。这在输入中文的场景就比较有用,如用户在搜索时,在输入未完成前可提前联想,帮助用户更快完成。 [图片] 草稿状态下、红色的光标颜色 性能相关优化 持续的性能优化是 Skyline 渲染引擎最重要的工作之一,在新版本中,我们解决了在个别场景下发现的一些性能问题。比如,通过调整 Skyline 启动过程中的时序依赖,提高 JS 脚本执行与 Skyline 引擎启动的并行度,使 iOS 的启动耗时降低了近 100ms。 其次,开启了按需渲染的 scroll-view 场景下,由于对布局节点的误标脏,使得在滚动过程中触发了不必要的布局操作,在一些复杂的情况下会出现掉帧的情况。我们在新版本解决了这一问题。 此外,由于实现上的原因,在 iOS 下的原生组件(如 video)渲染时会出现发热现象,在新版本中,我们改用另一种实现方式优先解决了 video 渲染发热的问题,其它原生组件在后续的版本会逐一解决。 以上是新版本中 Skyline 带来的主要变更,还有更多的变更可查阅 变更日志,同时也可以关注后续版本即将支持的 特性状态。如开发者在 Skyline 开发过程中遇到问题,欢迎在社区发帖咨询。
02-19 - 小程序渲染引擎Skyline小试牛刀--快书
今年年初,在官方文档上看到小程序团队要推出一款性能逼近原生的渲染引擎Skyline,就一直在关注。刚好最近打算做一款新的阅读小程序,作为一名独立开发者,对于性能和用户体验的追求是永无止境的,于是我决定用纯Skyline打造这款小程序。 当然,这个项目里面所用到的skyline特性只是冰山一角,并非全部,更多酷炫的特性请前往官方文档查阅。 接下来,我会结合快书小程序,从以下几个方面,逐条阐述关于skyline特性(快书项目中所用到的)的理解与应用: 效果演示。如何开启Skyline。新版组件swiper。新版组件scroll-view。全新组件snapshot。增强特性worklet动画。增强特性手势系统。增强特性自定义路由。增强特性共享元素动画。希望对于刚接触Skyline,或者想要了解Skyline的同学有所帮助。当然,如有错误或遗漏,欢迎在评论区批评指正,不胜感激。 一、效果演示 [图片] 二、如何开启Skyline 开启Skyline的方式非常简单,只需要在app.json文件中,加入以下配置即可(这里是全局Skyline,若只打算指定页面开启,则在指定页面的json文件中配置即可): "renderer": "skyline", "lazyCodeLoading": "requiredComponents", "rendererOptions": { "skyline": { "defaultDisplayBlock": true, } }, "componentFramework": "glass-easel", 三、新版组件-Swiper 旧版的Swiper基于webview的,在性能上有所局限,特别是当swiper-item的数量动态不断增加的情况下。当然,也可以自己想办法去优化,比如做懒加载和缓存,但相对来说比较麻烦。而Skyline版本的Swiper性能会大幅度提升,首先渲染引擎本身的性能提升了,另外官方也做了缓存的功能,只需要通过定义cache-extent的值,就能轻松定义缓存区域大小,例如值为 1 则表示提前渲染上下各一屏区域。 [图片] 用法上,和webview版本没有太大区别(这里就不放代码了),只需注意不要使用某些webview独有的特性即可。 四、新版组件-Scroll-view 同样,旧版的scroll-view也基于webview的,滚动元素过多的时候会有明显卡顿,当然也是可以通过虚拟Dom的方式自行优化。然而,Skyline版本的scroll-view官方已经实现了只会渲染在屏节点的特性,大大提升了滚动的流畅度,真正做到了开箱即用。 用法上,有以下几个点要注意的。 指定type属性,有2个可选值,分别为:list和custom,对应的是列表模式和自定义模式。如是普通列表,list即可,如果是稍微复杂的列表,比如常见的瀑布流表现形式(类似小红书那样),则可使用custom。只有直接子节点才能根据是否在屏来按需渲染。即你不能把你的列表项,都放在同一个父级view中,而是应该直接放在scroll-view组件下。 // 错误的方式: <scroll-view type="list" scroll-y> <view> <view class="item" wx:for="{{dataList}}" wx:key="id"></view> </view> </scroll-view> // 正确的方式 <scroll-view type="list" scroll-y> <view class="item" wx:for="{{dataList}}" wx:key="id"></view> </scroll-view> // 正确的方式 <scroll-view type="custom" scroll-y> <list-view> <view class="item" wx:for="{{dataList}}" wx:key="id"></view> <list-view> </scroll-view> 另外,上面提到了瀑布流的问题,实现方式也很简单,官方提供了一个叫做grid-view的组件,只需定义它的type="masonry"即可,但若是在webview下,除了性能不理想以外,还会有一些小BUG,比如我在社区提的这个问题:grid-view masonry 在webview模式下经常会出现大块区域的空白。在Skyline下,就不会出现此类问题。 [图片] <scroll-view type="custom" scroll-y> <grid-view type="masonry" main-axis-gap="15" cross-axis-gap="15"> <view wx:for="{{dataList}}" wx:key="id"></view> </grid-view> </scroll-view> 五、全新组件Snapshot 我们常常会有分享精美海报的需求,但由于海报上的内容是动态,仅仅使用一张图片分享达不到我们的目的。在以往,我们可能会使用到wxml-to-canvas,通过绘制 canvas ,导出图片。现在,在Skyline下(基础库3.0.0以上),实现此需求就非常简单。只需要将我们要分享的内容包裹在snapshot组件下就行。 [图片] // wxml: <snapshot id="target"> <view>content</view> </snapshot> // page: Page({ onReady() { this.createSelectorQuery() .select("#target") .node() .exec(res => { const node = res[0].node node.takeSnapshot({ type: 'arraybuffer', format: 'png', success: (res) => { fs.writeFileSync(savePath,res.data,'binary'); //图片保存至本地 wx.showShareImageMenu({ //唤起分享图片的界面 path:savePath }) }, fail(res) {} }) } }) 六、增强特性-worklet动画 worklet动画相比传统的方式,流畅度提升了不少,但如何使用呢?常见的普通动画无非是对于页面元素的平移,缩放,旋转等变换。那么,要让一个元素动起来,只需要做以下2件事: 将页面元素的样式与某个变量进行绑定,变量值的变化会自动触发样式的更新。实时动态地改变这个变量。结合快书的例子(下拉时,让页面缩小,松手后,页面弹回),来看一下具体的实现步骤。 [图片] 首先,如何绑定样式与参数呢?通过官方提供的一个applyAnimatedStyle函数: // Wxml: <view id="#box">content</box> // Page: this.scale = shared(1); //这里是定义一个共享变量,即可在UI线程和JS线程间同步的变量。 this.applyAnimatedStyle(`#box`, () => { 'worklet'; // 声明这是一个worklet函数 return { transform: `scale(${this.scale.value})`, }; }); // 1、这里使用共享变量是为了让后续改变这个变量时,worklet的函数能捕获到。 // 2、#box你要动起来的元素 // 3、当this.scale.value变化时,会自动触发函数体的执行,从而改变#box的样式 第二步,下拉时,根据下拉的偏移量,改变这个scale的值。 this.scale.value = (evt.deltaY / 100) * 0.15; // 这里的evt.deltaY是下拉时的位置偏移量,然后根据偏移量按比例计算缩放的值 // 如何获取这个下拉偏移量?下一小节讲手势系统时会讲到 第三步,松手时,复原scale的值。 this.scale.value = timing(1, { duration: 300, easing: Easing.ease }); // timing函数表示:在300毫秒内,scale.value会逐渐变成1 // easing: Easing.ease 表示缓动的方式,具体可参考https://easings.net // 如何知道已经松手了?下一小节讲手势系统时会讲到 更多动画参考请查阅官方文档。 七、增强特性-手势系统 还是上面那个例子,我们只说了下拉时根据下拉的偏移量改变scale的值,那如何得到下拉的偏移量呢?这里就涉及到了手势系统。下面讲讲如何让一个元素能响应拖动,缩放等手势。 说回上一小结的例子,我们只需要讲#box元素包裹在手势组件vertical-drag-gesture-handler即可。更多示例可查阅官方文档 // wxml: <vertical-drag-gesture-handler worklet:ongesture="handlePan"> <view id="box"></view> <vertical-drag-gesture-handler> // page: handlePan(evt) { 'worklet' if (evt.state === GestureState.ACTIVE) { // 拖拽时 if (evt.deltaY > 0) { // 下拉 this.scale.value = Math.max(this.scale.value - (evt.deltaY / 100) * 0.15, 0.85); } else { // 上拉 this.scale.value = Math.min(this.scale.value - (evt.deltaY / 100) * 0.15, 1); } } else if (evt.state === GestureState.END || evt.state === GestureState.CANCELLED) { // 拖拽结束或取消 this.scale.value = timing(1, { duration: 300, easing: Easing.ease }); } }, 然而,当手势组件与scroll-view等可以滚动的组件嵌套时,会出现冲突的问题。比如,同上一小节的示例,为了让文章内容过长时可以滚动,我们需要将文章的内容放在scroll-view中。当scroll-view已经滚动到顶部,再继续下拉的话,应当触发手势组件的拖拽事件,即缩放页面。相反,则继续滚动scroll-view。 [图片] // wxml: <vertical-drag-gesture-handler tag="pan" worklet:ongesture="handlePan" shouldResponseOnMove="shouldPanResponse" simultaneousHandlers="{{['scroll']}}"> <vertical-drag-gesture-handler tag="scroll" native-view="scroll-view" shouldResponseOnMove="shouldScrollResponse" simultaneousHandlers="{{['pan']}}"> <scroll-view type="list" scroll-y bindscroll="handleContentScroll">文章内容</scroll-view> </vertical-drag-gesture-handler> </vertical-drag-gesture-handler> // page: // 处理scroll-view的滚动事件,获取scrollTop的值 handleContentScroll(evt) { 'worklet' this.scrollTop.value = evt.detail.scrollTop; }, // return false 则表示scroll-view不再响应滚动事件 shouldScrollResponse(evt) { 'worklet'; const { deltaY } = evt if (this.scrollTop.value <= 0 && deltaY > 0) { //scroll-view已经滚动到顶部,继续下拉时 this.pan.value = true; return false; } if (this.scale.value < 1 && deltaY < 0) { //#box已经被缩放,继续上拉时 this.pan.value = true; return false; } this.pan.value = false; return true; }, shouldPanResponse() { 'worklet' return this.pan.value; // true表示响应手势组件的拖拽事件,false则不响应 }, 八、增强特性-自定义路由 以往在webview中,路由的的过渡动画仅支持从右到左,较为单调。在skyline之后,我们可以自定义路由的过渡动画了,比如常见的淡入淡出,从底部弹起等。比如以下这个例子,从首页点击图片,会跳转到分享的页面,这里就是用自定义路由实现的淡入效果。 [图片] 自定义路由的使用相比前几个特性稍微复杂一点,这里官方讲的更为具体和清晰,可查阅官方文档。唯一要注意的一点是,只有连续的skyline页面跳转时,才会有效果。 九、增强特性-共享元素动画 还是上面的例子,当从首页点击图片跳转到分享页面时,图片看起来像是从首页飞到了分享页,这里便是使用到了共享元素动画。我同时也做Flutter的开发,所以这里看起来非常类似Flutter的hero动画或者叫飞行动画。 使用方式也类似于Flutter。将2个页面的相似组件都用share-element组件包括起来,并且使用相同的key即可。再配合自定义路由,可使得飞行动画看起来非常的丝滑。 // A页面: <share-element key="唯一key"> <image src="imagePath" mode="aspectFill" /> </share-element> // B页面: <share-element key="唯一key"> <image src="imagePath" mode="aspectFill" /> </share-element> // 有几个要注意的地方 // 1、两个个页面的share-element组件必须使用相同的key。 // 2、key是唯一的,即同一个页面中,不能出现重复的key。 // 3、image不要写死宽高,应百分比100%,具体宽高数值写在share-element组件上。 有一个常见的问题,A页面是一个列表,B页面是详情页,列表中的数据都是通过接口从后台返回的,由于共享元素的key又不能重复,那么这个key怎么定义?一般后台返回的数据都会有一个唯一标识,假设为ID,我们可以用这个ID当作Key。 但是,另一个问题来了,如果数据是后台接口返回的,然后通过setData的方式响应到页面,那么很有可能B页面的首帧获取不到这个Key,因为这时候接口请求可能还未完成,那么动画也是不会生效的。针对这种情况,官方也提供了一种方式: 共享元素动画需保证下一个页面首帧即创建好 [代码]share-element[代码] 节点,并设置了 key,用于计算目标位置。如果是通过 [代码]setData[代码] 设置的,可能会错过首帧。针对这种情况,可以 使用 Component 构造器构造下一个页面,只要在组件 [代码]attached[代码] 生命周期前(含)通过 [代码]setData[代码] 设置上去,就会在首帧渲染 十、总结 Skyline还有一些其他有趣的特性,大家感兴趣的话可以查阅官方文档。总的来说,相比起webview,skyline对性能的提升是显而易见的,并且,一些在webview很难实现的效果,在skyline的基础上,也能轻易实现,开箱即用。目前,skyline还在不断地迭代中,还有许多的新特性还在评估和开发中,相信之后的版本会更完善更好用。 最后,大家多多使用快书呀,球球了~ [图片]
2023-09-01 - rich-text添加class,修改wxss文件赋予rich-text宽度并且超出展示省略号无效?
rich-text组件添加类名, 修改样式样式不生效 [图片] [图片] [图片]
2021-12-17