用vue作移動端開發過程當中,須要手勢操做。由於vue-touch目前不支持vue2.0,因此本身寫了幾個手勢。html
myTouch.js >> export default(Vue) => { Vue.directive('touch', { bind: function (el, binding, vnode) { let type = binding.arg; // 傳入點擊的類型 let coordinate = {} // 記錄座標點的對象 let timeOutTap; let timeOutLong; let scaleSize; // 縮放尺寸 let displacement = {}; //移動的位移 // 勾股定理計算距離 function getDistance(bg, end){ return Math.sqrt(Math.pow((end.x - bg.x),2 ) + Math.pow((end.y - bg.y),2 )); } // 點擊開始的時候 el.addEventListener('touchstart', function(e){ // 獲取第一個手指點擊的座標 let x = e.touches[0].pageX; let y = e.touches[0].pageY; // 若是點擊的時間很長,那麼點擊的類型就是長按 --- longTouch timeOutLong = setTimeout(() => { timeOutLong = 0; if(type === 'longTouch'){ binding.value.func(binding.value.param) } }, 2000) timeOutTap = setTimeout(() => { timeOutTap = 0; if(type === 'tap' && e.touches.length === 1){ binding.value.func(binding.value.param) } }, 200) // 若是是兩個手指,並且類型是縮放 --- scaleTocuh if(e.touches.length > 1 && type === 'scaleTouch'){ // 記錄雙指的間距長度 coordinate.start = getDistance({ x: e.touches[0].pageX, y: e.touches[0].pageY, },{ x: e.touches[1].pageX, y: e.touches[1].pageY, }) } // 若是是移動的話,還要記錄下來最開始的位置,只能一個手指位移 if(type === 'slideTouch' && e.touches.length == 1){ // debugger displacement.start = { x: e.touches[0].pageX, y: e.touches[0].pageY, } } }, false) el.addEventListener('touchmove', function(e){ clearTimeout(timeOutTap) clearTimeout(timeOutLong) timeOutTap = 0; timeOutLong = 0; // 若是是縮放類型 if(type == 'scaleTouch' && e.touches.length === 2){ // 計算移動過程當中的兩個手指的距離 coordinate.stop = getDistance({ x: e.touches[0].pageX, y: e.touches[0].pageY, },{ x: e.touches[1].pageX, y: e.touches[1].pageY, }) // 設置縮放尺寸 scaleSize = (coordinate.stop / coordinate.start) - 1; // 這裏設置圖片不能無限放大與縮小 // 這裏設置放大縮小速度慢一點,因此 /4一下 binding.value.func(scaleSize / 2, false) } // 若是是移動類型 if(type == 'slideTouch' && e.touches.length === 1 ){ displacement.end = { x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY, } binding.value.func({x:displacement.end.x - displacement.start.x, y: displacement.end.y - displacement.start.y, is_endMove : false}) } }, false) el.addEventListener('touchend', function(e){ if(type === 'scaleTouch'){ binding.value.func(0, true) } if(type === 'slideTouch'){ binding.value.func({x:0, y: 0, is_endMove : true}) } }, false) } }) }
html: <img :src="picUrl" class="modal_content" v-touch:scaleTouch = "{func: scalePic, param: ''}" v-touch:slideTouch = "{func: movePic, param: ''}" /> vue: main.js >> import myTouch from './myTouch' myTouch(Vue) app.vue >> data:function () { return{ baseLeft : 0, baseTop: 0, bodyWidth: document.body.clientWidth, ele: null, // 不能在這裏設置, dom尚未生成 } },
scalePic: function(param, is_endScale){ this.ele =document.getElementsByClassName('modal_content')[0]; // 這個應該在圖片顯示的時候設置 let nodeStyle = this.ele.style.transform; let changeSize = nodeStyle ? parseFloat(nodeStyle.slice(nodeStyle.indexOf('scale')+6)) : 0; if(is_endScale){ // 縮放圖片結束,要從新計算定位 this.setMaxdisp(changeSize,parseInt(this.ele.style.marginLeft), parseInt(this.ele.style.marginTop), 'scale') return } if(nodeStyle){ // 若是存在的話,就說明已經設置了,scale已經改變了 let currScaleSize = changeSize + param; currScaleSize > 3 ? currScaleSize = 3 : null currScaleSize < 1 ? currScaleSize = 1 : null this.ele.style.transform = 'translate(-50%, -50%) scale('+currScaleSize+','+currScaleSize+')'; }else{ // 若是不存在,就說明是第一次設置 let scale = param + 1 this.ele.style.marginLeft = '0px'; this.ele.style.marginTop = '0px'; this.ele.style.transform = 'translate(-50%, -50%) scale('+scale+','+scale+')'; } }
movePic: function(param){ if(param.is_endMove){ // 每次移動鬆開手指的時候要下次移動的基礎座標 this.baseLeft = parseInt(this.ele.style.marginLeft.slice(0, -2)); this.baseTop = parseInt(this.ele.style.marginTop.slice(0, -2)); }else{ let nodeStyle = this.ele.style.transform if(nodeStyle){ // 有這個就表示應該是移動 let currScaleSize = parseFloat(nodeStyle.slice(nodeStyle.indexOf('scale')+6)) this.setMaxdisp(currScaleSize,this.baseLeft+ param.x, this.baseTop + param.y, 'move') } } }
setMaxdisp:function(changeSize, changeX, changeY, type){ // 計算最大位移 // naturalWidth : 是圖片原始的寬度,經過比例能夠計算出當前圖片在頁面的高度 let picHeight = this.bodyWidth / (this.ele.naturalWidth / this.ele.naturalHeight); let maxTop = ( picHeight * changeSize - window.innerHeight) /2 let maxLeft = this.bodyWidth / 2 * (changeSize - 1) if(changeX >= maxLeft){ this.ele.style.marginLeft = maxLeft + 'px' }else if(changeX < -maxLeft){ this.ele.style.marginLeft = -maxLeft + 'px' }else if(type==='move'){ this.ele.style.marginLeft =changeX +'px'; } // 若是圖片當前尺寸大於屏幕尺寸,能夠移動 if(maxTop > 0){ if(changeY >= maxTop){ this.ele.style.marginTop = maxTop + 'px'; }else if(changeY < -maxTop){ this.ele.style.marginTop = -maxTop + 'px' }else if(type==='move'){ this.ele.style.marginTop = changeY+'px'; } }else if(type==='move'){ this.ele.style.marginTop = 0 +'px'; } }
在雙指放大縮小的時候,兩個手指鬆開時間不一樣,頁面就會在兩個手指鬆開的時候判斷爲點擊事件。 這個尚未解決vue
圖片不能隨意的位移。應該是在必定範圍內去位移的,因此寫了一個計算最大位移的函數,圖片位移距離應該是圖片恰好能看到的程度。經過圖片原始的寬高,以及頁面當前的寬度比例能夠計算出當前圖片在頁面的高度。而後計算出最大位移node
圖片移動或者縮小懂應該是在一個基礎數據上去增長減小,若是沒有設置這個基礎數據,會致使每次都是從1的比例來移動以及縮小,因此每次移動以及放大縮小圖片以後,都要記錄下來改變以後圖片的參數,下次改變圖片的時候都是在這個參數基礎上去改變的。bash