當(dāng)年喬布斯的iPhone次支持多點觸控時,確實驚艷了世人,而現(xiàn)在大部分手機(jī)都支持多點觸控,這就有了手勢這個概念,通過多點觸控,形成不同的手勢,開發(fā)者根據(jù)不同手勢,提供不同功能,比如雙指縮放,是很常見的。
iOS的多點觸摸
iOS的Safari瀏覽器是個支持多點觸摸的瀏覽器,并提供觸摸API供開發(fā)者使用,到后來Android 3也開始支持多點觸摸,各大瀏覽器也借鑒Safari提出了觸摸API,除了個別硬件支持屬性外,大致相同,這是值得慶幸的。
IE10的多點觸摸
雖然現(xiàn)在市場上WP手機(jī)越來越少,但是為了更完整的學(xué)習(xí)理解手勢知識,我們也需要進(jìn)行學(xué)習(xí)。IE10支持多點觸摸,但是其多點觸摸與iOS和Android不同,iOS和Android瀏覽器為多點觸摸提供一個包含touches數(shù)組的事件,包含所有多點觸摸對象,而IE10為多點觸摸的每一個觸摸點創(chuàng)建一個單獨的觸摸事件。
我們知道手勢很方便,用戶也很喜歡手勢,但是我們也要明白手勢并不總是能使用,有些設(shè)備或瀏覽器還是不支持的,所以我們合適的是基于普通點擊和觸摸事件交互的頁面,將手勢作為增強(qiáng)的交互,這就是通常所說的漸進(jìn)增強(qiáng)思想。
既然是要漸進(jìn)增強(qiáng),那就必須從基礎(chǔ)點擊和觸摸事件說起,點擊事件就不再多說,關(guān)于觸摸事件,之前也有一篇文章介紹過移動開發(fā)之輕觸與單擊事件,關(guān)于觸摸四種基礎(chǔ)事件和事件對象,可以查看該文章,這里就不重復(fù)了,這里要對觸摸事件的處理進(jìn)行說明。
瀏覽器兼容
通常我們在觸摸和手勢事件處理函數(shù)內(nèi)會添加CSS3動畫處理,這個時候需要進(jìn)行瀏覽器兼容處理。
var TRANSITION = 'transition'; var TRANSITION_END = 'transitionend'; var TRANSFORM = 'transform'; var TRANSFORM_PROPERTY = 'transform'; var TRANSITION_PROPERTY = 'transition'; if (typeof document.body.style.webkitTransform !== undefined) {
TRANSFORM = 'webkitTransform';
TRANSITION = 'webkitTransition';
TRANSITION_END = 'webkitTransitionEnd';
TRANSFORM_PROPERTY = '-webkit-transform';
TRANSITION_PROPERTY = '-webkit-transition';
}
在移動端手勢事件中,雙指縮放的需求還是很常見的,本節(jié)詳細(xì)闡述,現(xiàn)在大多數(shù)移動設(shè)備都支持原生的雙指縮放,但是這樣可能影響頁面布局,而且為了更多可控性,很多時候還是會選擇自行實現(xiàn)縮放手勢功能。
縮放中心
在原生縮放動畫,縮放中心通常是圖像中心,可以拿起移動設(shè)備嘗試一番,而在現(xiàn)實需求中,我們通常希望縮放以手勢屏幕的兩個接觸點中心為中心,即縮放中心為接觸點中心。
變換原點
在CSS3動畫中,如,transform動畫旋轉(zhuǎn),縮放等動畫,有一個transform-origin屬性:
The transform-origin property lets you modify the origin for transformations of an element.
transform-origin屬性使得我們可以修改一個元素變換動畫的原點。
當(dāng)我們使用CSS3變換動畫進(jìn)行縮放時,由于變換動畫的變換原點和縮放中心(即接觸點中心)相互獨立,為了不影響縮放中心相對于元素的位置,元素變換縮放時,也應(yīng)該對縮放中心坐標(biāo)進(jìn)行縮放移動,即除了變換縮放元素,還應(yīng)該對該元素進(jìn)行額外坐標(biāo)偏移。
位移偏量
我們希望縮放以接觸點中心為中心,元素向四周縮放,假設(shè)變換原點為元素左上角,即transform-origin: 0 0;,此時元素變換縮放位移均為正值,僅向右下方向縮放,所以縮放中心(其實也就是該元素)應(yīng)對應(yīng)向相反方向(左上方向)偏移,值為縮放坐標(biāo)值 * (1 - 縮放比例)。
如上圖,原始元素A盒,以接觸點M,N兩點的中心點L(x, y)為縮放中心點,向四周縮放,其位置應(yīng)該如圖中C盒,由于L(x, y)點的位置是不可控的(用戶行為),我們設(shè)置元素變換原點transform-origin: 0 0;,此時其縮放后位置如B盒,然而我們依然希望達(dá)到縮放后形成C盒的位移效果,則我們需要將元素向左上方向位移,假設(shè)縮放比例為k, 則元素位移值計算過程如下:
L(x, y)點,在縮放前坐標(biāo)系中坐標(biāo)為(x, y),則縮放k倍后,其在縮放后坐標(biāo)系中坐標(biāo)為(kx, ky);
禁止原生縮放
要使用自行實現(xiàn)的縮放手勢,我們需要首先禁止元素縮放手勢,使用user-scalable=no:
<meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0,user-scalable=no">
縮放與滾動
我們自行實現(xiàn)的縮放事件需要使用touchmove事件,而touchmove事件會觸發(fā)設(shè)備的滾動事件,所以要么阻止?jié)L動,要么不讓屏幕出現(xiàn)滾動條。
阻止?jié)L動
document.addEventListener('touchmove', function(event){ event.preventDefault();
})
阻止?jié)L動條
html, body { height: 100%; }
計算縮放中心
縮放動畫以接觸點為中心,當(dāng)我們使用雙指手勢實現(xiàn)縮放時,這個接觸點中心就是兩個接觸點的中心點:
function getOrigin(first, second) {
return { x: (first.x + second.x) / 2, y: (first.y + second.y) / 2 }; }
getOrigin({ x: event.touches[0].pageX, y: event.touches[0].pageY }, { x: event.touches[1].pageX, y: event.touches[1].pageY });
計算縮放比例
縮放比例如何確定呢,起始觸摸兩指間距離除以縮放時兩指間距離,即縮放比例:
function getDistance(start, stop) { return Math.sqrt(Math.pow((stop.x - start.x), 2) + Math.pow((stop.y - start.y), 2));
} function getScale(start, stop) { return getDistance(start[0], start[1]) / getDistance(stop[0], stop[1]);
}
處理觸摸事件
要實現(xiàn)縮放功能除了計算相關(guān)縮放中心和縮放比例,另外還需要處理觸摸事件:
var distance = {};
var origin;
var scale = 1;
function handleTouch(e) { switch(e.type) { case 'touchstart': if (e.touches.length > 1) {
distance.start = getDistance({
x: e.touches[0].screenX,
y: e.touches[0].screenY
}, {
x: e.touches[1].screenX,
y: e.touches[1].screenY
});
} break; case 'touchmove': if (e.touches.length === 2) {
origin = getOrigin({
x: event.touches[0].pageX,
y: event.touches[0].pageY
}, {
x: event.touches[1].pageX,
y: event.touches[1].pageY
});
distance.stop = getDistance({
x: e.touches[0].screenX,
y: e.touches[0].screenY
}, {
x: e.touches[1].screenX,
y: e.touches[1].screenY
}); scale = distance.stop / distance.start;
setScaleAnimation(scale, true);
} break; case 'touchend': scale = 1;
setScaleAnimation(scale); break; case 'touchcancel': scale = 1;
setScaleAnimation(scale); break; default:;
}
}
使用變換
接下來就是使用CSS3動畫縮放圖片了,代碼如下:
function setScaleAnimation(scale, animation) { var transition_animation = ''; var x, y; if (animation) {
transition_animation = 'none';
} else {
transition_animation = TRANSFORM_PROPERTY + ' 0.3s ease-out';
}
element.style[TRANSITION] = transition_animation; // 計算位移偏量 x = origin.x + (-origin.x) * scale;// 縮放中心偏移量 y = origin.y + (-origin.y) * scale; // 縮放和位移 element.style[TRANSFORM] = 'matrix(' + scale + ', 0, 0, ' + scale + ', ' + x + ', ' + y + ')';
}
本文關(guān)于移動開發(fā)手勢及實現(xiàn)雙指縮放介紹到此完結(jié),實現(xiàn)的實例比較粗糙,但原理基本闡述清楚,感興趣可以自己動手實現(xiàn),優(yōu)化;本文很久以前就開篇了,但直到今天才終于完筆,若有不足,也歡迎指正。
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個個人學(xué)習(xí)交流的平臺,網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對作者和來源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請及時聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對此聲明的最終解釋權(quán)。