- Skyline|小程序手势:让半屏弹窗更顺滑
在小程序页面开发中,我们经常用半屏弹窗来进来内容展示,例如:微信开放社区切换主页、加入购物车的选项页、文章留言区等等。 [图片] 常见的半屏弹窗展示逻辑是这样的: 打开弹窗:点击 “打开弹窗” 按钮展示弹窗关闭弹窗:点击“关闭按钮” or 遮罩层 关闭弹窗当我们想在半屏弹窗加一些交互动画时,可以监听节点的 touch 事件来做一些手势判断,进而处理拖拽事件。但是这种方式实现的滚动动画容易卡顿,出现延迟的情况,效果并不理想。 为了丰富小程序的交互体验,我们内置了一批手势组件,可以帮助开发者更好的实现交互动画的效果。 下图演示使用手势的半屏弹窗下拉效果与普通半屏下拉的对比。 当内部评论列表往下拉到顶部时,变为半屏的下拉,可直接下拉关闭弹窗。 [图片] 我们来看下这种操作是怎么实现的 在上面评论列表的半屏弹窗中会有一个 scroll-view 滚动组件,在 scroll-view 中会有滚动事件,当滚动到顶部时,我们希望有整个半屏的下拉事件。 所以我们需要在半屏的最外层放置一个拖动手势组件 pan-gesture-handler 由于拖动组件内部的 scroll-view 也是可以滚动的,所以这里需要进行一个手势协商的处理,就是什么条件下由哪个组件来响应手势。 当手势往下 ⬇️ 滚动时,此时判断内部 scroll-view 滚动条的位置 滚动条处于顶部:外层 pan-gesture-handler 响应滚动,此时半屏往下拖动至关闭半屏滚动条不处于顶部:内层 scroll-view 响应滚动,此时内部列表往上滚[图片] 当手势往上 ⬆️ 滚动时,此时判断半屏的位置 半屏不完全打开时:外层 pan-gesture-handler 响应滚动,此时半屏往上拖动至完全打开半屏半屏完全打开时:内层 scroll-view 响应滚动,此时内部列表往下滚[图片] 我们来看一下代码的实现,这里用到的手势组件 pan-gesture-handler(拖动时触发)和 vertical-drag-gesture-handler(纵向滑动时触发),手势组件有以下属性 on-gesture-event:手势回调事件should-response-on-move:是否响应当前手势的 move 阶段simultaneous-handlers:指定需要协商的手势是哪几个,下面演示表示 pan 和 scroll 协同触发。native-view:代理的原生节点,这里 scroll-view(scroll-y) 内有个 vertical-drag 手势,scroll-view 自身无法处理,需要被代理出来 ... 接着,我们看看在页面 js 中怎么处理手势。 在手势处理的回调中因为会改变半屏的状态值,所以这里的回调函数采用 worklet 函数,worklet 函数运行在 UI 线程,使得小程序可以做到类原生动画般的体验。 // page.js // shared 创建的变量为共享变量,可在 UI 线程和 JS 线程间同步 this.transY = wx.worklet.shared(1000) this.scrollTop = wx.worklet.shared(0) this.startPan = wx.worklet.shared(true) // shouldPanResponse 和 shouldScrollViewResponse 用于 pan 手势和 scroll-view 滚动手势的协商 shouldPanResponse() { 'worklet' return this.startPan.value }, shouldScrollViewResponse(pointerEvent) { 'worklet' // transY > 0 说明 pan 手势在移动半屏,此时 scroll-view 滚动不应生效 if (this.transY.value > 0) return false const scrollTop = this.scrollTop.value const { deltaY } = pointerEvent // deltaY > 0 是往上滚动,scrollTop <= 0 是滚动到顶部边界,此时 pan 开始生效,scroll-view 滚动不生效 const result = scrollTop <= 0 && deltaY > 0 this.startPan.value = result return !result }, // pan 手势处理 handlePan(gestureEvent) { 'worklet' if (gestureEvent.state === GestureState.ACTIVE) { const curPosition = this.transY.value const destination = Math.max(0, curPosition + gestureEvent.deltaY) // 改变半屏的位置 this.transY.value = destination } // 其他手势状态的处理,如滚动结束时计算半屏处于打开还是关闭的状态 } 目前,同程旅行 已经上线了手势结合半屏的效果 体验路径:酒店查询 - 选择酒店 - 选择入住人 - 新增入住人 [图片] 普通半屏结合手势代码片段:https://developers.weixin.qq.com/s/lx0RH1mD7rGj 手势除了在普通半屏的应用之外,也可以实现分段式半屏。下面演示的分段式半屏比普通半屏的判断条件更多一些。 判断条件同普通半屏类似,根据手势方向 和 分段式半屏当前的位置来判断是响应分段式半屏还是内部列表,响应分段式半屏是改变到哪一个位置。 [图片] 这里与普通半屏不同的是我们还改变了地图的缩放级别(scale) 因为 worklet 函数是在 UI 线程运行的,当要改变 data 值时,需要通过 wx.worklet.runOnJS 调回 JS 线程。 // page.js // 设置 map scale // 运行在 JS 线程 setMapScale(scale) { this.setData({ scale }) }, // worklet 函数,运行在 UI 线程 scrollTo(toValue) { 'worklet' let scale = 18 if (toValue > screenHeight / 2) { scale = 16 } // 从 UI 线程调回 JS 线程 wx.worklet.runOnJS(this.setMapScale.bind(this))(scale) this.transY.value = timing(toValue, { duration: 200 }) }, // 处理拖动半屏的手势 handlePan(gestureEvent) { 'worklet' // 滚动半屏的位置 if (gestureEvent.state === GestureState.ACTIVE) { // deltaY < 0,往上滑动 this.upward.value = gestureEvent.deltaY < 0 // 当前半屏位置 const curPosition = this.transY.value // 只能在 [statusBarHeight, screenHeight] 之间移动 const destination = clamp(curPosition + gestureEvent.deltaY, statusBarHeight, screenHeight) if (curPosition === destination) return // 改变 transY,来改变半屏的位置 this.transY.value = destination } if (gestureEvent.state === GestureState.END || gestureEvent.state === GestureState.CANCELLED) { if (this.transY.value <= screenHeight / 2) { // 在上面的位置 if (this.upward.value) { this.scrollTo(statusBarHeight) } else { this.scrollTo(screenHeight / 2) } } else if (this.transY.value > screenHeight / 2 && this.transY.value <= this.initTransY.value) { // 在中间位置的时候 if (this.upward.value) { this.scrollTo(screenHeight / 2) } else { this.scrollTo(this.initTransY.value) } } else { // 在最下面的位置 this.scrollTo(this.initTransY.value) } } }, 分段式页面代码片段:https://developers.weixin.qq.com/s/fw0U31mI7bGf 半屏的交互除了在页面内实现,也能跨页面实现,如常见的下沉式半屏交互。其中,半屏效果与上述实现类似,而前一页面的下沉实现需要结合自定义路由 后面的文章中我们会介绍自定义路由结合手势怎么去实现下沉式半屏效果,不仅如此,还有很多类原生的页面切换效果都能通过自定义路由实现 [图片]
2023-08-03 - 微信开发者工具稳定版 1.02.1907160 更新说明
下载地址Windows 64 、 Windows 32 、 macOS 开发者工具稳定版 1.02.1907160 在灰度 6w 安装量后结单,已知问题已在最新的RC 1.02.1907301 修复了.上一个稳定版本为 [代码]1.02.1904090[代码],之后发布了[代码]1.02.1905151[代码]、[代码]1.02.1906141[代码]、[代码]1.02.1907081[代码] 三个 RC 版本,本文说明了 [代码]1.02.1907160[代码] 相较于 [代码]1.02.1904090[代码] 的新增功能和交互优化的要点已知问题 请升级到 1.02.1907301 部分 windows 机器打开时工具黑屏的问题 设置改变后,再次启动时没有生效的问题 使用 componentGenerics 异常的问题 1. nwjs 内核升级[代码]1.02.1904090[代码] 的内核为 nwjs 0.27.4,chromium 60,node: 8.4.0, 发布于 2017 年 8 月,这个 nwjs 版本会导致开发者工具在快速编译的时候 crash,详见 issue,表现为开发者工具黑屏。虽然我们做了很多事情去减低 crash 的几率,但是并不能从根本解决问题,所以这个版本对 nwjs 的版本进行升级。 当前开发者工具使用的 nwjs 版本是基于 nwjs win: 0.37.4,nwjs mac: 0.38.4,对 issue 的修复后的版本 升级后,部分低端显卡的机器会出现启动黑屏的情况,原因是 chromium 默认开启了 GPU 加速带导致的,该情况已经在之后的 RC 版 1.02.1907301 默认关闭了 GPU 加速,来解决。 如果回退到 [代码]1.02.1904090[代码],会在启动旧版本时出现提示 nw 版本不匹配的弹框,如需回退且避免这种情况,可在回退前在小程序调试器输入命令 [代码]cleanAppCache[代码],然后再安装旧版本。 2. 增强编译增加了增强编译的选项来增强 ES6 转 ES5 的能力,启用后会使用新的编译逻辑以及提供额外的选项供开发者使用。 启用增强编译后的编译能力的对比: 特性原有逻辑增强编译Babel版本babel6babel7Presetses2015、stage0env {chrome:53, ios:8}Helpers单文件内联跨文件共享Async/Await不支持支持严格模式开关不支持支持忽略文件目录不支持支持代码压缩uglify-jsterserBabel插件-一系列proposal*polyfill大部分es6新增三个polyfill*使用preset-env,支持最新的ECMAScript语法 共享helpers函数,默认放在项目@babel/runtime目录,可通过项目配置文件配置 支持async/await语法,按需注入regeneratorRuntime,目录位置与helpers函数一致 文件首行是// use strict disable;时,即可禁用文件严格模式 可通过项目配置文件指定任意文件、目录不经过编译(如:miniprogram_npm) 原有逻辑是支持stage0语法的,为了向前兼容,引入了一系列proposal插件 关于polyfill,基础库中已经引入了大量的es6相关的polyfill 可参考文档,增强编译下,新增:Array.prototype.includes(es7)、Object.entries(es8)、Object.values(es8) 开启增强编译项目详情页中,勾选[代码]增强编译[代码]选项 [图片] 打开后,即可在项目中使用最新的js语法 [图片] 工具运行时,会按需注入一些辅助函数和 regeneratorRuntime, 注入的目录路径可通过配置修改,上传代码时(包括预览时)这些文件会作为代码包的一部分 [图片] 其他选项其他可选项详情请参考项目配置文档 3. 任务通知中心任务完成后的消息通知会自动进入通知中心,通知中心入口在右下角的任务状态栏 [图片] 任务状态栏也进行了优化,以图标形式显示正在进行中的任务、失败任务数、及通知中心入口。 [图片] 4. 上传时版本号推荐上传的对话框现在会显示版本号推荐 [图片] 5.控制台显示当前页面是否被索引根据 sitemap.json 的配置,我们可以在控制台中查看改页面的索引情况是否符合我们的预期 [图片] 该功能默认打开,如果不需要改功能,可以修改 [代码]project.config.json[代码] [代码]{ "setting": { "checkSiteMap": false } }[代码]6. Network 面板能力升级渲染层的图片请求现在也会展示在 Network 面板。 [图片] 小程序中发起的云开发请求可以直接在 Network 面板中显示。 [图片] 7. 快速体验开发版菜单新增 "快速体验开发版" [图片] 由于 RC/Stable 版本有一定的发布周期,而我们有一些小的 bug 修复会以 Nightly build 的形式发布,我们可以通过快速体验开发版来快速更新版本,更新的开发版如果有问题,可以快速回退到之前的版本 8.伪类调试支持wxml 本地调试支持 before/after 伪类(真机调试暂不支持) [图片] 9. 版本管理支持标签操作[图片] 10. 快速申请使用插件未授权的插件不再需要前往管理后台进行申请,可以在开发者工具的小程序调试器中,直接申请 [图片] 11. 自定义编译模式交互优化新增自定义编译模式时,默认以页面名为条件名 [图片] 当自定义编译条件超过 10 个时,会出现模式名过滤条件输入框 [图片] 12. 云控制台支持消息推送配置在云控制台-设置-全局设置,可以设置将消息推送至指定的云函数,而不再推送到微信公众平台-开发设置-消息推送中配置的域名 [图片] 13. 云控制台支持数据库高级查询云控制台-数据库-高级操作中可以通过编写指令对数据库进行高级查询 [图片] 14.云控制台新增配额调整云控制台-设置-环境设置,可以更加需求购买高版本的配额 [图片] 15. 编辑设置——上传时保存所有问题新增上传时保存所有文件的设置,默认不勾选 [图片] 16. 通用设置可以使用通用设置来修改默认工作区路径、启动时是否打开最后一次修改的项目 [图片]
2019-07-31