<template>
<view class="slider-verify" v-if="isShow" @touchmove.stop.prevent="stopMoveHandle">
<view class="slider-verify-mask" :style="{ 'background-color': maskColor }"></view>
<view class="slider-verify-wrap" :style="{ 'background-color': wrapColor }">
<view class="slider-verify-top">
<text class="slider-verify-title">{{ title }}</text>
<view class="slider-verify-close" @click="closeHandle"
><uni-icons type="closeempty" size="20"></uni-icons
></view>
</view>
<!-- <view class="slider-verify-tips">
<text class="slider-verify-tips-text">{{ tips }}</text>
</view> -->
<view class="slider-verify-box">
<image
class="slider-verify-img"
v-if="verifyImg"
:src="verifyImg"
mode="scaleToFill"
></image>
<image class="slider-verify-img" v-else :src="VerifyCodeImg" mode="scaleToFill"></image>
<!-- 右侧用来验证的滑块 -->
<view class="slider-verify-block-verify" :style="blockVerifyStyle"></view>
<!-- 被css操控的滑块 -->
<view class="slider-verify-block-move" :style="blockMoveStyle"></view>
<!-- 手指触摸的滑块 -->
<view
class="slider-verify-block-touch"
:style="blockTouchStyle"
@touchstart="touchstartHandle"
@touchmove="touchmoveHandle"
@touchend="touchendHandle"
>
</view>
</view>
<view class="slider-verify-slider" v-if="showBottomSlider">
<!-- 被css操控的滑块 -->
<view
class="slider-verify-slider-move"
:style="sliderMoveStyle"
@touchstart="touchstartHandle"
@touchmove="touchmoveHandle"
@touchend="touchendHandle"
></view>
<!-- 手指触摸的滑块 -->
<view class="slider-verify-slider-touch" :style="sliderTouchStyle"> </view>
</view>
</view>
</view>
</template>
<script>
import VerifyCodeImg from '@/components/ComTouchVerifyCode/img/verifyImg.jpg'
export default {
name: 'SliderVerify',
emits: ['success', 'error', 'close'],
props: {
//标题
title: {
type: String,
default: 'Sliding check',
},
//提醒
// tips: {
// type: String,
// default: 'Please drag the left transparent slider into the white box',
// },
//滑块大小
slideSize: {
type: Number,
default: 50,
},
//滑块颜色
slideColor: {
type: String,
default: 'rgba(0,0,0,0.4)',
},
//遮罩层背景色
maskColor: {
type: String,
default: 'rgba(0,0,0,0.4)',
},
// 图片
verifyImg: {
type: String,
default: '',
},
//主体背景色
wrapColor: {
type: String,
default: '#ffffff',
},
//校验正负差值区间像素
between: {
type: Number,
default: 10,
},
// 是否显示底部滑动条
showBottomSlider: {
type: Boolean,
default: true,
},
//底部滑块大小
bottomSlideSize: {
type: Number,
default: 40,
},
//底部滑块颜色
bottomSlideColor: {
type: String,
default: '#c33e2d',
},
},
data() {
return {
startPageX: 0, //开始距离
moveLeft: 0, //滑动距离
done: false, //是否成功
autoLeft: 80, //验证滑块随机的像素
autoTop: 80, //验证滑块随机的top像素
isShow: false,
VerifyCodeImg,
bottomSlideBg: 'rgb(195, 62, 45,.2)', //底部滑块路径背景颜色
bottomSlideborderColor: '#c33e2d', //底部滑块路径背景边框颜色
slideborderColor: '#fff',
}
},
computed: {
blockVerifyStyle() {
return `top:${this.autoTop}px;left:${this.autoLeft}px;height:${this.slideSize}px;width:${this.slideSize}px;background-color:${this.slideColor}; border: 1px ${this.slideborderColor} solid;`
},
blockMoveStyle() {
return `top:${this.autoTop}px;left:${this.moveLeft}px;height:${this.slideSize}px;width:${this.slideSize}px;background-color: ${this.slideColor};`
},
blockTouchStyle() {
return `top:${this.autoTop}px;height:${this.slideSize}px;width:${this.slideSize}px;`
},
sliderMoveStyle() {
return `left:${this.moveLeft}px;height:${this.bottomSlideSize}px;width:${this.bottomSlideSize}px;background-color: ${this.bottomSlideColor};`
},
sliderTouchStyle() {
return `height:${this.bottomSlideSize}px;width:${
this.moveLeft + this.bottomSlideSize
}px;background-color: ${this.bottomSlideBg};border:1px solid ${this.bottomSlideborderColor}`
},
},
methods: {
// 拦截其他触摸事件防止nvue下input等元素层级问题
stopMoveHandle(e) {
if (e.preventDefault) {
// 阻止页面滚动
e.preventDefault()
}
},
// 随机数
rMathfloor(min, max) {
//返回包括最大/小值
return Math.floor(Math.random() * (max - min + 1)) + min
},
// 初始化
init() {
this.moveLeft = 0
this.done = false
this.autoTop = this.rMathfloor(0, 170 - this.slideSize)
this.autoLeft = this.rMathfloor(this.slideSize + 20, 280 - this.slideSize)
this.slideborderColor = '#fff'
},
// 显示
show() {
this.isShow = true
this.init()
},
// 关闭
hide() {
this.closeHandle()
},
//按下
touchstartHandle(e) {
if (this.done) {
return
}
this.startPageX = e.changedTouches[0].pageX
},
// 滑动
touchmoveHandle(e) {
// 滑动分两个块来操作不然会有数据抖动
if (this.done) {
return
}
var left = e.changedTouches[0].pageX - this.startPageX //补偿起始位置
this.moveLeft = left
// 滑块到目标 变色
var verifyLeft = this.autoLeft + this.startPageX //补偿起始位置
var chazhi = verifyLeft - e.changedTouches[0].pageX //最终差值
if (chazhi >= 0 - this.between && chazhi <= this.between) {
this.bottomSlideBg = 'rgba(32, 194, 102, .2)'
this.bottomSlideborderColor = 'rgba(32, 194, 102, .2)'
this.slideborderColor = 'RGBA(37, 211, 102, 1)'
} else {
this.bottomSlideBg = 'rgb(195, 62, 45,.2)'
this.bottomSlideborderColor = '#c33e2d'
this.slideborderColor = 'rgb(195, 62, 45,1)'
}
},
// 滑动离开(最终)
touchendHandle(e) {
var endLeft = e.changedTouches[0].pageX
var verifyLeft = this.autoLeft + this.startPageX //补偿起始位置
var chazhi = verifyLeft - endLeft //最终差值
// 判断是否在正负差值区间
if (chazhi >= 0 - this.between && chazhi <= this.between) {
this.done = true
// 通过会执行成功和关闭
this.closeHandle()
this.$emit('success', 'success')
this.$emit('close', 'close')
} else {
this.$emit('error', 'failed')
// 失败会执行失败并重新初始化
this.init()
uni.showToast({
title: this.tips,
icon: 'none',
})
}
},
// 关闭事件
closeHandle() {
this.isShow = false
this.$emit('close', 'close')
},
},
}
</script>
<style lang="scss" scoped>
$sliderVerifyWidth: 660rpx;
.slider-verify {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.slider-verify-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.slider-verify-wrap {
width: 700rpx;
display: flex;
flex-direction: column;
position: relative;
padding: 20rpx;
border-radius: 24rpx;
background-color: #ffffff;
.slider-verify-top {
display: flex;
flex-direction: row;
align-items: center;
.slider-verify-title {
flex: 1;
color: #333;
font-size: 32rpx;
text-align: center;
margin-bottom: 30rpx;
}
.slider-verify-close {
font-size: 28rpx;
color: #333;
}
}
.slider-verify-tips {
margin-top: 12rpx;
margin-bottom: 12rpx;
.slider-verify-tips-text {
color: #999;
font-size: 28rpx;
}
}
.slider-verify-box {
position: relative;
width: $sliderVerifyWidth;
height: 360rpx;
overflow: hidden;
.slider-verify-img {
width: $sliderVerifyWidth;
height: 360rpx;
border-radius: 8rpx;
}
.slider-verify-block-verify,
.slider-verify-block-move,
.slider-verify-block-touch {
position: absolute;
left: 0px;
top: 0;
border-radius: 8rpx;
}
.slider-verify-block-verify {
/* #ifndef APP-NVUE */
box-sizing: border-box;
/* #endif */
}
}
.slider-verify-slider {
margin-top: 34rpx;
width: $sliderVerifyWidth;
background-color: rgba(0, 0, 0, 0.07);
position: relative;
overflow: hidden;
border-radius: 800rpx;
.slider-verify-slider-touch {
border-radius: 800rpx;
}
.slider-verify-slider-move {
position: absolute;
left: 0px;
top: 0px;
border-radius: 800rpx;
}
}
}
}
</style>
vue+uniapp 图片拖拉验证码插件
于 2024-09-10 18:16:37 首次发布