canvas实现刮刮卡效果,并输出刮奖区域百分比
闲来无聊,就像去做点以前没有做过东西,这是我的第一篇博客,如有错误还望大家谅解!
实现思路:
1.创建一个canvas元素,canvas元素背景色设为透明,背景图片设为我们想要放置的图片,记得写canvas的globalCompositeOperation = "destination-out"属性(在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的);
2.初始化canvas (fillstyle)填充为gray,然后写鼠标事件,通过获取鼠标坐标画圆(类似橡皮擦效果,我用的是arc,你也可以尝试用lineTo)
3.获取涂擦百分比,通过getImageData.data获去canvas像素点个数来计算,刮取得面积百分比(具体如下代码)
代码如下:
<!DOCTYPE> <html> <head> <meta charset="utf-8"> <!-- <meta name="viewport" content="width=device-width;initial-scale=1.0">--> <title></title> <style type="text/css"> .demo{ width: 320px;margin: 10px auto 20px; min-height: 300px; } </style> </head> <body> <div class="demo"> <canvas></canvas> </div> <script type="text/javascript"> var bodyStyle = document.body.style; bodyStyle.mozUserSelect = "none"; bodyStyle.webkitUserSelect = "none"; var img = new Image(); var canvas = document.querySelector("canvas"); canvas.style.backgroundColor = "transparent"; canvas.style.position = "absolute"; var imgs = ["https://img.alicdn.com/tfs/TB1lbi3bxz1gK0jSZSgXXavwpXa-500-418.jpg"]; var num = Math.floor(Math.random()*1); img.src = imgs[num]; img.addEventListener("load", function(){ var ctx; var w = img.width, h = img.height; var offsetX = canvas.offsetLeft, offsetY = canvas.offsetTop; var mousedown = false; function layer(ctx){ ctx.fillStyle = "gray"; ctx.fillRect(0,0,w,h); } function eventDown(e){ e.preventDefault(); mousedown = true; } function eventUp(e){ e.preventDefault(); mousedown = false; } //获取百分比 function eventMove(e){ e.preventDefault(); if(mousedown){ if(e.changedTouches){ e = e.changedTouches[e.changedTouches.length -1]; } var x = (e.clientX + document.body.scrollLeft || e.pageX) - offsetX || 0, y = (e.clientY + document.body.scrollTop || e.pageY) - offsetY || 0; with(ctx){ beginPath() arc(x,y,10,0,Math.PI * 2); fill(); console.log(getFilledPercentage()) } } } // 计算已经刮过的区域占整个区域的百分比 function getFilledPercentage() { let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height); console.log(imgData) // imgData.data是个数组,存储着指定区域每个像素点的信息,数组中4个元素表示一个像素点的rgba值 let pixels = imgData.data; console.log(pixels) let transPixels = []; for(let i = 0; i < pixels.length; i += 4) { // 严格上来说,判断像素点是否透明需要判断该像素点的a值是否等于0, // 为了提高计算效率,这儿设置当a值小于128,也就是半透明状态时就可以了 if(pixels[i + 3] < 128) { transPixels.push(pixels[i + 3]); } } // console.log(transPixels.length,pixels.length); return(transPixels.length / (pixels.length / 4) * 100).toFixed(2) + '%' } canvas.width = w; canvas.height = h; canvas.style.backgroundImage = 'url('+img.src+')'; ctx = canvas.getContext("2d"); ctx .fillStyle = "transparent"; ctx.fillRect(0, 0, w, h); layer(ctx); ctx.globalCompositeOperation = "destination-out";//在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。 canvas.addEventListener("touchstart", eventDown); canvas.addEventListener("touchend",eventUp); canvas.addEventListener('touchmove', eventMove); canvas.addEventListener("mousedown", eventDown); canvas.addEventListener("mouseup", eventUp); canvas.addEventListener("mousemove", eventMove); }) </script> </body> </html>