最近需要做一個投票活動,上傳圖片時需要拖拽、縮放來裁剪圖片,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>
最後,ε=(´ο`*)))唉路漫漫其修遠兮,我這隻後端的小菜鳥在前端的路上還要奮力向前,不說了接著接收運營大佬的神仙建議去了~~