作者:金豪杰
前言
初学鸿蒙技术不久,就想自己试着实现一下swipe组件。 当组件绑定autoplay属性为true时 , 即可开启自动播放,也可以左右移动图片,并且会修改自动播放的播放方向。
效果演示
实现思路
1.布局思路
通过对内外层盒子定位(父相子绝),外层盒子对溢出的内容进行隐藏,调整每个小盒子的left值来显示不同的图片内容。
2.移动实现
//初始化赋值
onReady() {
setTimeout(()=>{
//获取组件宽度
this.clientWidth=this.$refs.moveBox.getBoundingClientRect().width;
let screenWidth=this.clientWidth;
//设置 spacing值
this.spacing=this.clientWidth/4;
if(!(this.imgArr instanceof Array)) return;
//初始化 传入的图片数组
this.arr = [
this.imgArr[this.imgArr.length - 2],
this.imgArr[this.imgArr.length - 1],
...this.imgArr,
this.imgArr[0],
];
//初始化left值
this.leftArr=this.arr.map((item,id)=> (-2+id)*screenWidth);
//备份 整体位置
this.leftArrCopy=[...this.leftArr];
//是否开启自动播放
this.autoplay && this.autoPlay();
},100)
//初始化修改图片数组
},
//手指点下
moveStart(e) {
//记录手指点下的起始位置
this.startPoint = e.touches[0].localX;
//记录固定的起始数据
this.startPointCopy=this.startPoint;
//开放事件
this.pointerEvent=true;
clearInterval(this.auto);
this.auto=null;
},
//手指移动
move(e) {
//移动的距离
this.newX = e.touches[0].localX - this.startPoint;
//重置起点
this.startPoint=e.touches[0].localX;
//改变整体的left值 随着手指移动
this.leftArr=this.leftArr.map((item)=> item+this.newX);
},
//手指松开
moveEnd() {
//计算移动了的距离
let direction=this.startPoint-this.startPointCopy;
//判断移动的距离是否大于spacing值
if (Math.abs(direction) > this.spacing) {
//根据newX值判断方向
if (this.newX < 0) {
//向右
this.index++;
this.direction=1;
} else {
//向左
this.index--;
this.direction=-1;
}
//开始移动
this.startMove();
}else{
//没有超过spacing 则回弹
//确定回弹方向
this.direction=this.newX>0? -1:1;
//回弹移动
this.moveBack();
}
},
// 移动距离过小 开始回弹
moveBack(){
this.timer=setInterval(()=>{
this.sec+=this.direction;
//移动距离累计和
this.oldNum=this.sec+this.oldNum;
//改变整体left值
this.leftArr=this.leftArr.map((item)=> parseInt(item+this.sec));
//累计和大于移动距离时 图片回弹
if(Math.abs(this.oldNum)>=Math.abs(this.startPoint-this.startPointCopy)){
//根据index改变left值 从而显示对应图片
this.leftArr=this.leftArrCopy.map((item,id)=> (-2+id- this.index)*this.clientWidth);
this.stopMove();
//移动结束后 是否开启自动播放
this.autoplay && this.autoPlay();
}
},20)
},
//开始移动
startMove(){
//计算剩余所需移动的距离
let a=this.clientWidth-Math.abs(this.startPoint-this.startPointCopy);
this.timer=setInterval(()=>{
this.changeLeft();
//当累计和大于等于剩余所需移动的距离时
if(Math.abs(this.oldNum)>=Math.abs(a)){
//图片归位
this.comeBack();
//图片归位后开启自动播放
this.autoplay && this.autoPlay();
}
},10);
},
changeLeft(){
//每次移动的距离
this.sec-=this.direction;
//移动距离累计和
this.oldNum=this.sec+this.oldNum;
//改变整体left值
this.leftArr=this.leftArr.map((item)=> parseInt(item+this.sec));
},
//位置判断
comeBack(){
//到达右边界回归原位
this.num=this.index;
if (this.index === this.arr.length - 4 ) {
this.index=-1;
this.num=this.imgArr.length - 1;
}
//到达左边界回归原位
if (this.index === -2 ) {
this.index=this.arr.length - 5;
this.num=this.imgArr.length - 2;
}
if(this.index===-1){
this.num=this.imgArr.length - 1;
}
//改变left值
this.leftArr=this.leftArrCopy.map((item,id)=> (-2+id-this.index)*this.clientWidth);
this.stopMove();
},
3.自动播放
autoPlay(){
this.auto=setInterval(()=>{
//根据移动方向改变index值
this.index=this.index+this.direction;
this.timer=setInterval(()=>{
this.changeLeft();
//当累计和大于等于容器宽时 图片不在移动
if(Math.abs(this.oldNum)>=this.clientWidth){
this.comeBack();
//清除数据
this.stopMove();
}
},10);
},this.timing)
},
使用方法
引入swipe组件
<element name="swipea" src="../../common/swipea/swipea"></element>
<swipea img-arr="{{arr}}" autoplay="true"></swipea>
在data中挂载图片路径数据并传入到swipe组件中
arr: [
'/common/images/a1.jpg',
'/common/images/a2.jpg',
'/common/images/a3.jpg',
'/common/images/a4.jpg'
]
属性
属性名 | 类型 | 默认值 | 作用 |
---|---|---|---|
imgArr | Array | -- | 图片路径(必传项) |
liColor | String | 'red' | 底部激活状态颜色 |
swipeHeight | Number | 250 | 组件高度 |
autoplay | Boolean | false | 是否开启自动播放 |
timing | Number | 2000 | 播放间隔时间 |
swipe组件可传值
//图片路径(必传项)
props:{
imgArr: {
type:Array,
default:[]
},
//底部激活状态颜色
liColor:{
type:String,
default:'red'
},
//组件高度
swipeHeight:{
type:Number,
default:250
},
//是否开启自动播放
autoplay:{
type:Boolean,
default:false
},
//播放间隔
timing:{
type:Number,
default:2000
}
},
总结:
1.onReady生命周期中无法直接获取到dom元素,可以使用定时器来获取。
2.鸿蒙中无法直接获取dom元素的style属性 。
3.只有6以上的版本才支持transition属性,而且只支持个别属性拥有渐变效果 。
4.overflow属性好像并不支持,我就改用clip-path属性,它可以对不同区域进行裁剪。
源码地址
https://gitee.com/xiaojin1233323/harmonyos-swipe.git
更多原创内容请关注:中软国际 HarmonyOS 技术团队
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
https://ost.51cto.com/#bkwz
::: hljs-center
:::