图片-滑动-解锁-组件-vue-canvas
2023-09-11 14:19:39 时间
<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()" />
效果:
手机端:
睡觉。。。
。
相关文章
- [转] vue中父子组件通信
- [转] vue 自定义组件使用v-model
- 【css/vue】Vue组件中对body操作样式的一种解决方案
- 【Vue】通过自定义组件事件绑定,让【父组件】获取【子组件】的值(emit方式,图文+代码示例)
- 【Vue】单文件的组件(.vue)代码实例
- 【Vue】第一个Vue例子Hello Vue(图文+完整示例)
- 从入口文件找到Vue构造函数
- Vue - 判断终端是否为:IE内核、opera内核、苹果、谷歌内核、火狐内核、是否为移动终端、ios终端、android终端、是否为iPhone或者QQHD浏览器、是否iPad、是否微信、是否QQ
- vue 试图改变子组件props 属性值时,控制台报错解决方案
- Vue项目--FLoor组件的实现
- vue 父组件如何调用子组件的函数Methods
- Vue 组件之间传值
- vue.js-详解三大流行框架VUE_快速进阶前端大咖-Vue基础
- Web前端-Vue.js必备框架(四)
- vue报错 :NavigationDuplicated {_name: "NavigationDuplicated", name: "NavigationDuplicated"}
- vue 的组件查找
- vue开发组件并发包到npm
- vue中全局组件与局部组件的注册,以及动态绑定props值
- vue+electron 打包后刷新,页面空白
- VUE高阶组件解析
- Vue表单和组件
- springboot+vue家具销售电商平台(源码+文档)
- 如何使用@vue/cli 3.0在npm上创建,发布和使用你自己的Vue.js组件库
- 前端技术:vue(Vue项目中-axios设置默认请求地址和请求头)
- 怎么在Vue项目中使用Element组件
- Vue结合Element-UI 实现双击单元格编辑
- 剖析 Vue.js 内部运行机制 (1)
- uniapp 微信小程序无法获取Vue.prototype的值
- vue 钟表功能:动态显示实时时间(时间格式化插件dayjs)