canvas-scratch-card
Version:
scratch card plugin base on Canvas,Compatible with pc and mobile
147 lines (145 loc) • 4.06 kB
JavaScript
const isMobile = () => {
return 'ontouchstart' in window;
};
export const canvasCard = {
img: null,
cvs: null,
cxt: null,
tempcvs: null,
tempcxt: null,
isDown: false,
r: null,
rate: 0.5,
isMobile: true,
eventStrat: 'touchstart',
eventMove: 'touchmove',
eventEnd: 'touchend',
foos: null,
foom: null,
fooe: null,
init({ dom, image, r = 20, rate = 0.5, callback = () => {} }) {
//判断平台
if (!isMobile()) {
//PC
this.isMobile = false;
this.eventStrat = 'mousedown';
this.eventMove = 'mousemove';
this.eventEnd = 'mouseup';
}
this.callback = callback;
let that = this;
let img = new Image();
img.onload = function () {
let canvas = document.createElement('canvas');
let tempcanvas = document.createElement('canvas');
canvas.style.cssText = 'width: 100%; height: 100%;';
tempcanvas.width = canvas.width = dom.offsetWidth;
tempcanvas.height = canvas.height = dom.offsetHeight;
dom.innerHTML = null;
dom.appendChild(canvas);
that.tempcvs = tempcanvas;
that.cvs = canvas;
that.tempcxt = tempcanvas.getContext('2d');
that.cxt = canvas.getContext('2d');
that.r = r;
that.rate = rate;
that.img = img;
that.draw(img);
};
img.onerror = function () {
console.error('img load fail. -- canvasCard.js');
};
img.src = typeof image === 'string' ? image : image.src;
},
callback() {},
draw(img) {
let that = this;
this.tempcxt.fillStyle = '#000';
this.tempcxt.fillRect(0, 0, this.tempcvs.width, this.tempcvs.height);
this.cxt.drawImage(img, 0, 0, this.cvs.width, this.cvs.height);
// event
this.foos = function (e) {
that.start(e);
};
this.foom = function (e) {
that.move(e);
};
this.fooe = function (e) {
that.end(e);
};
this.cvs.addEventListener(this.eventStrat, this.foos, { passive: false });
this.cvs.addEventListener(this.eventMove, this.foom, { passive: false });
this.cvs.addEventListener(this.eventEnd, this.fooe, { passive: false });
},
start(e) {
e.preventDefault();
this.isDown = true;
let pot = this.getBound(e);
this.clip(pot.x, pot.y, this.r);
},
move(e) {
e.preventDefault();
if (this.isDown) {
let pot = this.getBound(e);
this.clip(pot.x, pot.y, this.r);
}
},
end() {
this.isDown = false;
if (this.cale() > this.cvs.width * this.cvs.height * this.rate) {
this.callback();
}
},
getBound(e) {
let point = { x: 0, y: 0 };
let { left, top } = this.cvs.getBoundingClientRect();
if (this.isMobile) {
point.x = Math.round(e.touches[0].pageX - left);
point.y = Math.round(e.touches[0].pageY - top);
} else {
point.x = Math.round(e.clientX - left);
point.y = Math.round(e.clientY - top);
}
return point;
},
clip(x, y, r) {
this.cxt.save();
this.cxt.beginPath();
this.cxt.arc(x, y, r, 0, 2 * Math.PI);
this.cxt.clip();
this.cxt.clearRect(x - r, y - r, x + r, y + r);
this.cxt.restore();
this.tempcxt.save();
this.tempcxt.beginPath();
this.tempcxt.arc(x, y, r, 0, 2 * Math.PI);
this.tempcxt.clip();
this.tempcxt.clearRect(x - r, y - r, x + r, y + r);
this.tempcxt.restore();
},
cale() {
let num = 0;
let imageData = this.tempcxt.getImageData(
0,
0,
this.tempcvs.width,
this.tempcvs.height
);
let pixeData = imageData.data;
for (let i = 0; i < this.tempcvs.width * this.tempcvs.height; i++) {
if (pixeData[4 * i + 3] == 0) {
num++;
}
}
return num;
},
clear() {
this.cxt.clearRect(0, 0, this.cvs.width, this.cvs.width);
this.tempcxt.clearRect(0, 0, this.tempcvs.width, this.tempcvs.width);
this.cvs.removeEventListener(this.eventStrat, this.foos);
this.cvs.removeEventListener(this.eventMove, this.foom);
this.cvs.removeEventListener(this.eventEnd, this.fooe);
},
reset() {
this.draw(this.img);
},
};