![](https://img.haomeiwen.com/i16535515/0c4f1a61641fde89.gif)
实现思路:
主要是通过jq,canvas画布实现的,因为这里是用的别人的代码,这里主要跟大家说下怎么使用。
1.首先需要配置下jq到你的项目中
vue-cli2.0配置方法
vue-cli3.0好像直接 npm 下就可以了
2.我这边是通过mixin混合使用的别人的代码,因为这样看起来比较简洁,具体引用代码 jquery.eraser.js 看最下面
参数:
completeRatio: 0.5, //当画布被擦除50%时触发事件
size: 40, //橡皮擦大小,默认40
completeFunction: function() { //擦出百分比达到 completeRatio 标准时执行的方法
alert('谢谢参与')
}
遇到问题:
1.目前代码的遮罩层及涂刮层必须是图片,而且canvas会根据图片尺寸的大小去创建画布,因此最终的大小是根据图片尺寸生成的;结果层是不受限制的,你可以设置成图片,也可以写成标签形式;
建议把图片的尺寸和标签大小都设成 330*126像素,基本都能在移动端正常显示了
2.你会发现,我在初始化方法 this.init() 的时候添加了一个计时器,因为有时候进入页面引入的部分代码没有执行,目前我这边是加上了一个计时器才解决的。原来的代码用的是监听页面的加载 addEventListener ,但是这种方法是存在问题的
window.addEventListener('load', this.init, false)
使用页面:
<template>
<div>
<div class="container">
<!-- 涂刮蹭 -->
<img id="redux" src="@/assets/img/bb5fa12a-60a3-496c-8897-8c9190ff494b.png" />
<!-- 结果层 也可以替换成标签 -->
<!-- <img id="robot" src="@/assets/img/Tesla.jpg" /> -->
<div v-if="load" id="robot">谢谢参与</div>
</div>
<h2>{{result}}</h2>
</div>
</template>
<script>
import { jqueryEraser } from '../../assets/js/jquery.eraser'
export default {
mixins: [jqueryEraser],
data() {
return {
load: false,
result: ''
}
},
mounted() {
setTimeout(() => {
this.init()
}, 300)
},
methods: {
init(event) {
let _this = this
console.log(111)
$('#redux').eraser({
completeRatio: 0.7, //当画布被擦除50%时触发事件
size: 50, //橡皮擦大小,默认40
completeFunction: function() {
_this.result = '谢谢参与'
}
})
_this.load = true
}
}
}
</script>
<style lang="scss" scoped>
.container {
display: inline-block;
margin: 0 10%;
position: relative;
width: 330px;
height: 126px;
* {
-webkit-touch-callout: none;
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-user-select: none;
}
}
#robot {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
font-size: 50px;
font-weight: bold;
color: red;
background: rgb(238, 238, 238);
}
#redux {
position: absolute;
left: 0;
top: 0;
z-index: 9;
}
</style>
jquery.eraser.js引用代码:
export const jqueryEraser = {
mounted() {
var methods = {
init: function (options) {
return this.each(function () {
var $this = $(this),
data = $this.data('eraser');
if (!data) {
var width = $this.width(),
height = $this.height(),
pos = $this.offset(),
$canvas = $("<canvas/>"),
canvas = $canvas.get(0),
size = (options && options.size) ? options.size : 40,
completeRatio = (options && options.completeRatio) ? options.completeRatio : .7,
completeFunction = (options && options.completeFunction) ? options.completeFunction : null,
parts = [],
colParts = Math.floor(width / size),
numParts = colParts * Math.floor(height / size),
n = numParts,
ctx = canvas.getContext("2d");
console.log(width, height);
// replace target with canvas
$this.after($canvas);
canvas.id = this.id;
canvas.className = this.className;
canvas.style.position = 'absolute'
canvas.style.left = 0
canvas.style.top = 0
canvas.style.zIndex = 99
canvas.width = width;
canvas.height = height;
ctx.drawImage(this, 0, 0);
$this.remove();
// prepare context for drawing operations
ctx.globalCompositeOperation = "destination-out";
ctx.strokeStyle = 'rgba(255,0,0,255)';
ctx.lineWidth = size;
ctx.lineCap = "round";
// bind events
$canvas.bind('mousedown.eraser', methods.mouseDown);
$canvas.bind('touchstart.eraser', methods.touchStart);
$canvas.bind('touchmove.eraser', methods.touchMove);
$canvas.bind('touchend.eraser', methods.touchEnd);
// reset parts
while (n--) parts.push(1);
// store values
data = {
posX: pos.left,
posY: pos.top,
touchDown: false,
touchID: -999,
touchX: 0,
touchY: 0,
ptouchX: 0,
ptouchY: 0,
canvas: $canvas,
ctx: ctx,
w: width,
h: height,
source: this,
size: size,
parts: parts,
colParts: colParts,
numParts: numParts,
ratio: 0,
complete: false,
completeRatio: completeRatio,
completeFunction: completeFunction
};
$canvas.data('eraser', data);
// listen for resize event to update offset values
$(window).resize(function () {
var pos = $canvas.offset();
data.posX = pos.left;
data.posY = pos.top;
});
}
});
},
touchStart: function (event) {
var $this = $(this),
data = $this.data('eraser');
if (!data.touchDown) {
var t = event.originalEvent.changedTouches[0],
tx = t.pageX - data.posX,
ty = t.pageY - data.posY;
methods.evaluatePoint(data, tx, ty);
data.touchDown = true;
data.touchID = t.identifier;
data.touchX = tx;
data.touchY = ty;
event.preventDefault();
}
},
touchMove: function (event) {
var $this = $(this),
data = $this.data('eraser');
if (data.touchDown) {
var ta = event.originalEvent.changedTouches,
n = ta.length;
while (n--)
if (ta[n].identifier == data.touchID) {
var tx = ta[n].pageX - data.posX,
ty = ta[n].pageY - data.posY;
methods.evaluatePoint(data, tx, ty);
data.ctx.beginPath();
data.ctx.moveTo(data.touchX, data.touchY);
data.touchX = tx;
data.touchY = ty;
data.ctx.lineTo(data.touchX, data.touchY);
data.ctx.stroke();
event.preventDefault();
break;
}
}
},
touchEnd: function (event) {
var $this = $(this),
data = $this.data('eraser');
if (data.touchDown) {
var ta = event.originalEvent.changedTouches,
n = ta.length;
while (n--)
if (ta[n].identifier == data.touchID) {
data.touchDown = false;
event.preventDefault();
break;
}
}
},
evaluatePoint: function (data, tx, ty) {
var p = Math.floor(tx / data.size) + Math.floor(ty / data.size) * data.colParts;
if (p >= 0 && p < data.numParts) {
data.ratio += data.parts[p];
data.parts[p] = 0;
if (!data.complete) {
if (data.ratio / data.numParts >= data.completeRatio) {
data.complete = true;
if (data.completeFunction != null) data.completeFunction();
}
}
}
},
mouseDown: function (event) {
var $this = $(this),
data = $this.data('eraser'),
tx = event.pageX - data.posX,
ty = event.pageY - data.posY;
methods.evaluatePoint(data, tx, ty);
data.touchDown = true;
data.touchX = tx;
data.touchY = ty;
data.ctx.beginPath();
data.ctx.moveTo(data.touchX - 1, data.touchY);
data.ctx.lineTo(data.touchX, data.touchY);
data.ctx.stroke();
$this.bind('mousemove.eraser', methods.mouseMove);
$(document).bind('mouseup.eraser', data, methods.mouseUp);
event.preventDefault();
},
mouseMove: function (event) {
var $this = $(this),
data = $this.data('eraser'),
tx = event.pageX - data.posX,
ty = event.pageY - data.posY;
methods.evaluatePoint(data, tx, ty);
data.ctx.beginPath();
data.ctx.moveTo(data.touchX, data.touchY);
data.touchX = tx;
data.touchY = ty;
data.ctx.lineTo(data.touchX, data.touchY);
data.ctx.stroke();
event.preventDefault();
},
mouseUp: function (event) {
var data = event.data,
$this = data.canvas;
data.touchDown = false;
$this.unbind('mousemove.eraser');
$(document).unbind('mouseup.eraser');
event.preventDefault();
},
clear: function () {
var $this = $(this),
data = $this.data('eraser');
if (data) {
data.ctx.clearRect(0, 0, data.w, data.h);
var n = data.numParts;
while (n--) data.parts[n] = 0;
data.ratio = data.numParts;
data.complete = true;
if (data.completeFunction != null) data.completeFunction();
}
},
size: function (value) {
var $this = $(this),
data = $this.data('eraser');
if (data && value) {
data.size = value;
data.ctx.lineWidth = value;
}
},
reset: function () {
var $this = $(this),
data = $this.data('eraser');
if (data) {
data.ctx.globalCompositeOperation = "source-over";
data.ctx.drawImage(data.source, 0, 0);
data.ctx.globalCompositeOperation = "destination-out";
var n = data.numParts;
while (n--) data.parts[n] = 1;
data.ratio = 0;
data.complete = false;
}
}
}
$.fn.eraser = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not yet exist on jQuery.eraser');
}
};
},
}
网友评论