<template> <div> <div id="slide_unloack_wraper"> <canvas width="310" height="155" id="slide_unloack_wraper1"></canvas> <div id="slide_unloack_inner"> <canvas width="310" height="155" id="slide_unloack_inner1"></canvas> </div> </div> </div> </template> <script> export default { data(){ return{ isSuccess:false,//是否滑动成功 } }, created() { }, mounted() { // 将两张图片渲染在cavas上 var canvas = document.getElementById('slide_unloack_wraper1'); var block = document.getElementById('slide_unloack_inner1'); var canvas_ctx = canvas.getContext('2d'); var block_ctx = block.getContext('2d'); var img = document.createElement('img'); img.onload = function() { canvas_ctx.drawImage(img, 0, 0, 310, 155); block_ctx.drawImage(img, 0, 0, 310, 155); var blockWidth = w + r * 2;//滑块实际宽度 var _y = y - r * 2 + 2 // 滑块实际的y坐标 var ImageData = block_ctx.getImageData(x, _y, blockWidth, blockWidth);//拿到滑块的像素数据 block.width = blockWidth;//将滑块dom元素的宽度设置成滑块的掉 block_ctx.putImageData(ImageData, 0, _y) }; img.crossOrigin = 'Anonymous';//防止图片报跨域的错 img.src = 'http://kexiepingtaieposter.hoohui.cn//registFile/fa5df7c9-445d-4b58-97c4-ad8b86a92241/Z0134_2020033134932.jpeg?time='+ new Date();//加事件戳 防止图片报跨域的错 // 先利用clip()方法裁剪出个方块儿,让大家认识裁剪 var x = 150, y = 40, w = 42, r = 10, PI = Math.PI;//x坐标、y坐标、正方形的宽、圆的半径、圆周率(3.14...) function draw(ctx, operation) { ctx.beginPath();//拿笔 ctx.moveTo(x,y);//把笔尖点到这个点 ctx.lineTo(x+w/2,y);//笔尖画到 正方形上边线中间 ctx.arc(x+w/2,y-r+2, r,0,2*PI); //在坐标点(x+w/2,y-r+2)画一个r为半径的圆,角度开始为0,结束角度为2π,顺时针画个圆 ctx.lineTo(x+w/2,y);//笔尖移动到 正方形上边线中间 ctx.lineTo(x+w,y);//笔尖画到 正方形的上边线的右侧 ctx.lineTo(x+w,y+w/2);//笔尖再画到正方形的右边线中间点 ctx.arc(x+w+r-2,y+w/2,r,0,2*PI) //在合适的位置画个圆 ctx.lineTo(x+w,y+w/2);//笔尖画到正方形的 右边线中间点 ctx.lineTo(x+w,y+w);//笔尖画到正方形右边线的底部 ctx.lineTo(x,y+w);//再画到正方形的下边线的左侧 if(operation=='clip'){ ctx.lineTo(x,y+w/2+r); ctx.arc(x+2,y+w/2,r,0.5*PI,1.5*PI,true) //在合适的位置画个圆 true:逆时针 ctx.lineTo(x,y+w/2-r); } ctx.lineTo(x,y);//再画到正方形的起始点 形成闭环 if(operation=='clip'){ ctx.strokeStyle='black'; ctx.lineheight='1'; ctx.stroke(); } ctx.fillStyle = '#fff';//填充背景 ctx[operation](); ctx.beginPath();//重新开始画 ctx.arc(x,y+w/2, r,1.5*PI,0.5*PI) // 只需要画正方形内的半圆就行,方便背景图片的裁剪 ctx.globalCompositeOperation = "xor";//将原图遮盖出一个缺口 ctx.fill();//填充颜色 前面没加fillStyle就是白色 } draw(canvas_ctx,"fill"); draw(block_ctx,"clip"); // 绘图结束 // 添加事件 var self=this; self.$nextTick(()=>{ //一、定义了一个获取元素的方法 function getEle(selector){ return document.querySelector(selector); } //二、获取到需要用到的DOM元素 var box = getEle("#slide_unloack_wraper"),//容器 slider = getEle("#slide_unloack_inner"),//滑块 maxMoveX = box.offsetWidth- 64,//解锁可以滑动的距离 64是写死的 downX,//用于存放鼠标按下时的位置 successUnlockX=[130,170];//成功解锁活动距离 //三、给滑块添加鼠标按下事件 slider.onmousedown = mousedownHandler; slider.ontouchstart = mousedownHandler;//移动端加touchstart事件 //3.1鼠标按下事件的方法实现 function mousedownHandler(e){ slider.style.transition = ""; var e = e || window.event || e.which; downX = e.clientX ? e.clientX : e.changedTouches[0].clientX; if(!self.isSuccess){ //在鼠标按下时,分别给鼠标添加移动和松开事件 document.onmousemove = mousemoveHandler; document.onmouseup = mouseupHandler; //添加移动端对应事件 document.ontouchmove = mousemoveHandler; document.ontouchend = mouseupHandler; } }; //四、定义一个获取鼠标当前需要移动多少距离的方法 function getOffsetX(offset,min,max){ if(offset < min){ offset = min; }else if(offset > max){ offset = max; } return offset; } //3.1.1鼠标移动事件的方法实现 function mousemoveHandler(e){ var e = e || window.event || e.which; var moveX = e.clientX?e.clientX:e.changedTouches[0].clientX; var offsetX = getOffsetX(moveX - downX,0,maxMoveX); slider.style.left = offsetX + "px"; // e.preventDefault(); }; //3.1.2鼠标松开事件的方法实现 function mouseupHandler(e){ var moveX = e.clientX?e.clientX:e.changedTouches[0].clientX; var endX = getOffsetX(moveX - downX,0,maxMoveX); if(endX <= successUnlockX[1] && endX >= successUnlockX[0]){ slider.style.left = endX + "px"; success(); } if(!self.isSuccess){ slider.style.left = 0 + "px"; slider.style.transition = "left 0.5s linear"; } document.onmousemove = null; document.onmouseup = null; //移除移动端事件 document.ontouchmove = null; document.ontouchend = null; }; //五、定义一个滑块解锁成功的方法 function success(){ self.isSuccess = true; //滑动成功时,移除鼠标按下事件和鼠标移动事件 slider.onmousedown = null; document.onmousemove = null; //移除移动端事件 document.ontouchstart = null; document.ontouchmove = null; self.$emit("successUnlock"); }; }) }, methods: { }, } </script> <style scoped> #slide_unloack_wraper{ position: relative; } #slide_unloack_inner{ position: absolute; left:0; top:0; touch-action: none; } </style>
使用:
import SlideToUnlock from '@/components/slideToUnlock';
components:{SlideToUnlock},
<SlideToUnlock @successUnlock="unlockSuccess()" />
效果:
手机端:
睡觉。。。
。