旅行小程序最佳技术实践,实现丝滑用户体验|天天滚动
1、开发自定义路由
实现此交互,需要 ,因为小程序渲染框架的页面支持自定义跳转动画。当使用自定义路由后,页面跳转时指定路由类型,就会触发自定义路由动画,而不再是默认的从右往左的动画,此处的实现可以使得页面跳转时,没有默认的路由动画,页面将直接以透明的方式渲染在屏幕上,由开发者自己控制页面内元素的动画展示方式,具体实现如下: (1)在图片查看页面配置文件 index.json 中声明(2)在 wxss 中,设置图片查看页面的 page 节点为透明背景{
\"backgroundColor\": \"#00000000\",
\"backgroundColorContent\": \"#00000000\", // 设置客户端页面背景为透明
\"navigationStyle\": \"custom\",
\"renderer\": \"skyline\", // skyline渲染引擎
\"disableScroll\": true,
\"usingComponents\": {
}
}
(3)在 js 中,使用 wx.router.addRouteBuilder(routeType, fn) 来声明自定义路由动画page {
background: transparent;
}
(4)在图片列表页面中,使用 wx.navigateTo 来跳转页面,并且设置 routeType 为 myCustomRoutewx.router.addRouteBuilder("myCustomRoute", function (params) {
const handlePrimaryAnimation = () => {
"worklet";
return {
// 可在此处,根据 params.primaryAnimation.value 的值,来设置页面的动画效果
backgroundColor: `rgba(0,0,0,${ params.primaryAnimation.value })`
};
};
return {
opaque: false,
handlePrimaryAnimation,
barrierColor: "",
barrierDismissible: false,
transitionDuration: 320,
reverseTransitionDuration: 250,
canTransitionTo: true,
canTransitionFrom: false
};
})
需配置页面的渲染引擎为 Skyline,并且在跳转时使用 routeType 就可以实现让页面在跳转时没有默认的路由动画。wx.navigateTo({
url: "/pages/skyline-image-viewer/index?index=0",
routeType: "myCustomRoute"
})
2、共享元素穿越
在连续的页面跳转时,页面间 key 相同的 share-element 节点将产生飞跃特效,还可自定义插值方式和动画曲线,通常作用于图片。为保证动画效果,前后页面的 share-element 子节点结构应该尽量保持一致这时,界面的表现像上面视频一样,是一个连续的动画状态,这完全是由 share-element 来控制的,share-element 的动画原理如下图所示:
you code here
3、接入手势组件,实现图片放大、缩小、平移
在图片查看页面有如下结构:这里,我们使用小程序渲染框架提供的
const GestureState = {
POSSIBLE: 0, // 此时手势未识别
BEGIN: 1, // 手势已识别
ACTIVE: 2, // 连续手势活跃状态
END: 3, // 手势终止
CANCELLED: 4 // 手势取消
};
Component({
attached() {
this.shareX = wx.worklet.shared(0);
this.shareY = wx.worklet.shared(0);
this.sharScale = wx.worklet.shared(1);
// 声明共享变量,并且给需要变化的dom,绑定动画
this.applyAnimatedStyle(".current-item", () => {
"worklet";
return {
transform: `translate3d(${this.shareX.value}px, ${this.shareY.value}px, 0) scale(${this.sharScale.value})`
}
});
// 页面所需的数据,需要在 attached 事件里初始化完毕,使其可以参与首帧渲染
this.setData({ src: "...", shareKey: "..." });
},
methods: {
// 当手势组件识别到手势时,触发此回调
onScaleGestureHandle(e) {
"worklet";
const { state } = e;
// 在worklet函数里,不要使用 const {} = this 对this解构
const shareX = this.shareX;
const shareY = this.shareY;
const sharScale = this.sharScale;
if (state === GestureState.BEGIN) {
// 手势已经识别,此时,可以获取到手势的初始值
} else if (state === GestureState.ACTIVE) {
// 手势活跃状态,此时,可以获取到手势的变化值,如平移的距离、缩放的比例等
// 将当前变化的值,设置到 `shared` 变量,就可以改变元素的样式,类似于vue3的数据驱动
shareX.value += e.focalDeltaX;
shareY.value += e.focalDeltaY;
sharScale.value = e.scale;
} else if (state === GestureState.END || state === GestureState.CANCELLED) {
// 手势终止或取消,此时,可以获取到手势的最终值
}
}
}
})
4、手势协商(解决手势冲突)
上面的 demo 简单演示如何使用手势组件来做图片交互,但是在图片查看页面中,我们还有其他的手势交互,如图片的左右滑动切换等,一般我们会使用
什么是手势协商?
手势协商指的是:当页面同时有多个手势交互时,需通过一定的约定来决定哪些手势事件应该被执行,哪些需要被忽略。
小程序渲染框架解决手势冲突的方式,主要是通过手势组件的 tag、simultaneous-handlers、native-view 和 should-response-on-move 来实现
(资料图)
tag:手势组件的标识,用于区分不同的手势组件
simultaneous-handlers:手势组件的协商者,表示需要同时触发事件的手势组件的标识
should-response-on-move:参与手势时间的派发过程,返回 false时,表示该手势时间不会继续派发
native-view:用当前手势组件来代理原生组件内部的手势事件,如
simultaneous-handlers=\"{{["swiper"]}}\"
worklet:ongesture=\"onScaleGestureHandle\">
native-view=\"swiper\"
simultaneous-handlers=\"{{["scale"]}}\"
worklet:should-response-on-move=\"shouldResponseOnMove\">
const GuestureMode = {
INIT: 0,
SCALE: 1,
SWIPE: 2,
MOVE: 3
// ...
};
Component({
attached() {
this.GuestureModeShared = wx.worklet.shared(GuestureMode.INIT);
this.shareX = wx.worklet.shared(0);
this.shareY = wx.worklet.shared(0);
this.shareScale = wx.worklet.shared(1);
// 声明共享变量,并且给需要变化的dom,绑定动画
this.applyAnimatedStyle(".current-item", () => {
"worklet";
return {
transform: `translate3d(${this.shareX.value}px, ${this.shareY.value}px, 0) scale(${this.shareScale.value})`
}
});
// ...
},
methods: {
onScaleGestureHandle(e) {
"worklet";
const { state } = e;
if (state === GestureState.BEGIN) {
this.GuestureModeShared.value = GuestureMode.INIT;
} else if (state === GestureState.ACTIVE) {
if(this.GuestureModeShared.value === GuestureMode.INIT) {
this.gestureBefore(e); // 手势类型未知时,判断手势类型
} else {
this.gestureHandle(e); // 手势类型已知时,处理手势事件
}
} else if (state === GestureState.END || state === GestureState.CANCELLED) {
this.GuestureModeShared.value = GuestureMode.INIT;
}
},
// 判断手势类型
gestureBefore(e) {
"worklet";
const { focalDeltaX, focalDeltaY, scale } = e;
if (Math.abs(focalDeltaX) > Math.abs(focalDeltaY)) {
this.GuestureModeShared.value = GuestureMode.SWIPE;
} else if (scale > 1) {
this.GuestureModeShared.value = GuestureMode.SCALE;
} else {
this.GuestureModeShared.value = GuestureMode.MOVE;
}
},
// 处理手势事件
gestureHandle(e) {
"worklet";
if (this.GuestureModeShared.value === GuestureMode.SCALE) {
this.shareScale.value = e.scale;
} else if (this.GuestureModeShared.value === GuestureMode.SWIPE) {
// swiper 切换模式时,这里什么都不用做
} else if (this.GuestureModeShared.value === GuestureMode.MOVE) {
this.shareX.value += e.focalDeltaX;
this.shareY.value += e.focalDeltaY;
}
},
// 用于判断手势事件是否应该派发
shouldResponseOnMove(e) {
"worklet";
return this.GuestureModeShared.value === GuestureMode.SWIPE; // 当模式为SWIPE时,才响应手势事件
}
}
})
通过上面的代码,我们实现了手势协商,当用户在图片上进行滑动的操作时,总是会触发
5、使用小程序渲染框架时需要注意的一些地方
作为一款新的渲染优化方式,开发者使用小程序渲染框架需要注意以下内容,以保证渲染的效果和性能。
(1)自定义路由时首帧渲染&首帧性能优化
小程序渲染框架的首帧渲染对共享元素动画非常重要,若共享元素节点的key 错过首帧设置的话,可能会丢失飞跃动画,所以在使用小程序渲染框架时,共享元素的 key 应该尽量在 attached 中或之前设置到页面,并且在首帧渲染时,应尽可能的减少 UI 层的渲染工作 如下:
1)所需要的数据应尽可能使用提前计算好,避免构建页面时等待太久影响响应速度
2)首次设置的数据应该尽可能的少,避免首次渲染时,页面上的元素过多,导致首帧渲染时间过长,导致动画卡顿(如:不要同时初始化太多的
3)确保首帧渲染时,共享元素的 key 正确的设置,避免在首帧渲染时,由于找不到对应的共享元素,导致动画丢失,看不到飞跃动画
4)由于手势事件触发频繁,应尽量避免大量需要的计算的逻辑高频执行,容易导致机器发烫,或者导致动画卡顿
**worklet 函数的使用**
worklet 函数的使用有一些限制,主要是由于它是在 UI 线程执行的,所以 worklet 函数中的 this 并非是页面的 this 实例, 里面所使用到的变量也是通过特殊的 babel 插件转换到UI线程的,需要与逻辑层共用的变量都需要用 wx.worklet.shared 将它声明成共享变量,在 UI 线程调用逻辑层的函数需要使用 wx.worklet.runOnJS
(2)与 web 规范的差异
虽然小程序渲染框架尽可能的与 web 规范保持一致,但是由底层渲染引擎的限制,还是有一些差异,如:
1)display: flex 的默认朝向是 column,而不是 row,这需要开发者注意,官方后续会支持 block 布局方式
2)暂不支持 css 伪元素,如 ::after、::before,官方正在支持中
3)position 仅支持 absolute、relative,不支持 sticky,实现滚动吸附的效果需用 sticky-* 组件来配合 scroll-view 实现
**
在非小程序渲染框架的运行环境内,
6、何时使用小程序渲染框架
开发时,请确保小程序开发者工具版本是,sdk 版本在 2.30.2+,具体限制可参考。
这些新特性的引入,使得小程序渲染框架在小程序开发中的优势更加明显,开发者可以更加便捷地实现各种复杂的交互效果,并且达到接近原生APP的体验。
未来展望1、个性化产品形态:将会根据不同的用户需求和场景,设计出更加符合用户喜好和习惯的动效衔接,进行组件化调用。
2、更加自然和真实的动效衔接:动效衔接将会更加贴近自然规律和真实物理效应,从而增强动画的真实感和用户体验。
3、更加智能化和自适应的动效衔接:动效衔接将会根据用户的操作行为和使用习惯,自适应调整动画效果,从而提高用户体验和产品效果。
4、扩大产品、设计与开发的协作效应:设计对动效的把控、产品对用户的洞察以及开发对新技术的应用,才可以发挥最大化的协作效应。
附1:本文作者
惠波:同程旅行研发工程师
洛奇、子聪:同程旅行体验设计师
老干部:同程旅行产品经理
附2:代码片段
相册小程序代码片段(请使用 PC 端浏览器打开):
附3:UE标注
附4:AB 实验效果
AB 实验显著win0.23%。
标签:
抢先读
- 《无人知晓的故事》获上影节电影项目创投大奖 《她问》世界首映 焦点报道
- 领克09亚运行政五座版上市 售价28.99万元
- 实时焦点:智慧农业属于什么概念?十大智慧农业龙头股?
- 《星空》尚未发售就遭差评 玩家指责开发商及制作人 世界观点
- 【环球时快讯】蓝色协议登录不进去 开服网络错误有效解决方法
- 房贷提前还款的方式有几种?房贷逾期不还的后果看这里 全球动态
- 全球今日讯!球迷“狂飙”盖过梅西进球,媒体:热情可理解,“越界”莫赞美
- 国家统计局:二季度经济增长明显快于一季度
- 2023年5月上汽集团汽车产量情况:新能源汽车销量同比增长5.94%_天天最新
- 债券基金有哪些风险?如何办理基金转换?-环球速读
- 破坏组蛋白遗传可能导致肿瘤加速发展
- SK海力士据报将翻倍HBM产能,因人工智能半导体需求增加_天天精选
- 全球热议:时光之穴开启黑暗之门任务_时光之穴怎么去
- 美国疾控中心:枪支暴力推波助澜 青少年谋杀率飙升_全球快资讯
- 恩威医药同山东朗诺达成合作 战略布局得到持续深化
- 每日关注!vivo全系列型号大全:从旗舰到入门级,一网打尽!
- 初始投资成本是什么?初始投资成本怎么计算?
- 医生进校,为光祈幼儿园教职工普及健康知识 头条焦点
- 天天观热点:亚运会的运动员村什么样?先睹为快
- 日本央行决定继续维持当前宽松货币政策
- 高合HiPhi Y一体化压铸后舱获碳中和大奖,7月15日全球上市|热头条
- 动画|宝“藏”朋友圈
- 前沿热点:辛奇是什么意思(辛奇隆个人资料出生哪一年)
- 阿里要建“欧洲版”天猫? 回应:天猫APP在欧洲本身就可以提供服务-全球看热讯
- 世界观天下!阿里影业为什么暴跌
- 爱情公寓4在线播放_爱情公寓3在线播放免费高清_世界短讯
- 飞机靠桥率不高,让坐摆渡车?民航局启动专项整治 天天聚看点
- ieencode.dll重新安装有哪些方法
- 今头条!ehviewer图片无法加载(图片无法加载)
- 苏翊鸣回应被保送清华大学:会更加努力不负期望
- 热门看点:猪头猪脑指什么动物?猪头猪脑是什么意思?
- 神界原罪2重要角色背景故事科普 神界原罪2重要角色背景故事科普书_环球观焦点
- 韩国塔塔大宇商用车公司客人访问法士特
- 国家发改委:1-5月份 全国全社会用电量同比增长5.2% 环球报资讯
- 股票穿头破脚是什么意思?
- 股票进行洗盘该怎么理解?区分庄家洗盘和出货的方法_天天看热讯
- 热点!幼小衔接初体验,和盛小学迎“小客人”到校参观
- 电报解读|紫东太初2.0发布 机构关注华为AI算力产业链 全球最新
- 哈弗全新插混SUV申报 命名“翔龙”/搭载1.5T Hi4混动|天天快资讯
- 【天天新视野】股票做长线的好处?股票大跌如何选股?
- 港元拆息连续三日全线上升 与楼按相关的一个月拆息逼近5%创近半年新高
- 砣矶镇持续加大道路交通安全宣传力度 今热点
- 2023年5月电量点评:用电需求略有回落 来水有望边际改善
- 京东618不止买买买 冲话费、冲流量、冲腾讯视频会员都有超值福利-全球动态
- 通讯!金陵丸子是哪里的菜系?金陵丸子是什么地方的菜?
- 雅诗兰黛精华水好用吗?-全球速讯
- 环球通讯!动画 | 宝“藏”朋友圈
- AMD 确认 MI300X GPU TBP 为 750W 当前短讯
- 甘肃高台县第四幼儿园:安全伴“童”行-时快讯
- 环球热点评!选择按摩椅需要注意什么?为什么不建议买红木?
- 全球看热讯:回天新材锂电池用聚氨酯胶生产线建成投产
- 焦点快看:降息了,居民手头的“闲钱”流向哪里了?
- 生物质燃烧器_关于生物质燃烧器介绍
- 工信部等五部门:开展2023年新能源汽车下乡活动
- 衣柜喷漆多少钱_当前通讯
- 世界观焦点:农业农村部:6月16日“农产品批发价格200指数”比昨天下降0.08个点
- 热点!美日韩安全高官会晤炒作台海及南海议题,中方早明确表态
- 安童生布洛芬混悬液
- 普通股和优先股的区别都是什么? 优先股资本成本计算公式是什么?-天天最新
- 全球焦点!Apple Music Classical登陆安卓立即在Play商店下载
- 每日资讯:防盗门开锁最简单手法防盗门如何开锁
- 柳公权是哪个朝代的?柳公权的楷书特点是什么? 环球关注
- 机器视觉板块震荡拉升,大华股份尾盘涨停
- 79年羊2022年运势如何,2022 79年羊2022年运势如何女|环球观点
- 天天热门:成都天府公安成功解救身陷缅北受骗人员平安回国
- 天天实时:第 14 代英特尔处理器全新命名公布,这下更看不懂了?
- 6月16日国内顺丁橡胶市场行情弱势盘整
- 世界热议:纯电轻卡天花板 江铃乐行E路达全球首发重磅上市
- 安逸花借款额度如何评估?如何提高安逸花借款额度? 前沿资讯
- 《如龙7外传:无名之龙》情报汇总 桐生一马和春日一番对话公开|今日热闻
- 酮酸中毒是怎么引起_酮酸中毒是怎么引起的-观点
- 国债期货跌幅持续扩大
- 当前热讯:郑州金水区金冠美寓周围有学校吗?附地址
- 球迷闯入球场抱梅西或导致工体“严防死守”,克洛普曾吐槽球迷入侵球场很愚蠢,英超考虑关闭球场处罚该行为
- 万华化学(600309)6月16日主力资金净买入1588.60万元
- 环球热推荐:最贵的红旗汽车多少钱一辆?红旗Esh9价格多少钱?
- 世界新动态:第四十三章 隐者与审判
- 全球观焦点:基金认购与基金申购哪个更好?理财认购和申购的区别是什么?
- 世界视点!高校干部车内出轨被女方婆婆抓现行,校方回应!
- spss做相关性分析数据怎么做_spss做相关性分析
- 1月-5月 厦门130个省重点项目投资完成率居全省前列
- 吕海洋|大美宝地—全国书画名家学术交流展
- 中国革命必须走农村包围城市的道路其主要依据除了谁_中国革命必须走农村包围城市的道路其主要依据除了_ 每日热闻
- 松花粉品牌哪个好?松花粉真的有那么好吗? 环球今头条
- 天天热资讯!魔兽世界剃刀高地任务怎么完成(wow60怀旧服剃刀高地副本任务流程)
- 大众汽车召回部分进口宾利飞驰系列汽车,共计3028辆
- 西北妹长大了,KimKardashian携女儿亮相巴黎时装周,女儿抢眼
- 《我爱你!》曝主题曲创作特辑 李健谈爱情众生相
- 每日热闻!市发改委召开成都市制造业中长期贷款银政企对接会
- 时光代理人第二季定档,陆光抢救无效死亡,这一季的剧情已经明了
- 四川宣汉一小区业主自发砸掉占用盲道停车线,当地:停车位应退离盲道
- 天天速看:6月17日晚8点京东618高潮开启手机小时购下单1小时新机即可送达
- 货车顺风车拉货长途_货车拉货平台软件有哪些|世界速递
- 世界速讯:体图:哈维公开示好基米希的发言令人惊讶,而拜仁视其为非卖品
- 新债中一签能赚多少?新债中签技巧与注意事项有哪些? |热文
- 我找到了阅读GitHub项目源码的最佳姿势,太舒服了!-世界头条
- 中小板固态电池概念股股票一览,代码查询|环球微资讯
- 联合国难民署驻华代表:应对全球难民危机 中方支持发挥重要作用 聚焦
- A股历史第四大IPO今日上会 拟募资650亿元_精选
- 吵吵了半天,布林肯还没到,比尔盖茨先来了!说明中国越来越清楚对美怎么办