vue 图片滑动验证

vue

先看效果

做的是粗糙版本,需要其他的效果,可以在原有基础上进行修改

思路

1.上半部分红色的为背景canvas,绿色的为缺失部分canvas

2.这两个canvas要在同一位置,并且为同一张背景图,随机选择图片上的一块小方格,将红色canvas的该部分填充浅色,做出缺失一块的效果,绿色canvas除了选中的方格子留下,其他部分都删除

3.绿色canvas移到最左边

4.下半部分红色部分为滑块滑动部分,蓝色部分为小滑块

5.蓝色滑块滑动时,上面绿色的canvas也要跟着滑块滑动,绿色的canvas与红色canvas部分重合,则成功,不重合滑块与绿色canvas就会回到最左边

6.刷新就是将两个canvas中的图片换成其他图片,并且将滑块和绿色canvas移动到最左边

代码部分

<template>

<div class="yazheng" ref="yanzheng">

<!-- 背景滑块 -->

<canvas ref="slideVerify" class="slide-img"></canvas>

<!-- 图片 -->

<div style="display:none">

<img ref="imgs" :src="imgList[imgIndex]"/>

</div>

<!-- 下面滑块部分 -->

<div class="slide-wrapper bg-start">

<div class="btn" ref="btn" @mousedown="mouseDown" @mouseup="mouseUp"></div>

<p class="text" ref="text">{{content}}</p>

<!-- 拖动的时候出现的绿色背景 -->

<div class="bg" ref="bg"></div>

</div>

<!-- 刷新按钮 -->

<p @click="reflesh">刷新</p>

</div>

</template>

绿色canvas部分我们选择生成canvas,然后再插入到红色canvas(ref=\'slideVerify\')的前面,如果绿色canvas是直接写上去的不是动态生成的会造成一些问题,下文我会说会有什么问题

先写滑块部分的代码

mouseDown(e) {

//滑块按下去的时候,我们要设置isDown为true,为了确保是按下滑块滑动

this.isDown = true;

//点击滑块的位置,和滑块的左端相差的距离

this.btnX = e.clientX - this.$refs.btn.offsetLeft;

},

mouseMove(e) {

//滑块左端向右边移动的距离

let moveX = e.clientX - this.btnX;

//确认滑块是在按下时拖动

if (this.isDown) {

//滑块滑动的位置,不能超过最左端和最右端,就是不能让滑块滑出去

if (this.$refs.btn.offsetLeft <= 260 && this.$refs.btn.offsetLeft >= 0) {

//滑块移动

this.$refs.btn.style.left = `${moveX}px`;

//绿色canvas移动

this.blockCanvas.style.left = `${moveX - this.imgX}px`;

//绿色背景出现,呈现出拉动的效果

this.$refs.bg.style.width = `${moveX}px`;

}

}

},

mouseUp() {

//滑块最左边部分滑动的距离

let leftX = this.$refs.btn.offsetLeft;

//绿色canvas的位置和红色canvas缺失的重合允许左右2px的误差

if (this.imgX >= leftX - 2 && this.imgX <= leftX + 2) {

this.isDown = false;

}

if (this.isDown) {

//如果滑动成功,那么滑块和绿色canvas会回到最初位置

this.$refs.btn.style.left = 0;

this.blockCanvas.style.left = `-${this.imgX}px`;

this.$refs.bg.style.width = 0;

}

this.isDown = false;

}

注意点:

由于我们点击的时候和滑块的最左边有一定的差值,如果我们每次将滑块移动的位置,都是鼠标移动的距离,就会产生滑块多移动了差值的距离,就是会移动到,下图绿色的位置,并且会导致我们的鼠标一直作用不到滑块的身上

canvas部分

//画图

imageCanvas() {

//我们要刷新的时候需要把之前生成的绿色的canvas删除,在重新创建新的canvas

this.blockCanvas ? this.blockCanvas.remove() : null

this.blockCanvas = this.createCanvas(300, 150)

this.$refs.yanzheng.insertBefore(this.blockCanvas,this.$refs.slideVerify)

let x = this.randomNumber(60, 200),

y = 40;

this.imgX = x;

console.log(\'xxxx\',x,y)

let c = this.$refs.slideVerify;

let bg = c.getContext("2d");

let img = this.$refs.imgs;

let bk = this.blockCanvas.getContext("2d");

//在两块画布上都放上相同的图片

img.onload = () => {

bg.drawImage(img, 0, 0);

bk.drawImage(img, 0, 0);

};

this.drawBlock(bg, x, y, "fill");

this.drawBlock(bk, x, y, "clip");

},

//画抠出来的方块

drawBlock(ctx, x, y, type) {

console.log(\'xxxxxxxxxxxxxxxxxxxxxxxxx\',x)

let w = 40;

ctx.beginPath();

ctx.moveTo(x, y);

ctx.lineTo(x + w, y);

ctx.lineTo(x + w, y + w);

ctx.lineTo(x, y + w);

ctx.lineTo(x, y);

ctx.lineWidth = 0;

ctx.fillStyle = "rgba(255, 255, 255, 0.5)";

ctx.strokeStyle = "rgba(255, 255, 255, 0.5)";

ctx.stroke();

ctx[type]();

ctx.globalCompositeOperation = "destination-over";

this.blockCanvas.style.left = `-${x}px`;

// console.log(this.$refs.block.style.left)

},

//刷新

refresh(){

this.clean()

this.imgIndex = this.randomNumber(0,6)

this.$refs.btn.style.left = 0;

this.$refs.bg.style.width = 0;

this.isDown = false, //鼠标是否按下

this.btnX = 0, //鼠标点击的水平位置与滑块移动水平位置的差

this.imgX = 0

this.imageCanvas(\'restore\')

},

//清空canvas

clean(){

let cxt2=this.$refs.slideVerify.getContext("2d");

cxt2.clearRect(0,0,300,150);

},

//新建canvas

createCanvas (width, height) {

const canvas = document.createElement(\'canvas\')

canvas.width = width

canvas.height = height

canvas.style.position = \'absolute\'

// canvas.style.border = \'1px solid red\'

return canvas

}

注意:


所以初始的时候绿色canvas的位置,是要根据方块随机产生的位置所决定的

之前说过不能先把绿色的canvas在html结构中写出,原因如下:

  1. clip()函数,会把不要的部分删除,就算清除画布后,刷新下次画图也只会在没删除的部分画,如下图,所以你需要在合适的时候保留没有剪切时候的画布,并在合适的时候恢复保留时候的画布

  2. 但是这个样子就会出现新的问题,会导致绿色画布中的小方格出现重影(我也不知道该怎么描述这个东西了,只能说是重影),还是图片展示下重影吧,这边偷懒了,点击图片就会刷新,没有找出合适的办法解决这个问题所以就用重新创建canvas的办法,实现了功能,如果哪位大佬有解决的办法可以留言告诉我

所有代码

SlideVerify.vue

<template>

<div class="yazheng" ref="yanzheng">

<!-- 背景滑块 -->

<canvas ref="slideVerify" class="slide-img"></canvas>

<!-- 图片 -->

<div style="display:none">

<img ref="imgs" :src="imgList[imgIndex]"/>

</div>

<!-- 下面滑块部分 -->

<div class="slide-wrapper bg-start">

<div class="btn" ref="btn" @mousedown="mouseDown" @mouseup="mouseUp"></div>

<p class="text" ref="text">{{content}}</p>

<!-- 拖动的时候出现的绿色背景 -->

<div class="bg" ref="bg"></div>

</div>

<!-- 刷新按钮 -->

<p @click="refresh">刷新</p>

</div>

</template>

<script>

export default {

name: "SlideVerify",

data() {

return {

imgIndex:0,

blockCanvas:null,

imgList:[require(\'../assets/1.jpg\'),

require(\'../assets/2.jpg\'),

require(\'../assets/3.jpg\'),

require(\'../assets/4.jpeg\'),

require(\'../assets/5.jpg\'),

require(\'../assets/6.jpg\'),],

content: "滑动滑块",

isDown: false, //鼠标是否按下

btnX: 0, //鼠标点击的水平位置与滑块移动水平位置的差

imgX: 0 //图片的水平位置

};

},

methods: {

//生成随机数字

randomNumber(min, max) {

return Math.floor(Math.random() * (max - min) + min);

},

mouseDown(e) {

//滑块按下去的时候,我们要设置isDown为true,为了确保是按下滑块滑动

this.isDown = true;

//点击滑块的位置,和滑块的左端相差的距离

this.btnX = e.clientX - this.$refs.btn.offsetLeft;

},

mouseMove(e) {

//滑块左端向右边移动的距离

let moveX = e.clientX - this.btnX;

//确认滑块是在按下时拖动

if (this.isDown) {

console.log(\'hahahhahah\',this.blockCanvas.style.left)

//滑块滑动的位置,不能超过最左端和最右端,就是不能让滑块滑出去

if (this.$refs.btn.offsetLeft <= 259 && this.$refs.btn.offsetLeft >= 0) {

console.log(moveX);

//滑块移动

this.$refs.btn.style.left = `${moveX}px`;

//绿色canvas移动

this.blockCanvas.style.left = `${moveX - this.imgX}px`;

//绿色背景出现,呈现出拉动的效果

this.$refs.bg.style.width = `${moveX}px`;

}

}

},

mouseUp() {

//滑块最左边部分滑动的距离

let leftX = this.$refs.btn.offsetLeft;

console.log(this.imgX,leftX)

//绿色canvas的位置和红色canvas缺失的重合允许左右2px的误差

if (this.imgX >= leftX - 2 && this.imgX <= leftX + 2) {

this.isDown = false;

}

if (this.isDown) {

//如果滑动成功,那么滑块和绿色canvas会回到最初位置

this.$refs.btn.style.left = 0;

this.blockCanvas.style.left = `-${this.imgX}px`;

this.$refs.bg.style.width = 0;

}

this.isDown = false;

},

//画图

imageCanvas() {

//我们要刷新的时候需要把之前生成的绿色的canvas删除,在重新创建新的canvas

this.blockCanvas ? this.blockCanvas.remove() : null

this.blockCanvas = this.createCanvas(300, 150)

this.$refs.yanzheng.insertBefore(this.blockCanvas,this.$refs.slideVerify)

let x = this.randomNumber(60, 200),

y = 40;

this.imgX = x;

console.log(\'xxxx\',x,y)

let c = this.$refs.slideVerify;

let bg = c.getContext("2d");

let img = this.$refs.imgs;

let bk = this.blockCanvas.getContext("2d");

//在两块画布上都放上相同的图片

img.onload = () => {

bg.drawImage(img, 0, 0);

bk.drawImage(img, 0, 0);

};

this.drawBlock(bg, x, y, "fill");

this.drawBlock(bk, x, y, "clip");

},

//画抠出来的方块

drawBlock(ctx, x, y, type) {

console.log(\'xxxxxxxxxxxxxxxxxxxxxxxxx\',x)

let w = 40;

ctx.beginPath();

ctx.moveTo(x, y);

ctx.lineTo(x + w, y);

ctx.lineTo(x + w, y + w);

ctx.lineTo(x, y + w);

ctx.lineTo(x, y);

ctx.lineWidth = 0;

ctx.fillStyle = "rgba(255, 255, 255, 0.5)";

ctx.strokeStyle = "rgba(255, 255, 255, 0.5)";

ctx.stroke();

ctx[type]();

ctx.globalCompositeOperation = "destination-over";

this.blockCanvas.style.left = `-${x}px`;

// console.log(this.$refs.block.style.left)

},

//刷新

refresh(){

this.clean()

this.imgIndex = this.randomNumber(0,6)

this.$refs.btn.style.left = 0;

this.$refs.bg.style.width = 0;

this.isDown = false, //鼠标是否按下

this.btnX = 0, //鼠标点击的水平位置与滑块移动水平位置的差

this.imgX = 0

this.imageCanvas(\'restore\')

},

//清空canvas

clean(){

// let cxt1=this.blockCanvas.getContext("2d");

let cxt2=this.$refs.slideVerify.getContext("2d");

// cxt1.clearRect(0,0,300,150);

cxt2.clearRect(0,0,300,150);

},

//新建canvas

createCanvas (width, height) {

const canvas = document.createElement(\'canvas\')

canvas.width = width

canvas.height = height

canvas.style.position = \'absolute\'

// canvas.style.border = \'1px solid red\'

return canvas

}

},

mounted() {

this.imgIndex = this.randomNumber(0,6)

//将移动事件绑定在document上,绑定在dom元素上会导致滑块滑的太快触发不到鼠标移动事件

document.addEventListener("mousemove", this.mouseMove);

this.imageCanvas();

}

};

</script>

<style scoped>

.yazheng {

position: relative;

width: 300px;

margin: 0 auto;

/* border: 1px solid red; */

}

.slide-wrapper {

position: relative;

width: 300px;

height: 40px;

}

.bg-start {

background: cadetblue;

}

.bg {

position: absolute;

height: 40px;

background: rgb(34, 218, 80);

}

.text {

position: absolute;

width: 100%;

height: 40px;

text-align: center;

line-height: 40px;

margin: 0;

/* z-index: 1; */

}

.text-success {

color: white;

z-index: 2;

}

.btn {

position: absolute;

width: 40px;

height: 50px;

top: -5px;

z-index: 1;

border-radius: 5px;

background: rgb(143, 145, 148);

}

</style>

如果有什么错误的地方欢迎大家指正

以上是 vue 图片滑动验证 的全部内容, 来源链接: utcz.com/z/378900.html

回到顶部