這篇文章將為大家詳細(xì)講解有關(guān)vue如何實現(xiàn)裁切圖片同時實現(xiàn)放大、縮小、旋轉(zhuǎn)功能,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
成都創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比惠濟(jì)網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式惠濟(jì)網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋惠濟(jì)地區(qū)。費用合理售后完善,10余年實體公司更值得信賴。Vue是一套用于構(gòu)建用戶界面的漸進(jìn)式JavaScript框架,Vue與其它大型框架的區(qū)別是,使用Vue可以自底向上逐層應(yīng)用,其核心庫只關(guān)注視圖層,方便與第三方庫和項目整合,且使用Vue可以采用單文件組件和Vue生態(tài)系統(tǒng)支持的庫開發(fā)復(fù)雜的單頁應(yīng)用。
vue實現(xiàn)裁切圖片同時實現(xiàn)放大、縮小、旋轉(zhuǎn)功能,分享給大家,具體如下:
實現(xiàn)效果:
裁切指定區(qū)域內(nèi)的圖片
旋轉(zhuǎn)圖片
放大圖片
輸出bolb 格式數(shù)據(jù) 提供給 formData 對象
效果圖
大概原理:
利用h6 FileReader 對象, 獲取 “上傳到瀏覽器的文件” ,文件形式 為base64形式, 把 base64 賦給canvas的上下文。
然后給canvas 元素上加入對(mousedown)監(jiān)聽事件。 當(dāng)用戶鼠標(biāo)左鍵在canvas按下時:
掛載對 window 對象mousemove事件 ---> 獲取 鼠標(biāo)移動x,y距離.從而操作 canvas里的圖像的位置移動。
掛載對 window 對象mouseup 事件, 清除 mousemove事件的綁定。(同時該事件觸發(fā)后會被刪除)
剩下的 放大、縮小 、 旋轉(zhuǎn) 是對 canvas 對象的操作/坐標(biāo)體系的操作。具體api詳見mdn canvas 文檔
代碼
dom.js
export const on = ({el, type, fn}) => { if (typeof window) { if (window.addEventListener) { el.addEventListener(type, fn, false) } else { el.attachEvent(`on${type}`, fn) } } } export const off = ({el, type, fn}) => { if (typeof window) { if (window.addEventListener) { el.removeEventListener(type, fn) } else { el.detachEvent(`on${type}`, fn) } } } export const once = ({el, type, fn}) => { const hyFn = (event) => { try { fn(event) } finally { off({el, type, fn: hyFn}) } } on({el, type, fn: hyFn}) } // 最后一個 export const fbTwice = ({fn, time = 300}) => { let [cTime, k] = [null, null] // 獲取當(dāng)前時間 const getTime = () => new Date().getTime() // 混合函數(shù) const hyFn = () => { const ags = argments return () => { clearTimeout(k) k = cTime = null fn(...ags) } } return () => { if (cTime == null) { k = setTimeout(hyFn(...arguments), time) cTime = getTime() } else { if ( getTime() - cTime < 0) { // 清除之前的函數(shù)堆 ---- 重新記錄 clearTimeout(k) k = null cTime = getTime() k = setTimeout(hyFn(...arguments), time) } }} } export const contains = function(parentNode, childNode) { if (parentNode.contains) { return parentNode != childNode && parentNode.contains(childNode) } else { return !!(parentNode.compareDocumentPosition(childNode) & 16) } } export const addClass = function (el, className) { if (typeof el !== "object") { console.log('el is not elem') return null } let classList = el['className'] classList = classList === '' ? [] : classList.split(/\s+/) if (classList.indexOf(className) === -1) { classList.push(className) el.className = classList.join(' ') } else { console.warn('warn className current') } } export const removeClass = function (el, className) { let classList = el['className'] classList = classList === '' ? [] : classList.split(/\s+/) classList = classList.filter(item => { return item !== className }) el.className = classList.join(' ') } export const delay = ({fn, time}) => { let oT = null let k = null return () => { // 當(dāng)前時間 let cT = new Date().getTime() const fixFn = () => { k = oT = null fn() } if (k === null) { oT = cT k = setTimeout(fixFn, time) return } if (cT - oT < time) { oT = cT clearTimeout(k) k = setTimeout(fixFn, time) } } } export const Event = function () { // 類型 this.typeList = {} } Event.prototype.on = function ({type, fn}){ if (this.typeList.hasOwnProperty(type)) { this.typeList[type].push(fn) } else { this.typeList[type] = [] this.typeList[type].push(fn) } } Event.prototype.off = function({type, fn}) { if (this.typeList.hasOwnProperty(type)) { let list = this.typeList[type] let index = list.indexOf(fn) if (index !== -1 ) { list.splice(index, 1) } } else { console.warn('not has this type') } } Event.prototype.once = function ({type, fn}) { const fixFn = () => { fn() this.off({type, fn: fixFn}) } this.on({type, fn: fixFn}) } Event.prototype.trigger = function (type){ if (this.typeList.hasOwnProperty(type)) { this.typeList[type].forEach(fn => { fn() }) } }
組件模板