手势模型和Angular Material的实现
iPhone的出現(xiàn)讓手勢操作大為流行,也使得手勢編程成為開發(fā)人員的挑戰(zhàn)。 擬物設(shè)計(jì)也把手勢編程納入在內(nèi),大概也想制定一個(gè)在交互模型標(biāo)準(zhǔn)。現(xiàn)階段因?yàn)镸D還在預(yù)發(fā)布階段,因此還只實(shí)現(xiàn)了單點(diǎn)手勢(一個(gè)指頭),可是已經(jīng)有足夠的東西值得學(xué)習(xí),無論對(duì)我們應(yīng)用還是自己設(shè)計(jì)手勢編程都是大有裨益。
Angular Material有兩個(gè)手劃控件mdSwipeLeft和mdSwipeRight,然而真正的代碼支持卻不在這兩個(gè)控件的定義中,而是在核心代碼中,文件位置src\core\services\gesture\gesture.js這里也就是我們深入研究手勢實(shí)現(xiàn)的地方。
基本屏幕事件
做過界面的人都熟悉mousedown, mouseup, mousemove等事件,很多后臺(tái)函數(shù)多與這些事件綁定,從而能夠與用戶交互。但是這些事件都有些單薄而僵硬,手勢事件卻更友好和人性化,這也是其大受歡迎的根本原因。
手勢事件不是空中樓閣,它們本身是需要這些基本事件的支持,這些基本屏幕事件也就成為了手勢模型的一個(gè)組成部分,成為最底的一層。
這些事件首先被劃分為三類,說是三類,理解成三個(gè)事件更為恰當(dāng),它們與手指與屏幕的交互一一對(duì)應(yīng):開始事件就是手指按下屏幕;移動(dòng)事件就是手指在屏幕移動(dòng);結(jié)束事件就是手指離開屏幕。非常簡單而直觀。
從下面MD對(duì)這三類事件的定義,我們也可以看到每類事件中的變體大都與設(shè)備的不同有關(guān)而不是真正的不同事件,如鼠標(biāo)的按下,和手指的按下。這也是我上面說的把它們理解為三個(gè)事件更為恰當(dāng)。
- START_EVENTS =>'mousedown touchstart pointerdown';
- MOVE_EVENTS => 'mousemove touchmove pointermove';
- END_EVENTS => 'mouseup mouseleave touchend touchcancel pointerup pointercancel';
手勢歸納
基本事件都是瞬間事件,不存在延時(shí)和邏輯判斷,按下就是按下,松開就是松開;這也是稱之為基本事件的原因。
而手勢卻恰恰相反,
- 手勢是綜合事件,如滑動(dòng)手勢,直觀的感覺就是手指按下快速向左(右)滑動(dòng),并同時(shí)松開手指,這整個(gè)過程完成才是一個(gè)滑動(dòng)手勢。
- 手勢還有邏輯判斷,還是滑動(dòng)手勢,不僅僅要在以上的全過程之后才激發(fā),手指的還要超過一定的速度才能算是滑動(dòng)手勢。
因此,可以把手勢看作在基本事件之上的一個(gè)封裝,在MD的實(shí)現(xiàn)也是用GestureHandler的函數(shù)還偵聽基本事件然后作出綜合處理。
偵聽
這里是MD綁定基本事件的代碼:
angular.element(document).on(START_EVENTS, gestureStart).on(MOVE_EVENTS, gestureMove).on(END_EVENTS, gestureEnd)MD移動(dòng)事件的偵聽處理函數(shù):
function gestureMove(ev) {if (!pointer || !typesMatch(ev, pointer)) return;updatePointerState(ev, pointer);runHandlers('move', ev); }其它兩個(gè)(開始和結(jié)束事件)都與此類似,只不過有更多的處理過程。這個(gè)因?yàn)楹唵?#xff0c;可以用來好好分析關(guān)鍵過程。我們可以看到,這個(gè)偵聽函數(shù)的關(guān)鍵一步就是調(diào)用處理器(runHandler)。這個(gè)函數(shù)內(nèi)部并不復(fù)雜,只是簡單的遍歷預(yù)存處理器,然后調(diào)用該處理器定義的對(duì)應(yīng)的基本事件處理器。這個(gè)處理器就是手勢處理器,它會(huì)分析歸納基本事件當(dāng)條件滿足時(shí)觸發(fā)手勢事件。
手勢處理器$$MdGestureHandler
MD用工廠(factory)的方式定義了手勢處理器的模板(或者可以理解為基類幫助理解),這個(gè)factory名稱就是$$MdGestureHandler,為了便于理解,我們把它分解成三部分來看。
基本屏幕事件處理
第一部分:4個(gè)方法,分別與三類基本屏幕事件對(duì)應(yīng)(cancel是輔助方法),也是用來分別處理三類屏幕事件的,上面的runHandler就是調(diào)用的源頭。
start: function(ev, pointer) {if (this.state.isRunning) return;var parentTarget = this.getNearestParent(ev.target);var parentTargetOptions = parentTarget && parentTarget.$mdGesture[this.name] || {};this.state = {isRunning: true,options: angular.extend({}, this.options, parentTargetOptions),registeredParent: parentTarget};this.onStart(ev, pointer);}, move: function(ev, pointer) {if (!this.state.isRunning) return;this.onMove(ev, pointer);}, end: function(ev, pointer) {if (!this.state.isRunning) return;this.onEnd(ev, pointer);this.state.isRunning = false;}, cancel: function(ev, pointer) {this.onCancel(ev, pointer);this.state = {}; },優(yōu)化的屏幕事件
第二部分:4個(gè)內(nèi)部事件,也是基本與以上4個(gè)方法對(duì)應(yīng),并在4個(gè)方法中適當(dāng)?shù)臅r(shí)機(jī)觸發(fā),可以看作是對(duì)原始基本事件的梳理之后的重新拋出。 你如果創(chuàng)建自己的手勢處理器,要做的也就是重載這4個(gè)事件。從以下代碼我們也可以看到,MD為每一個(gè)事件給出了空實(shí)現(xiàn)(`angular.noop'),目的就是為了讓自定義處理器自己重載實(shí)現(xiàn)。
onStart: angular.noop, onMove: angular.noop, onEnd: angular.noop, onCancel: angular.noop,手勢的觸發(fā)
第三部分:也是最后最關(guān)鍵的一個(gè)方法,手勢事件的觸發(fā)dispatchEvent。自定義的手勢處理器最終都是要調(diào)用這個(gè)方法來觸發(fā)手勢事件。大部分觸發(fā)時(shí)機(jī)都在onEnd中,當(dāng)是不是必須的,要根據(jù)你具體的手勢的含義來定。
dispatchEvent的實(shí)現(xiàn):
手勢實(shí)例解析
手勢內(nèi)部實(shí)現(xiàn)過程雖然較為復(fù)雜,以上的流程解析也是為了更好的理解從而有個(gè)直觀的感覺。到了每一個(gè)手勢的實(shí)現(xiàn)時(shí),真正用到的卻不算多,主要就是那4個(gè)優(yōu)化的事件onStart, onMove, onEnd, onCancel和一個(gè)觸發(fā)的方法'dispatchEvent`。我們來看看一些手勢實(shí)例,親身感受一下,良好建模以后的手勢實(shí)現(xiàn)。
滑動(dòng)手勢 - Swipe
| [無] | ||
| 按下 | ||
| 移動(dòng) | ||
| 移動(dòng) | ||
| 移動(dòng) | ||
| 移動(dòng) | ||
| 松開 | 超過最低速度和位移 | $md.swiperight |
| [無] |
拖動(dòng)手勢 - Drag
| [無] | ||
| 按下 | ||
| 移動(dòng) | ||
| 移動(dòng) | 當(dāng)前觸點(diǎn)與起點(diǎn)位移超過閥值 | $md.dragstart |
| 移動(dòng) | $md.drag | |
| 移動(dòng) | $md.drag | |
| 松開 | $md.dragend | |
| [無] |
轉(zhuǎn)載于:https://www.cnblogs.com/Wonner/p/AngularJS_Material_Gesture.html
總結(jié)
以上是生活随笔為你收集整理的手势模型和Angular Material的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TCP的拥塞控制
- 下一篇: vim global命令