接到一个任务,做一个活动卡片,卡片左右滑动带动卡片上方的任务条走到对应节点:
1、卡片和任务条均为动态生成
2、卡片底部可以左右滑动
3、当一张卡片超过50%的区域展示出来后放手,定位到对应卡片
4、卡片更换完成后,上方任务轴同时更换
这个任务的主要就在数据格式的制定与滑动的判断,不是很难、用vue写的
1.首先写出一个卡片的样式,得到其宽度,获取共有多少张卡片。所有卡片放在一个div里面,div的宽度为(卡片宽度+卡片间距)*卡片数量 width:${cardcount*97}%
2.滑动开始,获取起始位置startX
滑动时,使卡片跟着滑动,transform:translateX(${cardLeft}px),滑动距离超过一个卡片的宽度时,滑动宽度为卡片的宽度
3.滑动结束时,获取结束位置endX,得到滑动的距离disX = endX - startX,判断超过卡片的50%,则滑动一个卡片,否则不滑动。如果此时是第一个卡片还要右滑,或者是最后一个卡片还要左滑,则不滑动
4.滑动一个卡片,任务轴传一个变量,改变当前任务点
核心:
cardLeft: 0, //现移动距离
startX: 0, //起始位置
endX: 0, //结束位置
nowLeft: 0, //移动时距离
disX: 0, //总移动距离
cardWidth: 0,//卡片(移动)宽度
touchStart(ev) {
ev = ev || event;
this.cardWidth = this.$refs.card.offsetWidth / this.cardcount - 10;
if (ev.touches.length === 1) {
this.startX = ev.touches[0].clientX;
}
},
touchMove(ev) {
ev = ev || event;
// 选项卡宽度
let cardWd = this.cardWidth;
if (ev.touches.length === 1) {
//滑动时距离浏览器左侧实时距离
let moveDisX = ev.touches[0].clientX;
this.disX = moveDisX - this.startX;
let absDisX = Math.abs(this.disX);
if (this.disX != 0) {
this.cardLeft = this.disX + this.nowLeft;
// 滑动超过一个卡片的距离
if (absDisX >= cardWd) {
this.cardLeft = this.nowLeft + cardWd * (this.disX / absDisX);
}
}
}
},
touchEnd(ev) {
ev = ev || event;
if (this.disX === 0) {
return;
}
//卡片宽度-滑动距离
var cardwd = this.cardWidth;
if (ev.changedTouches.length == 1) {
this.endX = ev.changedTouches[0].clientX;
this.disX = this.endX - this.startX;
//左滑到头仍要左滑 右滑到头仍要右滑,回到起点
if (
this.disX + this.nowLeft >= 0 ||
this.disX + this.nowLeft <= -cardwd * (this.cardcount - 1)
) {
this.cardLeft = this.nowLeft;
// 如果距离小于删除按钮一半,强行回到起点
} else if (Math.abs(this.disX) < cardwd / 2) {
this.cardLeft = this.nowLeft;
} else {
//大于一半 滑动到最大值
if (this.disX > 0) {
//切换任务轴
this.nowIndex--;
this.cardLeft = this.nowLeft + cardwd;
this.nowLeft = this.cardLeft;
} else {
//切换任务轴
this.nowIndex++;
this.cardLeft = this.nowLeft + cardwd * -1;
this.nowLeft = this.cardLeft;
}
}
}
}
html
<!-- 卡片列表 -->
<div class="occupied">
<div
:style="`width:${cardcount*97}%;transform:translateX(${cardLeft}px)`"
class="task_card"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
ref="card"
>
<card
class="card"
v-for="(item,index) in beginnerList"
:key="index"
:list="item"
:lock="index >= progressBar.current"
></card>
</div>
</div>
页面效果,中间为当前样式,左右任务卡各展示一点:
任务轴,完成的任务白色不透明,未完成的有一点透明度。展示那个卡片对应的原点,出现一个包裹的圈,并将此点展示在中间: