captain-ui
Version:
有赞vue wap业务组件库
254 lines (219 loc) • 7.01 kB
JavaScript
"use strict";
exports.__esModule = true;
exports.default = void 0;
var _default = {
render: function render() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c('transition', {
attrs: {
"name": "fade"
}
}, [_vm.show ? _c('div', {
staticClass: "cap-scroll-mask",
on: {
"mouseup": _vm.handleTouchend,
"touchend": _vm.handleTouchend
}
}, [_c('canvas', {
ref: "bg",
style: _vm.canvasStyle
}), _c('canvas', {
ref: "mask",
style: _vm.canvasStyle,
on: {
"mousedown": function mousedown($event) {
$event.preventDefault();
return _vm.handleTouchstart($event);
},
"mousemove": function mousemove($event) {
$event.preventDefault();
$event.stopPropagation();
return _vm.handleTouchmove($event);
},
"touchstart": function touchstart($event) {
$event.preventDefault();
return _vm.handleTouchstart($event);
},
"touchmove": function touchmove($event) {
$event.preventDefault();
$event.stopPropagation();
return _vm.handleTouchmove($event);
}
}
})]) : _vm._e()]);
},
name: 'cap-scroll-mask',
props: {
/**
* 是否有擦拭
*/
hasPageWipe: {
type: Boolean,
default: false
},
/**
* canvas蒙版图
*/
maskUrl: {
type: String,
default: 'https://img.yzcdn.cn/upload_files/no_pic.png'
},
/**
* canvas背景图
*/
bgUrl: String
},
data: function data() {
var supportTouch = 'ontouchstart' in window;
return {
show: this.hasPageWipe,
width: 0,
height: 0,
maskCtx: null,
bgCtx: null,
touchstart: false,
lastPosition: null,
stoptouch: false,
supportTouch: supportTouch
};
},
computed: {
canvasStyle: function canvasStyle() {
return {
position: 'absolute',
top: 0,
left: '50%',
width: this.width + "px",
height: '100%',
backgroundColor: 'transparent',
transform: 'translate3d(-50%, 0, 0)'
};
}
},
mounted: function mounted() {
var _this = this;
var size = document.body.getBoundingClientRect();
this.width = size.width;
this.height = size.height; // init canvas
this.init(); // bind resize
window.addEventListener('resize', function () {
_this.width = document.documentElement.clientWidth;
_this.height = document.documentElement.clientHeight;
_this.resizeCanvas(_this.$refs.mask, _this.width, _this.height);
_this.resizeCanvas(_this.$refs.bg, _this.width, _this.height);
});
},
methods: {
init: function init() {
this.bgCtx = this.bgCtx || this.$refs.bg.getContext('2d');
this.maskCtx = this.maskCtx || this.$refs.mask.getContext('2d'); // 给mask图层添加高级index
this.$refs.mask.style.zIndex = 20; // draw canvas
this.draw(this.$refs.mask, this.maskUrl).then(this.draw(this.$refs.bg, this.bgUrl));
},
resizeCanvas: function resizeCanvas(canvas, width, height) {
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').clearRect(0, 0, width, height);
},
draw: function draw(canvas, url) {
var _this2 = this;
return new Promise(function (resolve, reject) {
var img = new Image(); // eslint-disable-line
img.onload = function () {
var ctx = canvas.getContext('2d');
_this2.resizeCanvas(canvas, _this2.width, _this2.height); // set canvas config
ctx.globalAlpha = 0.98;
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, _this2.width, _this2.height); // 后面画的内容和当前重叠部分会变透明, 利用该特性实现擦拭
ctx.globalCompositeOperation = 'destination-out';
resolve();
};
img.crossOrigin = 'anonymous';
img.src = url;
});
},
/**
* @description 擦拭时绘制point,形成橡皮擦效果
* @param {number} x - x轴坐标
* @param {number} y - y轴坐标
*/
drawPoint: function drawPoint(x, y) {
this.maskCtx.beginPath();
this.maskCtx.arc(x, y, 30, 0, Math.PI * 2);
this.maskCtx.fill(); // 蒙板-路径还是记录
this.maskCtx.beginPath(); // 画笔大小
this.maskCtx.lineWidth = 60; // 前者是线的末端样式,后者是线连接处的样式---圆
this.maskCtx.lineCap = this.maskCtx.lineJoin = 'round'; // 画点
if (this.lastPosition) {
this.maskCtx.moveTo(this.lastPosition[0], this.lastPosition[1]);
}
this.maskCtx.lineTo(x, y);
this.maskCtx.stroke();
this.lastPosition = [x, y];
this.$refs.mask.style.zIndex = 21;
},
/**
* @description 计算蒙版擦拭百分比
* @param {DOMElement} ctx - 蒙版画布对象
* @param {number} width - 画布宽度
* @param {number} height - 画布高度
* @returns {string} 当前画布透明像素百分比
*/
getTransparentPercent: function getTransparentPercent(ctx, width, height) {
var imgData;
var pixelsData;
var transPixels = [];
try {
imgData = ctx.getImageData(0, 0, width, height);
pixelsData = imgData.data; // 计算画布中透明程度(4n值表示透明度)
for (var i = 0; i < pixelsData.length; i += 4) {
var alpha = pixelsData[i + 3];
if (alpha < 128) {
transPixels.push(i);
}
}
} catch (e) {
return 100;
}
return (transPixels.length / (pixelsData.length / 4) * 100).toFixed(2);
},
getEventPosition: function getEventPosition(e) {
var x = this.supportTouch ? e.touches[0].clientX : e.clientX;
var y = this.supportTouch ? e.touches[0].clientY : e.clientY;
return {
x: x,
y: y
};
},
handleTouchstart: function handleTouchstart(e) {
if (!this.stoptouch) {
var _this$getEventPositio = this.getEventPosition(e),
x = _this$getEventPositio.x,
y = _this$getEventPositio.y;
this.touchstart = true;
this.drawPoint(x, y);
}
},
handleTouchmove: function handleTouchmove(e) {
if (!this.touchstart) {
return void 0;
}
var _this$getEventPositio2 = this.getEventPosition(e),
x = _this$getEventPositio2.x,
y = _this$getEventPositio2.y;
this.drawPoint(x, y);
},
handleTouchend: function handleTouchend(e) {
this.touchstart = false;
var per = this.getTransparentPercent(this.maskCtx, this.width, this.height);
if (per >= 30) {
// 超过擦拭百分比, 去除mask
this.show = false;
this.stoptouch = true;
this.$emit('remove');
}
}
}
};
exports.default = _default;