<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()" />
效果:
手機端:
睡覺。。。
。