背景介绍
Taro是一款基于React语法开发的小程序工具,它具备跨平台的功能,能够将编写的代码转换为适用于微信、百度、支付宝等多个小程序平台的版本,并且还能兼容H5和RN等多种应用环境。在项目开发的实际过程中,我们常常遇到需要引入类似于Tinder应用中的卡片滑动功能的需求。此功能一般采用向左滑动来表示用户的不感兴趣态度,而向右滑动则用来表达用户的兴趣所在。
问题发现
接手任务后,我注意到iOS和Android版本已成功实现了卡片滑动功能。然而,H5和小程序版本由于缺乏现成的插件和资料支持,该功能尚未实现。经过深入调查,我发现我们能够利用小程序中的可拖动组件movable-view
来达成这一效果。
基本原理
实现这一效果的核心在于监听卡片的拖动事件:
1. 使用movable-view
组件作为卡片容器
2. 监听onTouchStart
获取初始触摸位置
3. 监听onChange
获取拖动过程中的位置变化
4. 监听onTouchEnd
判断最终滑动方向
......
实现步骤
1. 基础拖动实现
首先创建一个可拖动的卡片组件:
<MovableArea style={{width: '100%', height: '100%'}}>
<MovableView
direction="all"
onTouchStart={this.handleTouchStart}
onChange={this.handleChange}
onTouchEnd={this.handleTouchEnd}
>
{/ 卡片内容 /}
</MovableView>
</MovableArea>
// 触发方法,打印参数 onChange(e) { console.log('参数',e); } ......
2. 事件处理逻辑
处理触摸开始事件,记录初始位置:
<--中间加入图片之类的滑动内容-->
handleTouchStart = (e) => {
此处所设定的起始横坐标,正是基于事件触发的瞬间,根据客户端上第一个触摸点所对应的横坐标值来确定的。
}
state = { x: '16', y: '16', like: false, unlike: false, shopList: [ { img: 'https://edgefix-image.edgecom.top/ABD846F6672997A7F76CD38E8A57F954.jpg', }, { img: 'https://edgefix-image.edgecom.top/F6E5801C304CC76DA63C02C9FB38B8F4.jpg', }, { img: 'https://edgefix-image.edgecom.top/D518952AD1DD61B2D32556E20CC527C4.jpg', }, { img: 'https://edgefix-image.edgecom.top/1D187E28B349679908A44BBE81F3D3CA.jpg', }, { img: 'https://edgefix-image.edgecom.top/1129A411AC9CF5F81187CBED181B6F57.jpg', } ] }
3. 滑动方向判断
在触摸结束时判断滑动方向:
handleTouchEnd = (e) => {
endX的数值与事件e的changedTouches数组中的第一个元素的clientX属性值相对应。
定义变量deltaX,其值由endX与this.startX的差值确定。
if(deltaX > 50) { // 右滑
this.likeAction()
// 触摸触发onTouchStart(e) { console.log('222',e.touches[0].pageX); this.setState({ x: e.touches[0].pageX, y: e.touches[0].pageY, }); } // 触摸移动 onTouchMove(e) { console.log('333',e.touches[0].pageX); let dx = e.touches[0].pageX - this.state.x; if (dx > 50) { this.setState({ like: true, unlike: false, }); } else if (dx < -50) { this.setState({ like: false, unlike: true, }); } else { this.setState({ like: false, unlike: false, }); } } // 取消 onCancel(e) { console.log('444',e.changedTouches[0].pageX); this.setState({ x: '16', y: '16', like: false, unlike: false, }); }
} else if(deltaX < -50) { // 左滑
} else { // 回弹效果
// 恢复原位
}
style={{transform:'rotate('+this.state.tiltAngle[index]+'deg)'}}
}
<b>4. 多卡片处理</b>
当有多张卡片时,需要为每张卡片维护独立的状态:
state = {
cards: [
该记录编号为1,其横坐标和纵坐标均为0,且未标记为喜爱。
// ...
]
}
// 拖动后相差距离进行换算角度 let dxangle = (e.touches[0].pageX - this.state.startX) * 45 / 500;
优化与注意事项
1. 性能优化
使用key
属性确保卡片渲染效率
避免不必要的状态更新
2. 动画效果
可以添加过渡动画使滑动更加自然:
.movable-view {
过渡效果:实现0.3秒的平滑变化;
}
3. 常见问题
确保MovableArea
有足够的空间
state = { // 开始位置 startX: '', // 开始位置-最终位置距离 placeX: '', // 倾斜角度 tiltAngle: ['0','0','0','0','0'], // 坐标 x: ['16','16','16','16','16'], y: ['16','16','16','16','16'], // 是否喜欢状态 like: [false,false,false,false,false], unlike: [false,false,false,false,false], // 推荐商品数组 shopList: [ { id: 1, img: 'https://edgefix-image.edgecom.top/ABD846F6672997A7F76CD38E8A57F954.jpg', }, { id: 2, img: 'https://edgefix-image.edgecom.top/F6E5801C304CC76DA63C02C9FB38B8F4.jpg', }, { id: 3, img: 'https://edgefix-image.edgecom.top/D518952AD1DD61B2D32556E20CC527C4.jpg', }, { id: 4, img: 'https://edgefix-image.edgecom.top/1D187E28B349679908A44BBE81F3D3CA.jpg', }, { id: 5, img: 'https://edgefix-image.edgecom.top/1129A411AC9CF5F81187CBED181B6F57.jpg', } ] }
注意z-index层级关系
处理边界情况,如最后一张卡片
完整示例代码
在引入Taro库的Component组件时,我们需借助from关键字,以明确标识该组件的来源为@tarojs/taro模块。
我们采纳了源自 '@tarojs/components' 的 View 元素、可移动区域组件以及可移动视图组件。
class SwipeCards 是由 Component 类所继承的一个子类。
state = {
cards: [
{id: 1, x: 0, y: 0},
]
}
处理触摸开始事件 = (事件对象, 索引值) => {
const { cards } = this.state
在index所指定的卡片实体中,对startX属性进行赋值操作,该值应与事件e的changedTouches数组中的第一个元素所对应的clientX坐标相一致。
this.setState({ cards })
endX数值与事件对象的changedTouches数组中第一个元素的clientX属性所承载的信息相吻合。
定义deltaX变量,其数值应当等于endX减去cards数组中index位置对应的startX属性值。
if(Math.abs(deltaX) > 50) {
if(deltaX > 0) {
// 调用喜欢接口
} else {
}
// 移除当前卡片
cards.splice(index, 1)
// 恢复原位
cards[index].x = 0
}
}
render() {
return (
<View className='container'>
在state.cards数组里,每一项都必须经过.map()函数的遍历流程,接着,每个card元素以及它对应的索引index会被逐一提取出来,并接受相应的处理措施。
<MovableArea key={card.id} className='movable-area'>
className='movable-view'
direction='all'
x={card.x}
在触控动作被激活的瞬间,系统会激活一个名为handleTouchStart的程序来处理这一情况,并且会一并传入事件本身以及相应的索引值index作为必须的参数。
{/ 卡片具体内容 /}
))}
</View>
)
}
}
// 触摸触发 onTouchStart(index,e) { console.log('1111',index,e.touches[0].pageX,e.touches[0].pageY); // 重定义数组 var againX = []; var againY = []; // 遍历,判断拖动的该数组的位置 for (var i=0; i总结
依托于Taro框架的
movable-view
组件,我们能够轻松完成小程序中卡片间的滑动操作。这一功能的实现,需要精确处理触摸操作和位置变化,同时还要关注多张卡片的状态管理以及性能的优化。此外,这种方法同样适用于其他需要类似交互功能的场景。
版权声明:本文为 “博览广文网” 原创文章,转载请附上原文出处链接及本声明;
工作时间:8:00-18:00
客服电话
0755-88186625
电子邮件
admin@lanyu.com
扫码二维码
获取最新动态