程序員總結:HTML5中手勢原理分析與數學知識的實踐

數學 程序員 HTML5 CSS 孝道的重要性 孝道的重要性 2017-08-27

引言

在這觸控屏的時代,人性化的手勢操作已經深入了我們生活的每個部分。現代應用越來越重視與用戶的交互及體驗,手勢是最直接且最為有效的交互方式,一個好的手勢交互,能降低用戶的使用成本和流程,大大提高了用戶的體驗。

近期,公司的多個項目中都對手勢有著較高的需求,已有的手勢庫無法完全cover,因此便擼了一個輕量、便於使用的移動端手勢庫。這篇博文主要是解析了移動端常用手勢的原理,及從前端的角度學習過程中所使用的數學知識。希望能對大家有一點點的啟發作用,也期待大神們指出不足甚至錯誤,感恩。

主要講解項目中經常使用到的五種手勢:

  • 拖動: drag

  • 雙指縮放: pinch

  • 雙指旋轉: rotate

  • 單指縮放: singlePinch

  • 單指旋轉: singleRotate

程序員總結:HTML5中手勢原理分析與數學知識的實踐

實現原理

眾所周知,所有的手勢都是基於瀏覽器原生事件touchstart, touchmove, touchend, touchcancel進行的上層封裝,因此封裝的思路是通過一個個相互獨立的事件回調倉庫handleBus,然後在原生touch事件中符合條件的時機觸發並傳出計算後的參數值,完成手勢的操作。實現原理較為簡單清晰,先不急,我們先來理清一些使用到的數學概念並結合代碼,將數學運用到實際問題中,數學部分可能會比較枯燥,但希望大家堅持讀完,相信會收益良多。

這篇文章分享之前我還是要推薦下我自己的前端群:657137906,不管你是小白還是大牛,小編我都挺歡迎,不定期分享乾貨,包括我自己整理的一份2017最新的前端資料和零基礎入門教程,歡迎初學和進階中的小夥伴。。

基礎數學知識函數

我們常見的座標系屬於線性空間,或稱向量空間(Vector Space)。這個空間是一個由點(Point) 和 向量(Vector) 所組成集合;

點(Point)

可以理解為我們的座標點,例如原點O(0,0),A(-1,2),通過原生事件對象的touches可以獲取觸摸點的座標,參數index代表第幾接觸點;

程序員總結:HTML5中手勢原理分析與數學知識的實踐

向量(Vector)

是座標系中一種 既有大小也有方向的線段,例如由原點O(0,0)指向點A(1,1)的箭頭線段,稱為向量a,則a=(1-0,1-0)=(1,1);

如下圖所示,其中i與j向量稱為該座標系的單位向量,也稱為基向量,我們常見的座標系單位為1,即i=(1,0);j=(0,1);

程序員總結:HTML5中手勢原理分析與數學知識的實踐

獲取向量的函數:

程序員總結:HTML5中手勢原理分析與數學知識的實踐

向量模

代表 向量的長度,記為|a|,是一個標量,只有大小,沒有方向;

幾何意義代表的是以x,y為直角邊的直角三角形的斜邊,通過勾股定理進行計算;

程序員總結:HTML5中手勢原理分析與數學知識的實踐

getLength函數:

程序員總結:HTML5中手勢原理分析與數學知識的實踐

向量的數量積

向量同樣也具有可以運算的屬性,它可以進行加、減、乘、數量積和向量積等運算,接下來就介紹下我們使用到的數量積這個概念,也稱為點積,被定義為公式:

程序員總結:HTML5中手勢原理分析與數學知識的實踐

共線定理

共線,即兩個向量處於 平行 的狀態,當a=(x1,y1),b=(x2,y2),則存在唯一的一個實數λ,使得a=λb,代入座標點後,可以得到 x1·y2= y1·x2;

因此當x1·y2-x2·y1>0 時,既斜率 ka > kb ,所以此時b向量相對於a向量是屬於順時針旋轉,反之,則為逆時針;

旋轉角度

通過數量積公式我們可以推到求出兩個向量的夾角:

程序員總結:HTML5中手勢原理分析與數學知識的實踐

然後通過共線定理我們可以判斷出旋轉的方向,函數定義為:

程序員總結:HTML5中手勢原理分析與數學知識的實踐

矩陣與變換

由於空間最本質的特徵就是其可以容納運動,因此在線性空間中,

我們用向量來刻畫對象,而矩陣便是用來描述對象的運動;

而矩陣是如何描述運動的呢?

我們知道,通過一個座標系基向量便可以確定一個向量,例如 a=(-1,2),我們通常約定的基向量是 i = (1,0) 與 j = (0,1); 因此:

a = -1i + 2j = -1(1,0) + 2(0,1) = (-1+0,0+2) = (-1,2);

而矩陣變換的,其實便是通過矩陣轉換了基向量,從而完成了向量的變換;

例如上面的栗子,把a向量通過矩陣(1,2,3,0)進行變換,此時基向量i由 (1,0)變換成(1,-2)與j由(0,1)變換成(3,0),沿用上面

的推導,則

a = -1i + 2j = -1(-1,2) + 2(3,0) = (5,-2);

如下圖所示:

A圖表示變換之前的座標系,此時a=(-1,2),通過矩陣變換後,基向量i,j的變換引起了座標系的變換,變成了下圖B,因此a向量由(-1,2)變換成了(5,-2);

其實向量與座標系的關聯不變(a = -1i+2j),是基向量引起座標系變化,然後座標系沿用關聯導致了向量的變化;

程序員總結:HTML5中手勢原理分析與數學知識的實踐

結合代碼

其實CSS的transform等變換便是通過矩陣進行的,我們平時所寫的translate/rotate等語法類似於一種封裝好的語法糖,便於快捷使用,而在底層都會被轉換成矩陣的形式。例如transform:translate(-30px,-30px)編譯後會被轉換成transform : matrix(1,0,0,1,30,30);

通常在二維座標系中,只需要 2X2 的矩陣便足以描述所有的變換了, 但由於CSS是處於3D環境中的,因此CSS中使用的是 3X3 的矩陣,表示為:

程序員總結:HTML5中手勢原理分析與數學知識的實踐

其中第三行的0,0,1代表的就是z軸的默認參數。這個矩陣中,(a,b) 即為座標軸的 i基,而(c,d)既為j基,e為x軸的偏移量,f為y軸的偏移量;因此上慄便很好理解,translate並沒有導致i,j基改變,只是發生了偏移,因此translate(-30px,-30px) ==> matrix(1,0,0,1,30,30)~

所有的transform語句,都會發生對應的轉換,

如下:

程序員總結:HTML5中手勢原理分析與數學知識的實踐

translate/rotate/scale等語法十分強大,讓我們的代碼更為可讀且方便書寫,但是matrix有著更強大的轉換特性,通過matrix,可以發生任何方式的變換,例如我們常見的鏡像對稱,transform:matrix(-1,0,0,1,0,0);

程序員總結:HTML5中手勢原理分析與數學知識的實踐

MatrixTo

然而matrix雖然強大,但可讀性卻不好,而且我們的寫入是通過translate/rotate/scale的屬性,然而通過getComputedStyle讀取到的 transform卻是matrix:

transform:matrix(1.41421, 1.41421, -1.41421, 1.41421, -50, -50);

請問這個元素髮生了怎麼樣的變化?。。這就一臉懵逼了。-_-|||

因此,我們必須要有個方法,

來將matrix翻譯成我們更為熟悉的translate/rotate/scale方式,在理解了其原理後,我們便可以著手開始表演咯~

我們知道,前4個參數會同時受到rotate和scale的影響,具有兩個變量,因此需要通過前兩個參數根據上面的轉換方式列出兩個不

等式:

cos(θ·π/180)*s=1.41421;

sin(θ·π/180)*s=1.41421;

將兩個不等式相除,即可以輕鬆求出θ和s了,perfect!!

函數如下:

程序員總結:HTML5中手勢原理分析與數學知識的實踐

手勢原理

接下來我們將上面的函數用到實際環境中,通過圖示的方式來模擬手勢的操作,簡要地講解手勢計算的原理。希望各位大神理解這些基礎的原理後,能創造出更多炫酷的手勢,像我們在mac觸控板上使用的一樣。

下面圖例:

圓點: 代表手指的觸碰點;

兩個圓點之間的虛線段: 代表雙指操作時組成的向量;

a向量/A點:代表在 touchstart 時獲取的初始向量/初始點;

b向量/B點:代表在 touchmove 時獲取的實時向量/實時點;

座標軸底部的公式代表需要計算的值;

Drag(拖動事件)

程序員總結:HTML5中手勢原理分析與數學知識的實踐

相關推薦

推薦中...