impress.js學習

引子javascript

斷斷續續用了好幾天,終於把 impress.js 源碼看完,做爲剛入門的前端菜鳥,這是我第一次看 js 源碼,最初仍是比較痛苦的。不過還好,impress.js源碼的註釋至關清楚,每一個函數和事件的做用都寫得很詳細,這讓源碼讀起來更容易理解,此處手動給大神送糖果~~~

   接下來就由我給你們分享下 impress.js 效果是如何實現的、以及咱們怎麼利用它來實現特效。

impress.js的實現css

咱們在用 impress.js實現特效時,會用到相似下面的代碼:前端

<div id="its" class="step" data-x="900" data-y="3000" data-rotate="90" data-scale="4">

咱們看到代碼中有data-x,data-y等屬性,實際上咱們就是經過改變這些屬性的值來實現PPT的跳轉的。這些屬性分別表明:java

  • data-x:幻燈片的X座標api

  • data-y:幻燈片的Y座標瀏覽器

  • data-scale:幻燈片顯示的縮放比例函數

  • data-rotate:幻燈片旋轉的度數動畫

  • data-rotate-x:3D使用,設置它相對X軸旋轉多少度google

  • data-rotate-y:3D使用,設置它相對Y軸旋轉多少度url

  • data-rotate-z:3D使用,設置它性對Z軸旋轉多少度
    咱們來看看impress源碼中的 rotate函數:

//'rotate'對給定數據構造旋轉變換
//默認旋轉順序爲X,Y,Z,能夠將參數設定爲true來倒轉順序
var rotate = function( r, revert ) {
 var rX = " rotateX(" + r.x + "deg) ",
 rY = " rotateY(" + r.y + "deg) ",
 rZ = " rotateZ(" + r.z + "deg) ";
return revert ? rZ + rY + rX : rX + rY + rZ;
 };​

rotate函數的做用是將rotate對象轉換成css使用的字符串。
用戶自定義的數據經過data屬性讀取,並初始化給step對象。對應源碼以下

:var data = el.dataset,
 step = {
 translate: {//對給定數據構造平移變換
 x: toNumber( data.x ),
 y: toNumber( data.y ),
 z: toNumber( data.z )
 },
 rotate: {//對給定數據構造旋轉變換
 x: toNumber( data.rotateX ),
 y: toNumber( data.rotateY ),
 z: toNumber( data.rotateZ || data.rotate )
 },
 scale: toNumber( data.scale, 1 ),//對給定數據構造縮放變換
 el: el
 };​

咱們在編寫HTML時,經過改變data的屬性值實現頁面切換,那麼在源碼中,又是怎麼來實現的呢?
在impress.js源碼中,主要經過三個事件來實現impress的運行,它們分別是impress:init,impress:stepenter和impress:stepleave,在瞭解這些事件以前,先明白 step 這個概念,一個step就至關於PPT中的一頁,每切換一頁就至關於切換一個step。每一次切換都會觸發上面所提到的兩個事件:impress:stepenter和impress:stepleave,從而達到頁面跳轉的效果。

咱們在使用 impress.js的時候,須要調用impress.js中的impress().init()函數:`

<script type="text/javascript">impress().init();</script>

init() 函數是 impress 的主初始化函數,它的做用是初始化 impress API ,從而運行impress。在 init() 函數的結尾觸發 impress:init事件,這樣綁定上去的函數就會所有觸發了。如下代碼便是觸發 impress:init事件:

triggerEvent( root, "impress:init", { api: roots[ "impress-root-" + rootId ] } );
 };

Triggerevent()方法:觸發指定對象的指定事件,而且當即執行該事件中的腳本。
Triggerevent構造一個事件,該事件以 'eventnam'命名,用detail處理數據,並在el上執行。源碼以下:

var triggerEvent = function( el, eventName, detail ) {
 var event = document.createEvent( "CustomEvent" );
 event.initCustomEvent( eventName, true, true, detail );
 el.dispatchEvent( event );
 };​

接下來咱們看看 impress:init事件上綁定了哪些函數:
(1)爲step添加一些有用的類:

root.addEventListener( "impress:init", function() {
// STEP CLASSES
 steps.forEach( function( step ) {
 step.classList.add( "future" );//全部還沒有展現的 steps 都添加到都添加 `future` 類
 } );
root.addEventListener( "impress:stepenter", function( event ) {
 event.target.classList.remove( "past" );
 event.target.classList.remove( "future" );
 event.target.classList.add( "present" ); // 當某個step 被展現,`future`類會被移除,並被添加上 `present`類
 }, false );
root.addEventListener( "impress:stepleave", function( event ) {
 event.target.classList.remove( "present" );
 event.target.classList.add( "past" );//當某個step結束時, `present` 又會被替換成`past`類
 }, false );
}, false );​

經過上面的方法,每一個 step 都會處於 future, presentpast三個狀態中的一個,這樣使得咱們在切換PPT的時候能夠先後任意切換。
上面代碼中用到了addEventListener() 方法,該方法用於向指定元素添加事件句柄。語法以下:element.addEventListener(event,function,useCapture);
參數 event:必需,指定事件名,不要使用"on"前綴;
function:指定事件要觸發時執行的函數;
useCapture:可選(布爾值),指定事件是否在捕獲或者冒泡時執行。
可以使用 removeEventListener() 方法來移除 addEventListener() 方法添加的事件句柄。

(2)添加hash變化支持:

root.addEventListener("impress:init", function(){
 
  var lastHash = "";  // 將lasthash清空
 // `#step-id`將被替換成`#/step-id`以防止瀏覽器在默認狀態下滾動至hash表中所保存元素所在位置
 //
 // 並且添加hash的操做必須在動畫結束之後進行, 由於在Chrome裏會致使動畫延遲
 // BUG: http://code.google.com/p/chromium/issues/detail?id=62820
 root.addEventListener("impress:stepenter", function (event) {
 window.location.hash = lastHash = "#/" + event.target.id;
 }, false);
 
 window.addEventListener("hashchange", function () {
 // 當某一step被展現時,location裏的hash已經更新(就在上面幾行)
 // 因此hash change事件被觸發,咱們將在同一step上再一次調用`goto`方法。
 // 爲了不這一狀況,咱們將存儲上一次 hash 的結果並比較.
 if (window.location.hash !== lastHash) {
 goto( getElementFromHash() );
 }
 }, false);
 
 // 開始
 // 選擇記錄在url中的step地址,或者演示文稿的第一張step
 goto(getElementFromHash() || steps[0], 0);
 }, false);​

window.location.hash: hash 屬性是一個可讀可寫的字符串,該字符串是 URL 的錨部分(從 # 號開始的部分)。
location.hash能夠用來獲取或設置頁面的標籤值。
經過 window.location.hash=hash這個語句來調整地址欄的地址,使得瀏覽器裏邊的「前進」、「後退」按鈕能正常使用。

(3)導航事件
鍵盤處理導航:
按鍵被按下時:

// 防止不容許被按下的鍵被意外按下
 document.addEventListener("keydown", function ( event ) {
 if ( event.keyCode === 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
 event.preventDefault();
 }
 }, false);​

preventDefault() 方法阻止元素髮生默認的行爲。

按鍵彈起時,觸發impress動做(下一張或上一張):

document.addEventListener("keyup", function ( event ) {
     if ( event.keyCode === 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
     switch( event.keyCode ) {
     case 33: // 上翻頁
     case 37: // 小鍵盤左
     case 38: // 小鍵盤上
     api.prev();
     break;
     case 9: // tab鍵
     case 32: // 空格
     case 34: // 下翻頁
     case 39: // 小鍵盤右
     case 40: // 小鍵盤下
     api.next();
     break;
     }
     
     event.preventDefault();
     }
     }, false);​
 處理在當前演示 steps 上產生的單擊事件(當前step上是否存在超連接):

document.addEventListener("click", function ( event ) {
     // 事件冒泡處理
     // 檢查單擊的目標(及其祖先級容器)是不是超連接
     var target = event.target;
     while ( (target.tagName !== "A") &&
     (target !== document.documentElement) ) {
     target = target.parentNode;
     }
     
     if ( target.tagName === "A" ) {
     var href = target.getAttribute("href");
     
     // 若是指向某一鏈接,跳轉至這一鏈接
     if ( href && href[0] === '#' ) {
     target = document.getElementById( href.slice(1) );
     }
     }
     
     if ( api.goto(target) ) {
     event.stopImmediatePropagation();//若是目標對象件被執行,將阻止剩下事件執行
     event.preventDefault();
     }
     }, false);​
event.stopImmediatePropagation() 方法阻止剩下的事件處理程序被執行,該方法阻止事件在 DOM 樹中向上冒泡。
處理在當前演示 steps 上產生的單擊事件:

    document.addEventListener("click", function ( event ) {
     var target = event.target;
     // 查找距當前活躍step最近的不活躍step
     while ( !(target.classList.contains("step") && !target.classList.contains("active")) &&
     (target !== document.documentElement) ) {
     target = target.parentNode;
     }
     
     if ( api.goto(target) ) {
     event.preventDefault();
     }
     }, false);     
處理觸摸屏上上輕擊屏幕左邊或者右邊的事件:document.addEventListener("touchstart", function ( event ) {
 if (event.touches.length === 1) {
 var x = event.touches[0].clientX,
 width = window.innerWidth * 0.3,
 result = null;
 
 if ( x < width ) {
 result = api.prev();
 } else if ( x > window.innerWidth - width ) {
 result = api.next();
 }
 
 if (result) {
 event.preventDefault();
 }
 }
 }, false);

當窗口大小改變時,從新計算窗口大小:

window.addEventListener("resize", throttle(function () {
 // 強制激活當前step
 api.goto( document.querySelector(".step.active"), 500 );
 }, 250), false);

impress總共有4個API,分別是goto(), init(), next(), prev()。
impress的切換主要經過 goto()來實現,goto API 跳轉至以el參數(索引,id或元素名)標記的step 。prev API 按文檔順序跳回上一 step ,next API 按文檔順序跳向下一 step 。




相關文章
相關標籤/搜索