拖拽一个元素如此简单,mouse、drag、touch三兄弟的用处
最近需要做一个投票活动,上传图片时需要拖拽、缩放来裁剪图片,vue的组件不少,不过自己动手才能丰衣足食,一味使用别人的组件实在难以进步,所以自己研究一番。
一、mouse、drag、touch傻傻分不清
- mouse:pc端的鼠标按下、移动等事件
(1)、mousedown:当鼠标指针移动到元素上方,并按下鼠标按键时,会发生mousedown事件。
与 click 事件不同,mousedown 事件仅需要按键被按下,而不需要松开即可发生。mousedown()方法触发 mousedown 事件,或规定当发生mousedown事件 时运行的函数。
(2)、mouseenter:当鼠标指针穿过元素时,会发生 mouseenter 事件。
该事件大多数时候会与mouseleave事件一起使用。mouseenter()方法触发mouseenter事件,或规定当发生mouseenter事件时运行的函数。(与mouseover事件不同,只有在鼠标指针穿过被选元素时,才会触mouseenter 事件。如果鼠标指针穿过任何子元素,同样会触发mouseover事件。)
(3)、mouseleave:当鼠标指针离开元素时,会发生mouseleave事件。该事件大多数时候会与mouseenter事件一起使用。
mouseleave()方法触发mouseleave事件,或规定当发生mouseleave事件时运行的函数。(与mouseout事件不同,只有在鼠标指针离开被选元素时,才会触发mouseleave事件。如果鼠标指针离开任何子元素,同样会触发mouseout事件。)
(4)、mousemove:当鼠标指针在指定的元素中移动时,就会发生mousemove事件。
mousemove()方法触发mousemove事件,或规定当发生mousemove事件时运行的函数。(注意:用户把鼠标移动一个像素,就会发生一次mousemove事件。处理所有 mousemove 事件会耗费系 统资源。请谨慎使用该事件。)
(5)、mouseout:当鼠标指针从元素上移开时,发生mouseout事件。该事件大多数时候会与mouseover事件一起使用。
mouseout()方法触发mouseout事件,或规定当发生 mouseout 事件时运行的函数。(与mouseleave事件不同,不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。只有在鼠标指针离开被选元素时,才会触发mouseleave事件。)
(6)、mouseover:当鼠标指针位于元素上方时,会发生 mouseover 事件。该事件大多数时候会与mouseout事件一起使用。
mouseover()方法触发 mouseover 事件,或规定当发生mouseover事件时运行的函数。(与 mouseenter 事件不同,不论鼠标指针穿过被选元素或其子元素,都会触发mouseover事件。只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件。)
(7)、mouseup:当在元素上放松鼠标按钮时,会发生mouseup事件。与 click 事件不同,mouseup 事件仅需要放松按钮。当鼠标指针位于元素上方时,放松鼠标按钮就会触发该事件。mouseup()方法触发mouseup事件,或规定当发生mouseup事件时运行的函数。<div @mousedown="gMousedown" @mouseenter="gMouseenter" @mouseleave="gMouseleave" @mousemove="gMousemove" @mouseout="gMouseout" @mouseover="gMouseover" @mouseup="gMouseup"> 试一试移动 </div> methods:{ gMousedown(e){ console.log("鼠标左键按下了"); console.log(e) }, gMouseenter(e){ console.log("鼠标穿过了"); console.log(e) }, gMouseleave(e){ console.log("鼠标离开了"); console.log(e) }, gMousemove(e){ console.log("鼠标移动了"); console.log(e) }, gMouseout(e){ console.log("鼠标移开了"); console.log(e) }, gMouseover(e){ console.log("鼠标在元素上面了"); console.log(e) }, gMouseup(e){ console.log("鼠标松开了"); console.log(e) } }
- drag:pc端的鼠标事件,鼠标左键按下并且拖动
(1)、在被拖动目标上触发的事件:
ondragstart:在用户开始拖动元素或选择的文本时触发(为了让元素可拖动,需要使用draggable属性,链接和图片默认是可拖动的,不需要 draggable 属性)
ondrag:元素正在拖动时触发
ondragend:用户完成元素拖动后触发
(2)、在其他对象容器中触发的事件:
ondragenter:当被鼠标拖动的对象进入其容器范围内时触发此事件
ondragover:当某被拖动的对象在另一对象容器范围内拖动时触发此事件
ondragleave:当被鼠标拖动的对象离开其容器范围内时触发此事件
ondrop:在一个拖动过程中,释放鼠标键时触发此事件<template> <div style="margin-top: 66px;"> <div class="drag-container"> <p v-for="item in list" draggable="true" @dragstart="dragstart($event,item,'list')" @dragend="dragend($event,item)" >{{item.name}}</p> </div> <div class="drop-container"> <p>分层</p> <div class="drop-area" v-if="showLayer" @drop="drop($event,'layer')" @dragenter="dragenter" @dragover="dragover" > <p v-for="(item,index) in layer"> <span draggable="true" @dragstart="dragstart($event,item,'layer',index)" >{{item.name}}</span> <b v-if="index!==layer.length-1">-></b> </p> </div> <p>维度</p> <div class="drop-area" @drop="drop($event,'dimensions')" @dragover="dragover"> <span v-for="(item,index) in dimensions" @drop="dropToItem($event,item)" @dragover.prevent draggable="true" @dragstart="dragstart($event,item,'dimensions',index)" >{{item.name}}</span> </div> <p>对比</p> <div class="drop-area" @drop="drop($event,'contrasts')" @dragover="dragover"> <span v-for="(item,index) in contrasts" @dragover.prevent draggable="true" @dragstart="dragstart($event,item,'contrasts',index)" >{{item.name}}</span> </div> </div> </div> </template> <script> export default { data() { return { dragItem: {},//拖动的字段 dragFrom: '',//拖动从哪开始 dragIndex: '',//拖动的字段在数组中的索引 dropIndex: '',//放入地方的字段的索引 showLayer: false,//是否显示分层 isDropToItem: false,//是否是拖动到维度字段中进行分层操作 layer: [], dimensions: [], contrasts: [], list: [ { id: 1, name: '姓名' }, { id: 2, name: '性别' }, { id: 3, name: '年龄' }, { id: 4, name: '分数' }] } }, methods: { //拖拽开始 dragstart(event, item, frm, index) { console.log('拖拽开始'); console.log(event); console.log(item); console.log(frm); console.log(index); const that = this; event.dataTransfer.setData("Text", event.target.id); that.dragItem = item; that.dragFrom = frm; if (!isNaN(index)) { that.dragIndex = index; } }, //进入拖拽区域,进入时触发一次 dragenter(event) { console.log('进入拖拽区域,进入时触发一次'); console.log(event); }, //进入拖拽区域后多次触发 dragover(event) { console.log("进入拖拽区域后多次触发"); console.log(event); const that = this; event.preventDefault(); let target = event.target; that.dropIndex = that.indexFn(target); let nodeName = target.nodeName; if (nodeName !== 'SPAN') { that.dropIndex = -1; } }, //松开鼠标完成拖拽后触发 drop(event, target) { console.log('松开鼠标完成拖拽后触发'); console.log(event); console.log(target); const that = this; let dragFrom = that.dragFrom; let dragItem = that.dragItem; let dragIndex = that.dragIndex; let dropIndex = that.dropIndex; if (that.isDropToItem) { return; } if (that.dragFrom === 'layer') { that.layer.splice(dragIndex, 1); } else if (that.dragFrom === 'dimensions') { that.dimensions.splice(dragIndex, 1); } else if (that.dragFrom === 'contrasts') { that.contrasts.splice(dragIndex, 1); } if (dragFrom === target && dropIndex > -1) { let targetArr = that[target]; targetArr.splice(dropIndex, 0, dragItem); return; } if (target === 'layer') { that.layer.push(dragItem); } else if (target === 'dimensions') { that.dimensions.push(dragItem); } else if (target === 'contrasts') { that.contrasts.push(dragItem); } }, //拖动到维度第一个字段时触发 dropToItem(event, item) { console.log('拖动到维度第一个字段时触发'); console.log(event); console.log(item); const that = this; if (that.dragFrom !== 'list') { that.isDropToItem = false; return; } else { that.isDropToItem = true } if (that.showLayer) { that.layer.push(this.dragItem); } else { that.showLayer = true; that.layer.push(item); that.layer.push(this.dragItem); } }, //拖拽结束后触发,不管是否拖拽成功 dragend(event, item) { console.log('拖拽结束后触发,不管是否拖拽成功'); console.log(event); console.log(item); const that = this; that.isDropToItem = false }, //判断拖动字段的所以,用于排序 indexFn(el) { let index = 0; if (!el || !el.parentNode) { return -1; } while (el && (el = el.previousElementSibling)) { index++; } return index; }, } } </script> <style scoped lang="less"> /* css部分 */ .drag-container { width: 66px; height: 500px; float: left; background-color: #BAB5F5; p { line-height: 40px; text-align: center; cursor: pointer; } } .drop-container { margin-left: 120px; float: left; height: 500px; width: 600px; p { color: #fff; line-height: 40px; } .drop-area { height: 80px; width: 600px; background-color: #4c72ff; padding: 10px; p { display: inline-block; margin: 0; } span { display: inline-block; min-width: 50px; line-height: 40px; margin-right: 5px; background-color: #5a3e99; text-align: center; cursor: pointer; } } } </style>
-
touch:移动端的触摸事件,触发的条件是手指按在屏幕上并且移动(手指不能离开屏幕)
(1)、touchstart:当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发。
(2)、touchmove:当手指在屏幕上滑动时连续的触发。在这个事件发生期间,调用preventDefault()可阻止滚动。
(3)、touchend:当手指从屏幕上移开时触发。
(4)、touchcancel:当系统停止跟踪触摸时触发。关于此事件的确切触发事件,文档中没有明确说明。
3.1、以上event对象都包含以下属性:
(1)、touches:表示当前跟踪的触摸操作的Touch对象的数组。
(2)、targetTouches:特定于事件目标的Touch对象的数组。
(3)、changeTouches:表示自上次触摸以来发生了什么改变的Touch对象的数组。
3.2、每个Touch对象包含下列属性:
(1)、clientX:触摸目标在视口中的X坐标。
(2)、clientY:触摸目标在视口中的Y坐标。
(3)、identifier:表示触摸的唯一ID。
(4)、pageX:触摸目标在页面中的x坐标。
(5)、pageY:触摸目标在页面中的y坐标。
(6)、screenX:触摸目标在屏幕中的x坐标。
(7)、screenY:触摸目标在屏幕中的y坐标。
(8)、target:触摸的DOM节点坐标
二、运用touch实现图片手势推拽、缩放裁剪图片
-
通过touchstart和touchmove实现拖拽图片:
(1)、touchstart:获取touches[0]的pageX,pageY来更新scx与scy以及更新iX与iY
(2)、touchmovw:获取touches[0]的pageX,声明变量f1x存放,移动后的x坐标等于iX + f1x - scx,y坐标同理,最后调用_drawImage来更新图片 - 通过event.touches的数量判断是否是单指或双指实现图片缩放:
(1)、缩放后图片的宽高:图片初始宽度*缩放倍率和图片初始高度*缩放倍率
(1)、缩放倍率:首先在touchstart事件上求取两手指间的距离d1;然后在touchmove事件上继续求取两手指间的距离d2,当前缩放倍率= 初始缩放倍率 + (d2-d1) / 步长
(1)、缩放后图片左上角的坐标值:首先要找到一个缩放中心(先取双指的中点坐标,但是这个坐标必须要位于图片上,如果不在图片上,则取图片上离该中点坐标最近的点),通过等式(缩放中心x坐标 - 缩放后图片左上角x坐标)/ 缩放后图片的宽度 = (缩放中心x坐标 - 缩放前图片左上角x坐标)/ 缩放前图片的宽度;(y坐标同理) - 通过canvas画布截取画布中的图片
<template> <div class="clipper-container" ref="clipper"> <canvas ref="canvas"></canvas> <!-- 裁剪部分 --> <div class="clipper-part"> <div class="pCanvas-container"> <canvas ref="pCanvas"></canvas> </div> </div> <!-- 底部操作栏 --> <div class="action-bar"> <button class="btn-cancel" @click="cancel">取消</button> <button class="btn-ok" @click="clipper">确认</button> </div> <!-- 背景遮罩 --> <div class="mask" :class="{opacity: maskShow}"></div> <!-- 手势操作层 --> <div class="gesture-mask" ref="gesture" @touchstart="getTouchstart" @touchmove="getTouchmove" @touchend="getTouchend"></div> </div> </template> <style lang="less"> .position() { position: absolute; top: 0; bottom: 0; left: 0; right: 0; z-index: 100; } .clipper-container { .position(); line-height: 0; background-color: #000; .clipper-part { .position(); bottom: 61px; z-index: 102; .pCanvas-container { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border: 2px solid #fff; } } .action-bar { box-sizing: content-box; .position(); top: auto; z-index: 103; height: 60px; line-height: 60px; border-top: 1px solid rgba(256, 256, 256, 0.3); button { display: block; padding: 0 15px; line-height: 60px; font-size: 16px; color: #fff; background: none; border: none; outline: 0; &.btn-cancel { float: left; } &.btn-ok { float: right; } } } .mask { .position(); z-index: 101; transition: opacity 500ms; background-color: #000; opacity: 0; &.opacity { opacity: 0.8; } } .gesture-mask { .position(); bottom: 61px; z-index: 103; } } </style> <script> export default { name: 'imageTailor', props: { img: String, //url或dataUrl clipperImgWidth: { type: Number, default: 500 }, clipperImgHeight: { type: Number, default: 200 } }, watch: { img() { const that = this; that.loadImgQueue.push(that.img); that.loadImg(); } }, data() { return { originXDiff: 0, //裁剪canvas与原图canvas坐标原点上的差值 originYDiff: 0, maskShow: true, maskShowTimer: null, ctx: null, pCtx: null, actionBarHeight: 61, loadImgQueue: [], //加载图片队列 imageData: null, imgLoaded: false, imgLoading: false, imgStartWidth: null, imgStartHeight: null, imgCurrentWidth: null, imgCurrentHeight: null, imgX: null, //img对于canvas的坐标 imgY: null, imgScale: 1, //图片目前的缩放倍数 范围是1-5 imgMinScale: 1, imgMaxScale: 5, imgScaleStep: 60, //缩放步长,每60px加减0.1 //图片canvas宽高 cWidth: 0, cHeight: 0, scx:0,//对于单手操作是移动的起点坐标,对于缩放是图片距离两手指的中点最近的图标。 scy:0, iX:0, iY:0, } }, mounted() { setTimeout(() => { this.initClipper(); }, 10); }, beforeDestroy() { let getGesture = this.$refs.gesture; getGesture.ontouchstart = null; getGesture.ontouchmove = null; getGesture.outouchend = null; }, methods: { initClipper() { const that = this; that.loadImgQueue.push(that.img); that.initCanvas(); that.loadImg(); // that.initCanvas(); }, initCanvas() { const that = this; let getCanvas = that.$refs.canvas, getPCanvas = that.$refs.pCanvas, clipperClientRect = that.$refs.clipper.getBoundingClientRect(), clipperWidth = parseInt(that.clipperImgWidth / window.devicePixelRatio), clipperHeight = parseInt(that.clipperImgHeight / window.devicePixelRatio); that.ctx = getCanvas.getContext('2d'); that.pCtx = getPCanvas.getContext('2d'); //判断clipperWidth与clipperHeight有没有超过容器值 if (clipperWidth < 0 || clipperWidth > clipperClientRect.width) { clipperWidth = 250 } if (clipperHeight < 0 || clipperHeight > clipperClientRect.height) { clipperHeight = 100 } //因为canvas在手机上会被放大,因此里面的内容会模糊,这里根据手机的devicePixelRatio来放大canvas,然后再通过设置css来收缩,因此关于canvas的所有值或坐标都要乘以devicePixelRatio getCanvas.style.width = clipperClientRect.width + 'px'; getCanvas.style.height = clipperClientRect.height-50 + 'px'; getCanvas.width = that.ratio(clipperClientRect.width); getCanvas.height = that.ratio(clipperClientRect.height-50); getPCanvas.style.width = clipperWidth + 'px'; getPCanvas.style.height = clipperHeight-50 + 'px'; getPCanvas.width = that.ratio(clipperWidth); getPCanvas.height = that.ratio(clipperHeight-50); //计算两个canvas原点的x y差值 let cClientRect = getCanvas.getBoundingClientRect(), pClientRect = getPCanvas.getBoundingClientRect(); that.originXDiff = pClientRect.left - cClientRect.left; that.originYDiff = pClientRect.top - cClientRect.top; that.cWidth = cClientRect.width; that.cHeight = cClientRect.height; }, getTouchstart(event){ const that = this; let cClientRect = this.$refs.canvas.getBoundingClientRect(), fingers = {}; //记录当前有多少只手指在触控屏幕 event.preventDefault(); //two finger let figureDistance = 0; if (!that.imgLoaded) { return; } if (event.touches.length === 1) { let finger = event.touches[0]; that.scx = finger.pageX; that.scy = finger.pageY; that.iX = that.imgX; that.iY = that.imgY; fingers[finger.identifier] = finger; } else if (event.touches.length === 2) { let finger1 = event.touches[0], finger2 = event.touches[1], f1x = finger1.pageX - cClientRect.left, f1y = finger1.pageY - cClientRect.top, f2x = finger2.pageX - cClientRect.left, f2y = finger2.pageY - cClientRect.top; that.scx = parseInt((f1x + f2x) / 2); that.scy = parseInt((f1y + f2y) / 2); figureDistance = that.pointDistance(f1x, f1y, f2x, f2y); fingers[finger1.identifier] = finger1; fingers[finger2.identifier] = finger2; //判断变换中点是否在图片中,如果不是则去离图片最近的点 if (that.scx < that.imgX) { that.scx = that.imgX; } if (that.scx > that.imgX + that.imgCurrentWidth) { that.scx = that.imgX + that.imgCurrentHeight; } if (that.scy < that.imgY) { that.scy = that.imgY; } if (that.scy > that.imgY + that.imgCurrentHeight) { that.scy = that.imgY + that.imgCurrentHeight; } } }, getTouchmove(event){ const that = this; let cClientRect = that.$refs.canvas.getBoundingClientRect(), fingers = {}; //记录当前有多少只手指在触控屏幕 //two finger let figureDistance = 0, pinchScale = that.imgScale; event.preventDefault(); if (!that.imgLoaded) { return; } that.maskShowTimer && clearTimeout(that.maskShowTimer); that.maskShow = false; if (event.touches.length === 1) { let f1x = event.touches[0].pageX, f1y = event.touches[0].pageY; that.drawImage(that.iX + f1x - that.scx, that.iY + f1y - that.scy, that.imgCurrentWidth, that.imgCurrentHeight); } else if (event.touches.length === 2) { let finger1 = event.touches[0], finger2 = event.touches[1], f1x = finger1.pageX - cClientRect.left, f1y = finger1.pageY - cClientRect.top, f2x = finger2.pageX - cClientRect.left, f2y = finger2.pageY - cClientRect.top, newFigureDistance = that.pointDistance(f1x, f1y, f2x, f2y), scale = that.imgScale + parseFloat(((newFigureDistance - figureDistance) / that.imgScaleStep).toFixed(1)); fingers[finger1.identifier] = finger1; fingers[finger2.identifier] = finger2; if (scale !== pinchScale) { //目前缩放的最小比例是1,最大是5 if (scale < that.imgMinScale) { scale = that.imgMinScale; } else if (scale > that.imgMaxScale) { scale = that.imgMaxScale; } pinchScale = scale; that.scale(that.scx, that.scy, scale); } } }, getTouchend(event){ const that = this; let fingers = {}; //记录当前有多少只手指在触控屏幕 //two finger let pinchScale = that.imgScale; if (!that.imgLoaded) { return; } that.imgScale = pinchScale; //从finger删除已经离开的手指 let touches = Array.prototype.slice.call(event.changedTouches, 0); touches.forEach(item => { delete fingers[item.identifier]; }); //迭代fingers,如果存在finger则更新scx,scy,iX,iY,因为可能缩放后立即单指拖动 let i, fingerArr = []; for(i in fingers) { if (fingers.hasOwnProperty(i)) { fingerArr.push(fingers[i]); } } if (fingerArr.length > 0) { that.scx = fingerArr[0].pageX; that.scy = fingerArr[0].pageY; } else { that.maskShowTimer = setTimeout(() => { that.maskShow = true; }, 300); } //做边界值检测 let x = that.imgX, y = that.imgY, pClientRect = that.$refs.pCanvas.getBoundingClientRect(); if (x > pClientRect.left + pClientRect.width) { x = pClientRect.left } else if (x + that.imgCurrentWidth < pClientRect.left) { x = pClientRect.left + pClientRect.width - that.imgCurrentWidth; } if (y > pClientRect.top + pClientRect.height) { y = pClientRect.top; } else if (y + that.imgCurrentHeight < pClientRect.top) { y = pClientRect.top + pClientRect.height - that.imgCurrentHeight; } if (that.imgX !== x || that.imgY !== y) { that.drawImage(x, y, that.imgCurrentWidth, that.imgCurrentHeight); } }, loadImg() { const that = this; if (that.imgLoading || that.loadImgQueue.length === 0) { return; } let img = that.loadImgQueue.shift(); if (!img) { return; } let newImage = new Image(), onLoad = e => { newImage.removeEventListener('load', onLoad, false); that.imageData = newImage; that.imgLoaded = true; that.imgLoading = false; that.initImg(newImage.width, newImage.height); that.loadImg(); }, onError = e => { newImage.removeEventListener('error', onError, false); that.imageData = newImage = null; that.imgLoading = false; that.loadImg(); }; that.imgLoading = true; that.imgLoaded = false; newImage.src = that.img; newImage.crossOrigin = 'Anonymous'; //因为canvas toDataUrl不能操作未经允许的跨域图片,这需要服务器设置Access-Control-Allow-Origin头 newImage.addEventListener('load', onLoad, false); newImage.addEventListener('error', onError, false); }, initImg(w, h) { const that = this; let eW = null, eH = null, maxW = that.cWidth, maxH = that.cHeight - that.actionBarHeight; //如果图片的宽高都少于容器的宽高,则不做处理 if (w <= maxW && h <= maxH) { eW = w; eH = h; } else if (w > maxW && h <= maxH) { eW = maxW; eH = parseInt(h / w * maxW); } else if (w <= maxW && h > maxH) { eW = parseInt(w / h * maxH); eH = maxH; } else { //判断是横图还是竖图 if (h > w) { eW = parseInt(w / h * maxH); eH = maxH; } else { eW = maxW; eH = parseInt(h / w * maxW); } } if (eW <= maxW && eH <= maxH) { //记录其初始化的宽高,日后的缩放功能以此值为基础 that.imgStartWidth = eW; that.imgStartHeight = eH; that.drawImage((maxW - eW) / 2, (maxH - eH) / 2, eW, eH); } else { that.initImg(eW, eH); } }, drawImage(x, y, w, h) { const that = this; that.clearCanvas(); that.imgX = parseInt(x); that.imgY = parseInt(y); that.imgCurrentWidth = parseInt(w); that.imgCurrentHeight = parseInt(h); //更新canvas that.ctx.drawImage(that.imageData, that.ratio(x), that.ratio(y), that.ratio(w), that.ratio(h)); //更新pCanvas,只需要减去两个canvas坐标原点对应的差值即可 this.pCtx.drawImage(this.imageData, this.ratio(x - this.originXDiff), this.ratio(y - this.originYDiff), this.ratio(w), this.ratio(h)); }, clearCanvas() { const that = this; let getCanvas = that.$refs.canvas, getPCanvas = that.$refs.pCanvas; getCanvas.width = getCanvas.width; getCanvas.height = getCanvas.height; getPCanvas.width = getPCanvas.width; getPCanvas.height = getPCanvas.height; }, ratio(size) { return parseInt(window.devicePixelRatio * size); }, pointDistance(x1, y1, x2, y2) { return parseInt(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))); }, scale(x, y, scale) { const that = this; let newPicWidth = parseInt(that.imgStartWidth * scale), newPicHeight = parseInt(that.imgStartHeight * scale), newIX = parseInt(x - newPicWidth * (x - that.imgX) / that.imgCurrentWidth), newIY = parseInt(y - newPicHeight * (y - that.imgY) / that.imgCurrentHeight); that.drawImage(newIX, newIY, newPicWidth, newPicHeight); }, clipper() { const that = this; let imgData = null; try { imgData = that.$refs.pCanvas.toDataURL(); } catch (e) { console.error('请在response header加上Access-Control-Allow-Origin,否则canvas无法裁剪未经许可的跨域图片'); } this.$emit('getNewImage', imgData); }, cancel() { this.$emit('cancel'); }, getBase64(dataURL) { return dataURL.replace(/^data:image\/(png|jpg);base64,/, ''); } } } </script>
最后,ε=(´ο`*)))唉路漫漫其修远兮,我这只后端的小菜鸟在前端的路上还要奋力向前,不说了接着接收运营大佬的神仙建议去了~~