刮刮乐canvas实现

class Scratch {
        constructor(config) {
            this.config = config;
            let { clearRange, canvasId, radius } = config;
            this.moveNum = 0;
            this.clearRange = clearRange || 2;
            this.canvasId = canvasId;
            this.radius = radius || 25;
            this.canvas = $(this.canvasId);
            this.ifend = false;
            var img1 = './img/1.png';
            var img2 = './img/2.png';
            var img3 = './img/3.png';
            var img4 = './img/4.png';
            var img5 = './img/5.png';
            var img6 = './img/6.png';
            var img7 = './img/7.png';
            var img8 = './img/8.png';
            var jinbi1 = './img/jinbi1.png';
            var money1 = './img/money1.png';
            var noWin1 = [img1, img2, img3, img4, img5, img6, img7, img8, jinbi1];
            var noWin2 = [img1, img2, img3, img4, img5, img6, img7, img8, money1];
            var noWin3 = [img1, img2, img3, img4, img5, img6, img7, money1, jinbi1];
            this.noWin = this.disorder([noWin1, noWin2, noWin3])[0];
            this.getGold = [img1, img2, img3, img4, img5, img6, jinbi1, jinbi1, jinbi1];
            this.getCash = [img1, img2, img3, img4, img5, img6, money1, money1, money1];
            this.squeeBox = $('.squeegeeContent span')
            this.init();
        }
        init() {
            this.renderAct();
            this.bindEvent();
            this.renderSqueegeeBg();
        }
        bindEvent() {
            this.touchStart();
            this.touchMove();
            this.touchEnd();
        }
        winner() {
            $('.winnerPopup').css('display', 'block');
            this.getSqueeSpanBg('money1');



        }
        renderSqueegeeBg() {
            console.log(this.squeeBox)
            var arr = this.disorder(this.getCash)
            for (var i = 0; i < this.squeeBox.length; i++) {
                $(this.squeeBox[i]).css('background-image', 'url(' + arr[i] + ')')

                console.log($(this.squeeBox[i]).css('background-image'))
            }


        }
        getSqueeSpanBg(str) {
            for (var i = 0; i < this.squeeBox.length; i++) {
                console.log($(this.squeeBox[i]).css('background-image').indexOf(str) >= 0)
                if ($(this.squeeBox[i]).css('background-image').indexOf(str) >= 0) {
                    $(this.squeeBox[i]).css('background-color', 'gold')
                }
            }
        }
        disorder(arr) {
            var newArr = [];
            for (var i = 0, len = arr.length; i < len; i++) {
                var j = Math.floor(Math.random() * (len - i));
                newArr[i] = arr[j];
                arr.splice(j, 1)
            }
            return newArr;
        }
        //初始化绘画图层
        renderAct() {
            let image = new Image();
            let { wd, ht, imgurl } = this.config;
            image.onload = () => {
                [this.width, this.height] = [wd / 2, ht / 2];
                let canvas = $(this.canvasId)[0];
                canvas.width = this.width;
                canvas.height = this.height;
                if (canvas.getContext) {
                    this.ctx = canvas.getContext('2d');
                    this.ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, this.width, this.height);



                }
            };
            image.src = imgurl;
        }
        /**
         * 取消事件,以及回调
         */
        offFn() {
            this.ifend = true;
            $(this.canvasId).off('touchstart');
            $(this.canvasId).off('touchmove');
            $(this.canvasId).off('touchend');
        }
        /**
         * touchStart事件
         */
        touchStart() {
            $(document).on('touchstart', this.canvasId, () => {
                if (this.ifend) return;
                this.offset = this.canvas.offset();
                if (typeof this.config.Start === 'function') {
                    this.config.Start();
                }
            });
        }
        /**
         * touchMove事件
         */
        touchMove() {
            $(document).on('touchmove', this.canvasId, event => {
                if (this.ifend) return;
                this.rx = event.touches[0].pageX - this.offset.left;
                this.ry = event.touches[0].pageY - this.offset.top;
                this.ctx.beginPath();
                this.ctx.globalCompositeOperation = 'destination-out';

                this.ctx.arc(this.rx, this.ry, this.radius, 0, 2 * Math.PI);
                console.log(this.ctx.globalCompositeOperation)
                this.ctx.fill();
                this.moveNum++;
                // 在这里是通过像素点来计算,挂过的面积方式来的,比较好
                this.handleFilledPercentage.bind(this.handleFilledPercentage(this.getFilledPercentage()), this);
                if (typeof this.config.Move === 'function') {
                    this.config.Move();
                }
            });
        }
        /**
         * touchEnd事件
         */
        touchEnd() {
            $(document).on('touchend', this.canvasId, () => {
                if (this.ifend) return;
                if (this.moveNum > this.clearRange) {
                    // this.ctx.clearRect(0, 0, this.width, this.height);
                    if (typeof this.config.End === 'function') {
                        this.config.End();
                        this.moveNum = 0;
                    }
                }
                $(this.canvasId).off('touchstart');
                $(this.canvasId).off('touchmove');
                $(this.canvasId).off('touchend');
            });


        }
        // 计算已经刮过的区域占整个区域的百分比
        getFilledPercentage() {
            let imgData = this.ctx.getImageData(0, 0, this.width, this.height);
            console.log(imgData.data.length)
            // imgData.data是个数组,存储着指定区域每个像素点的信息,数组中4个元素表示一个像素点的rgba值
            let pixels = imgData.data;
            let transPixels = [];
            for (let i = 0; i < pixels.length; i += 4) {
                // 严格上来说,判断像素点是否透明需要判断该像素点的a值是否等于0,
                // 为了提高计算效率,这儿设置当a值小于128,也就是半透明状态时就可以了
                if (pixels[i + 3] === 0) {
                    transPixels.push(pixels[i + 3]);
                }
            }
            console.log((transPixels.length / (pixels.length / 4) * 100).toFixed(2))
            return (transPixels.length / (pixels.length / 4) * 100).toFixed(2) + '%'
        }
        // 设置阈值,去除灰色涂层
        handleFilledPercentage(percentage) {
            console.log(123)
            this.percentage = percentage || 0;
            if (parseInt(this.percentage) > 50) {
                // 当像素点的个数超过  50% 时,清空画布,显示底图
                // ctx.clearRect(0, 0, width, height);
                $("#squeegeeContentPopup").hide();
                this.winner();

            }
        }
    }
    //配置刮刮卡
    new Scratch({
        canvasId: '#squeegeeContentPopup',
        wd: '600',
        ht: '600',
        imgurl: `./img/body_bg.jpg`,
        Move() {
            // document.addEventListener(endEvtName, function () {

            // }, false)
        },
        Start() {

        },
        End() {
            
        }
    });
原文地址:https://www.cnblogs.com/bigkuan/p/13043705.html