uni-app小程序利用动画做出左右滑动切换的效果
需求:场景类似驾校刷题,手指从左往右大幅度滑动切换至上一题,手指从右往左大幅度滑动切换至下一题。已答题目直接显示正确与否和答案状态,所选答案不存在后端,后端只保存该题是否答过、答对还是答错的状态。获取题目时避免多次前后端交互,故做成分页形式:交互一次获取10道题目。思考:直接做切换页面虽然效果正确,但是相邻题作答状态无法保留。原本想过使用uView轮播图swiper或者类型组件来做,但是实现后出现
需求:场景类似驾校刷题,手指从左往右大幅度滑动切换至上一题,手指从右往左大幅度滑动切换至下一题。已答题目直接显示正确与否和答案状态,所选答案不存在后端,后端只保存该题是否答过、答对还是答错的状态。获取题目时避免多次前后端交互,故做成分页形式:交互一次获取10道题目。
思考:直接做切换页面虽然效果正确,但是相邻题作答状态无法保留。原本想过使用uView轮播图swiper或者类型组件来做,但是实现后出现两个问题:1.轮播一般是针对图片,且切换时可在两个轮播对象间停留,切换时中间状态可见,即会出现两道题都显示一部分的状态,用户体验感不佳;2.轮播必须事先存在页面元素,即至少页面上要写3个相同的轮播元素,再根据切换更换数据,页面效率不佳。所以,在既想完成滑页效果且不能看见中间状态,又不想浪费代码篇幅给重复的滑块元素而是直接做数据的切换,才最终选择了利用动画。
做法:给中间题目view添加动画实例和touch事件,当符合滑动条件则开启滑动动画,并在动画过程中切换题目数据。
动画官网API:uni-app官网
尤其要注意“.step()”的使用,如果两个动画写在一起表示动画同时发生,如“....translateX(0).opacity(1)”即同时进行平移和透明度设为1,如果在动画间只用了step(),则表示动画间的停顿,如“...translateX('100%').step().opacity(0)”即先平移,平移完成后再透明设为0.
<view :animation="animationData"
class="p-body"
@touchstart="touchstart"
@touchend="touchend"
>
<!-- 题型&来源 -->
<view class="p-subhead">
<text class="p-type">
{{ queType === 1 ? '多选' : queType === 10 ? '判断' : '单选' }}题
</text>
<view>
<u-icon v-if="pageType === 'wrong'" name="remove" custom-prefix="custom-icon"
color="#202020" size="38" class="mr-40" @click="showDeleteModal = true" />
<u-icon :name="ifCollect === 1 ? 'star-fill' : 'star'"
:color="ifCollect === 1 ? '#F7B500' : '#202020'"
size="38" @click="handleCollection" />
</view>
</view>
<!-- 题干&附加文字 -->
<view class="practice-question">
<p>{{ queTitle }}</p>
<p v-if="queSubtitle !== ''" class="practice-addtext">{{ queSubtitle }}</p>
</view>
</view>
<script>
export default {
name: 'Practice',
data() {
return {
animationData: {} // 动画
}
},
onLoad(option) {
// 创建动画实例
this.animation = uni.createAnimation({ timingFunction: 'ease', duration: 120 })
},
methods: {
// 触摸滑动开始
touchstart(e) {
this.startX = e.changedTouches[0].clientX // 触摸起点
},
// 触摸滑动结束
touchend(e) {
this.endX = e.changedTouches[0].clientX // 触摸终点
const subX = this.endX - this.startX // 触摸滑动距离
if (subX > 100) { // 手指大幅度从左向右滑动---上一题
// 非第一题有动画
if (this.queNum !== 1) {
// 动画:右出左进
this.animation.translateX('100%').step() 先横向向右移至100%,即整块移没
.opacity(0).step({ duration: 10 }) 再使题目部分透明
.translateX('-100%').step({ duration: 10 }) 然后趁透明横向向左移至-100%
.translateX(0).opacity(1).step() 接着横向向右移动至初始位置并恢复透明度
this.animationData = this.animation.export() 动态动画
// 为避免uniapp动画只有第一次生效,必须延迟删除动画实例数据
setTimeout(() => { this.animationData = {} }, 250)
}
// 上一题
this.lastQue()
} else if (subX < -100) { // 手指大幅度从右向左滑动---下一题
// 非最后一题有动画
if (this.queNum !== this.queSum) {
// 动画:左出右进
this.animation.translateX('-100%').step()
.opacity(0).step({ duration: 10 })
.translateX('100%').step({ duration: 10 })
.translateX(0).opacity(1).step()
this.animationData = this.animation.export()
setTimeout(() => { this.animationData = {} }, 250)
}
// 下一题
this.passQue()
}
},
...
}
更多推荐
所有评论(0)