本文根据插件vue-drag-verify修改后实现。
插件本身不支持vue3中使用npm i 的方式引入,如果直接引入的话会报错,所以需要在gitlab(GitHub - w3cpress/vue-drag-verify: vue滑块验证组件,图片验证组件,图片旋转验证组件)根据需要下载对应的文件(要翻墙才能下载哦)然后放在components中当普通的组件引入即可
本次开发下载的是dragVerify.vue文件,但由于vue-drag-verify传参的方式是.sync,vue3已经不再使用这个方法,所以对组件进行了调整:
<template>
<div
ref="dragVerify"
class="drag_verify"
:style="dragVerifyStyle"
@mousemove="dragMoving"
@mouseup="dragFinish"
@mouseleave="dragFinish"
@touchmove="dragMoving"
@touchend="dragFinish"
>
<div
class="dv_progress_bar"
:class="{goFirst2:isOk}"
ref="progressBar"
:style="progressBarStyle"
>
</div>
<div
class="dv_text"
:style="textStyle"
ref="messageRef"
>
<slot
name="textBefore"
v-if="$slots.textBefore"
></slot>
{{message}}
<slot
name="textAfter"
v-if="$slots.textAfter"
></slot>
</div>
<div
class="dv_handler dv_handler_bg"
:class="{goFirst:isOk}"
@mousedown="dragStart"
@touchstart="dragStart"
ref="handler"
:style="handlerStyle"
>
<IconFont :type="value ? successIcon : handlerIcon"/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, toRefs, onMounted, computed } from 'vue'
import { MouseEvent } from '@vue/runtime-dom'
const emit = defineEmits(['handlerMove', 'update:value', 'passCallback'])
interface PropsType {
value: boolean
width?: number
height?: number
text?: string
successText?: string
background?: string
progressBarBg?: string
completedBg?: string
circle?: boolean
radius?: string
handlerIcon?: string
successIcon?: string
handlerBg?: string
textSize?: string
textColor?: string
}
const props = withDefaults(defineProps<PropsType>(), {
value: false,
width: 250,
height: 40,
text: "swiping to the right side",
successText: 'success',
background: '#eee',
progressBarBg: '#134bec',
completedBg: '#134bec',
circle: false,
radius: '4px',
handlerIcon: 'icongengduo',
successIcon: 'iconxiala-yuan',
handlerBg: '#fff',
textSize: '14px',
textColor: '#333',
})
interface stateType {
isMoving: boolean
x: number
isOk: boolean
}
const state = reactive(<stateType>{
isMoving: false,
x: 0,
isOk: false
})
const { isMoving, x, isOk } = toRefs(state)
const dragVerify = ref()
const messageRef = ref()
const handler = ref()
const progressBar = ref()
onMounted(() => {
dragVerify.value?.style.setProperty("--textColor", props.textColor);
dragVerify.value?.style.setProperty("--width", Math.floor(props.width / 2) + "px");
dragVerify.value?.style.setProperty("--pwidth", -Math.floor(props.width / 2) + "px");
})
const handlerStyle = {
left: "0",
width: props.height + "px",
height: props.height + "px",
background: props.handlerBg
}
const dragVerifyStyle = {
width: props.width + "px",
height: props.height + "px",
lineHeight: props.height + "px",
background: props.background,
borderRadius: props.circle ? props.height / 2 + "px" : props.radius
}
const progressBarStyle = {
background: props.progressBarBg,
height: props.height + "px",
borderRadius: props.circle
? props.height / 2 + "px 0 0 " + props.height / 2 + "px"
: props.radius
}
const textStyle = {
height: props.height + "px",
width: props.width + "px",
fontSize: props.textSize
}
const message = computed(() => {
return props.value ? props.successText : props.text
})
const dragStart = (e: MouseEvent) => {
console.log(!props.value, 'dragStart')
if (!props.value) {
state.isMoving = true
handler.value.style.transition = 'none'
state.x =
(e.pageX || e.touches[0].pageX) -
parseInt(handler.value.style.left.replace("px", ""), 10)
}
emit("handlerMove")
}
const dragMoving = (e: MouseEvent) => {
if (state.isMoving && !props.value) {
var _x = (e.pageX || e.touches[0].pageX) - state.x;
if (_x > 0 && _x <= props.width - props.height) {
handler.value.style.left = _x + "px";
progressBar.value.style.width = _x + props.height / 2 + "px";
} else if (_x > props.width - props.height) {
handler.value.style.left = props.width - props.height + "px";
progressBar.value.style.width = props.width - props.height / 2 + "px";
passVerify()
}
}
}
const dragFinish = (e: MouseEvent) => {
if (state.isMoving && !props.value) {
var _x = (e.pageX || e.changedTouches[0].pageX) - state.x;
if (_x < props.width - props.height) {
state.isOk = true
handler.value.style.left = "0";
handler.value.style.transition = 'all 0.2s'
progressBar.value.style.width = "0"
state.isOk = false
} else {
handler.value.style.transition = 'none'
handler.value.style.left = props.width - props.height + "px";
progressBar.value.style.width = props.width - props.height / 2 + "px";
passVerify()
}
state.isMoving = false
}
}
const passVerify = () => {
emit("update:value", true)
state.isMoving = false;
progressBar.value.style.background = props.completedBg
messageRef.value.style["-webkit-text-fill-color"] = "unset";
messageRef.value.style.animation = "slidetounlock2 3s infinite";
messageRef.value.style.color = "#fff";
emit("passCallback");
}
const reset = () => {
handler.value.style.left = "0"
progressBar.value.valueFormat.style.width = "0"
handler.value.children[0].type = props.handlerIcon
messageRef.value.style["-webkit-text-fill-color"] = "transparent"
messageRef.value.style.animation = "slidetounlock 3s infinite"
messageRef.value.style.color = props.background
}
defineExpose({
reset
})
</script>
<style scoped>
.drag_verify {
position: relative;
background-color: #e8e8e8;
text-align: center;
overflow: hidden;
}
.drag_verify .dv_handler {
position: absolute;
top: 0px;
left: 0px;
cursor: move;
}
.drag_verify .dv_handler i {
color: #666;
padding-left: 0;
font-size: 16px;
}
.drag_verify .dv_handler .el-icon-circle-check {
color: #6c6;
margin-top: 9px;
}
.drag_verify .dv_progress_bar {
position: absolute;
height: 34px;
width: 0px;
}
.drag_verify .dv_text {
position: absolute;
top: 0px;
color: transparent;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
-o-user-select: none;
-ms-user-select: none;
background: -webkit-gradient(
linear,
left top,
right top,
color-stop(0, var(--textColor)),
color-stop(0.4, var(--textColor)),
color-stop(0.5, #fff),
color-stop(0.6, var(--textColor)),
color-stop(1, var(--textColor))
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-text-size-adjust: none;
animation: slidetounlock 3s infinite;
}
.drag_verify .dv_text * {
-webkit-text-fill-color: var(--textColor);
}
.goFirst {
left: 0px !important;
transition: left 0.5s;
}
.goFirst2 {
width: 0px !important;
transition: width 0.5s;
}
</style>
<style>
@-webkit-keyframes slidetounlock {
0% {
background-position: var(--pwidth) 0;
}
100% {
background-position: var(--width) 0;
}
}
@-webkit-keyframes slidetounlock2 {
0% {
background-position: var(--pwidth) 0;
}
100% {
background-position: var(--pwidth) 0;
}
}
</style>
使用方式为: