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>
原文地址:https://www.cnblogs.com/sbzf/p/11249198.html