<template>
<div class="captcha_drop" >
<div class="modal_popup" >
<div class="captcha-box">
<div class="captcha_header">
安全验证
</div>
<div class="captcha-inner">
<img :src="shadeImage" class="captcha-img" ref="captchaImg">
<img :src="verImg" class="block verify_img" :style="{left:posx+'px',top:posY+'px'}" alt="">
</div>
<div class="sliderContainer" :class="validateStatus" ref="sliderContainter">
<div class="sliderbg"></div>
<div class="sliderMask" :style="{width: posx+'px'}">
<div class="slider" ref="right_btn" :style="{left:posx+'px'}"
@touchstart.stop.prevent="touchstart"
@touchmove.stop.prevent="touchmove"
@touchend.stop.prevent="touchend">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 20">
<path fill="#B3B5B7" d="M21.7 10.2l-11.6 9c-.2.2-.5.1-.7-.1-.1-.1-.1-.2-.1-.3v-4.5c0-.3-.2-.5-.5-.5H.7c-.3 0-.5-.2-.5-.5V6.4c0-.3.2-.5.5-.5h8.1c.3 0 .5-.2.5-.5V.8c0-.3.2-.5.5-.5.1 0 .2 0 .3.1l11.6 9c.2.2.2.5 0 .8.1-.1 0 0 0 0z"></path>
</svg>
</div>
</div>
<span class="sliderText">{{text}}</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "verSlider",
data() {
return {
posx:0,
imgBgVisible: false,
refreshVisible: false,
canDrag:false,
startTime:'',
endTime:'',
position:{
left:0,
},
text:'按住左边按钮拖动完成上方拼图',//再试一次
move:{
posx:0//差值
},
maxWidth:0,//最大宽度
sliderW:0,
validateStatus:'',
verImgH:0,//校验图片高
imgRatio:1,
}
},
computed: {},
props:{
verImg:{
type:String,
default:''
},
posY:{
default:0
},
shadeImage:{
type:String,
default:''
},
isSuccess:{
type:String,
default:''//'false','true'
},
refresh:{
type:String,
default:new Date().getTime().toString()
},
},
created() {
},
mounted() {
this.maxWidth=this.$refs.sliderContainter&&this.$refs.sliderContainter.offsetWidth;
this.sliderW=this.$refs.right_btn&&this.$refs.right_btn.offsetWidth
},
methods: {
touchstart(e){
if(!this.canDrag){
this.startTime=e.timeStamp;
this.positionOld=this.getPosition(this.$refs.right_btn);
this.position={...this.positionOld};
this.inset={
left:e.targetTouches[0].clientX - this.positionOld.left,
}
this.canDrag=true;
this.validateStatus='sliderContainer_active'
}
},
touchmove(e){
if(this.canDrag){
let left=e.targetTouches[0].clientX-this.inset.left ;
if(left<0){
left=0
}else if(left>this.maxWidth - this.sliderW){
left=this.maxWidth- this.sliderW;
}
this.posx=left;
this.move.posx=left-this.positionOld.left;
this.position = {left};
}
},
touchend(e){
if(this.canDrag){
this.endTime=e.timeStamp;
if(this.endTime-this.startTime>500|| Math.abs(this.move.posx) > 2 ){
this.$emit('validate',{x:parseInt(this.posx)})
//debugger
}else{
this.posx=-1;
this.validateStatus='';
this.canDrag=false
}
}
},
/*重置*/
resetStatus(){
this.inset={};
this.move={};
this.position={};
this.posx=0;
this.canDrag=false;
this.validateStatus='';
this.text='再试一次'
},
getPosition(source){
let left=source.offsetLeft;
let current=source.offsetParent;
while (current=null){
left+=current.offsetLeft;
}
return{
left,
}
}
},
watch:{
refresh(newValue,oldValue){
if(this.isSuccess==='false'){
this.validateStatus='sliderContainer_fail';
setTimeout(()=>{
this.resetStatus();
},1000)
}else if(this.isSuccess==='true'){
this.validateStatus='sliderContainer_success';
}
},
}
}
</script>
<style scoped lang="scss">
div,img,span{
margin:0px;
padding:0px;
}
$h:35Px;
.block {
position: absolute;
left: 0;
top: 0;
}
.sliderContainer {
position: relative;
text-align: center;
line-height:$h;
height:$h;
background: #f7f9fa;
color: #45494c;
border-radius: 2px;
margin:20px auto;
}
.sliderbg {
position: absolute;
left: 0;
right: 0;
top: 0;
background-color: #f7f9fa;
height: $h;
border-radius: 2px;
border: 1Px solid #e6e8eb;
}
.sliderContainer_active{
.slider {
top: -1Px;
border: 1Px solid #1991FA;
}
.sliderMask {
border-width: 1Px 0 1Px 1Px;
}
}
.sliderContainer_success{
.slider {
top: -1Px;
border: 1Px solid #52CCBA;
}
.sliderMask {
border: 1Px solid #52CCBA;
border-width: 1Px 0 1Px 1Px;
background-color: #D2F4EF;
}
}
.sliderContainer_fail {
.slider {
top: -1Px;
border: 1Px solid #f57a7a;
}
}
.sliderContainer_fail{
.sliderMask {
border: 1Px solid #f57a7a;
background-color: #fce1e1;
border-width: 1Px 0 1Px 1Px;
}
}
.sliderContainer_active .sliderText, .sliderContainer_success .sliderText, .sliderContainer_fail .sliderText {
display: none;
}
.sliderMask {
position: absolute;
left: 0;
top: 0;
height: $h;
border: 0 solid #1991FA;
background: #D1E9FE;
border-radius: 2Px;
}
.slider {
position: absolute;
top: 1Px;
left: 0;
width: $h;
height: $h;
background: #fff;
box-shadow: 0 0 3Px rgba(0, 0, 0, 0.3);
cursor: pointer;
transition: background .2s linear;
border-radius: 2Px;
display: flex;
align-items: center;
justify-content: center;
svg {
display: block;
width: 60%;
height: 60%;
font-size: unset;
}
}
.sliderText {
position: relative;
font-size:13Px;
text-align:center;
color: #999
}
.captcha-box{
width:312Px;
padding:0px 6Px;
margin:0px auto;
position: relative;
box-sizing: border-box;
}
.captcha-inner{
position:relative;
width:100%;
overflow: hidden;
min-height:200Px;
}
.captcha-img{
max-width:300Px;
vertical-align: top;
}
.originImage{
position:absolute;
left:0px;
right:0px;
visibility: hidden;
width:auto;
height:auto;
}
.captcha_drop {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0,0,0,.5);
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: 1000;
-webkit-tap-highlight-color: transparent;
}
.modal_popup{
position: absolute;
z-index: 9999;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
background:#f8f8f8;
border-radius: 4Px;
overflow: hidden;
}
.captcha_header{
font-size: 15Px;
line-height: 40Px;
height: 40Px;
color: #333;
text-align: center;
position: relative;
}
</style>
vue图形验证码滑动组件
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
相关阅读更多精彩内容
- <template> <!-- --> </template> exportdefault{ name:'SId...