UNPKG

captain-ui

Version:

有赞vue wap业务组件库

254 lines (219 loc) 7.01 kB
"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;