uniapp滑动验证登录
先展示本次的效果,已经封装成组件想用的小伙伴可以直接使用
use.vue
<template>
<view style="height: 100vh;">
<sliderzz @change="change"></sliderzz>
</view>
</template>
<script>
import sliderzz from './sliderzz.vue'
export default {
components: {
sliderzz
},
methods: {
change({finish,reset}) { //这里有两个函数一般滑动都是要校验之后才能提交的,所以第一个finish知行之后他会提交
finish();//保存提交状态
// setTimeout(() => {
// reset();//这个是提交之后过一会可能会重新提交进入重置状态
// },2000)
},
}
}
</script>
sliderzz.vue
<template>
<view class="react" id="react">
<view :style="{width:width+'px',backgroundColor:'#65B58A'}" class="left kong">{{
title
}}</view>
<view :style="{left:width+'px'}" @touchstart="start" @touchmove="move" @touchend="end" id="slider"
:class="{slider:true,select:title}">
<image v-if="!title" src="https://i-blog.csdnimg.cn/blog_migrate/f52b1d8dfbc5c8bb7df2e8610bc4de25.png#pic_center" mode="widthFix"></image>
<!-- 这是两张图片一个是大于号一个是对号-->
<image v-else src="https://i-blog.csdnimg.cn/blog_migrate/3de484a9f2d56dfb6cd8e4e278b1714c.png#pic_center" mode="widthFix"></image>
</view>
<view class="right kong">
右滑提交
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: "",//划过之后的标题
width: 0,//滑到多宽
reactWidth: 0,//整个矩形的宽度
sliderWidth: 0,//滑块宽度
startX:0,//开始触摸距离屏幕左面的位置
sendFlag:false,//是否发送
finishFlag: false, //是否允许滑动 判断是否滑动完成
moveFlag:false,//是否执行滑动函数
}
},
mounted() {
let selectFc = uni.createSelectorQuery().in(this)
selectFc.select('#react').boundingClientRect((data) => {//获取总宽度
this.reactWidth = data.width-2;//矩形宽度去掉边框宽度
}).exec()
selectFc.select('#slider').boundingClientRect((data) => {//获取滑块的宽度
this.sliderWidth = data.width;
}).exec()
},
methods: {
start(e) {//开始的触摸
let {
clientX,
clientY
} = e.touches[0];
this.startX = clientX;//记录按下时刻距离屏幕左侧的距离
this.moveFlag = true;//允许滑动
},
reset() {//重置划款状态
this.sendFlag = false;
this.finishFlag = false;
this.width = 0;
this.title = "";
},
finish() {//划款完成状态
this.finishFlag = true;
this.title = "已提交";
},
move(e) {//划款移动中
if(!this.moveFlag) return;
if (this.width >= (this.reactWidth - this.sliderWidth)) {
if(!this.sendFlag){//到达最后面后就不允许他在滑动了,不然他会跳动体验比较差,所以加了限制
this.moveFlag = false;
this.sendFlag = true;
this.$emit("change", {
finish: this.finish.bind(this),
reset: this.reset.bind(this)
})//此时划款正好完成达到最右侧
}
} else {
let {
clientX,
clientY
} = e.touches[0];
var width = clientX - this.startX;//下面判断要是小0就不能在滑动,要是大于最大长度也要停止
if (width >= (this.reactWidth - this.sliderWidth)) {
width = this.reactWidth - this.sliderWidth
}else if(width<=0){
width = 0
}
this.width = width;
}
},
end(e) {//滑块结束时刻
this.moveFlag = true;
if(this.finishFlag){//完成状态
if (this.width < (this.reactWidth - this.sliderWidth)) {
this.width = 0;
}
}else{//没有完成每次都要重置
this.reset();
}
}
},
}
</script>
<style lang="scss" scoped>
.react {
margin: 0 auto;
width: 287rpx;
height: 60rpx;
box-sizing: content-box;
border: 1px solid #0E57A1;
display: flex;
align-items: center;
position: relative;
.sliderYuan{
position: absolute;
width: 100%;
left: 0;
top: 50%;
margin: 0;
transform: translate(0,-50%);
}
.slider {
width: 60rpx;
height: 60rpx;
background: #0E57A1;
display: flex;
align-items: center;
justify-content: center;
position: relative;
&.select {
background: #FFFFFF;
}
image {
display: block;
width: 29rpx;
height: auto;
}
}
.kong {
text-align: center;
line-height: 60rpx;
font-size: 22rpx;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
letter-spacing: 1rpx;
&.right {
flex: 1;
color: #0E57A1;
}
&.left {
position: absolute;
left: 1;
top: 0;
z-index: 10;
height: 60rpx;
color: #FFFFFF;
}
}
}
</style>
这里我介绍下我的思路,我用了三个div一个是滑动的时候绿色的div一个是正常情况下灰色的div还有个滑块
通过定位控制左侧div的宽度和滑块left属性保证他的滑动变化