最近坐地鐵發現「亞洲動物基金」在地鐵上作了不少公益廣告,比較吸引人的是一個月熊的廣告。作的很可愛。回去就搜了一下,發現這個網站是HTML5作的,很是炫。javascript
因此想學習一下,方法就是傳統的學習辦法,模仿、剖析,看看人家是怎麼作的。css
這個網站提供的是了一個沉浸式的翻閱體驗,用戶能夠在頁面切換時體驗到真實的3D翻書效果,很是的酷炫。而要實現這個效果,須要用到CSS3 3D transform和JavaScript,同時爲了實現跨瀏覽器和跨設備的統一體驗,用到hammer.js庫去處理滑動操做。就是下面這個樣子的,很是漂亮:java
示例效果:css3
查看代碼發現,網頁的結構十分簡單,整個雜誌是一個ID爲magazine的div,子元素. page即頁面元素,其中還須要包含一層.page-content層。瀏覽器
<div id="magazine"> <div class="page"> <div class="page-content"> <!-- ... --> </div> </div> <!-- pages --> <div class="page"> <div class="page-content"> <!-- ... --> </div> </div> </div> CSS: .page { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; display: none; } .page-content { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
當用戶拖拽頁面時,咱們會複製一份當前頁和下一頁,做爲3D翻頁的元素存在,層之間的關係以下:app
$currentPage -> 當前頁學習
$newPage -> 新的一頁(上一頁/下一頁)動畫
$pageBack -> 克隆的$newPage網站
$pageFront -> 克隆的$currentPagethis
除了當前頁的其餘頁面,爲了只顯示頁面一半,須要將外層div的寬度設置爲50%,同時將.page-content設爲200%。
CSS: .page.front, .page.back, .page.prev, .page.next { width: 50%; } .page.front .page-content, .page.back .page-content, .page.prev .page-content, .page.next .page-content { width: 200%; }
當開始拖拽時,經過鼠標位置在屏幕的左邊或者右邊判斷翻頁的方向並複製頁面。而後在拖拽時,根據移動距離計算翻頁進度並轉換爲角度應用到元素上。最後使用css transition完成餘下動畫。
JS代碼關鍵部分:
$("#magazine").hammer({prevent_default: true}).on("dragstart", function(event) { //開始拖拽 //根據指針的位置判斷新的一頁是上一頁仍是下一頁 var pageX = event.gesture.center.pageX; _.$newPage = pageX > centerX ? _.$currentPage.next(".page").addClass("next") : _.$currentPage.prev(".page").addClass("prev"); //複製當前頁和新的一頁 _.$pageFront = $("<div class='page front' />").append(_.$currentPage.children().clone()); _.$pageBack = $("<div class='page back/>").append(_.$newPage.children().clone()); $(this).on("drag", function(event) { //拖拽中 //得到手勢方向 var direction = event.gesture.direction; //若是是左右滑動才繼續 if (direction != "left" && direction != "right") return; //得到鼠標x座標,和窗口寬度相除得到百分比和角度 var deltaX = Math.max((_.direction == "left" ? -1 : 1) * event.gesture.deltaX, 0), progress = deltaX / winWidth, angle = (direction == "left" ? -180 : 180) * progress; //使用transform翻轉頁面 _.$pageFront.css("transform", "perspective(2200px) rotateY(" + angle + "deg)"); _.$pageBack.css("transform", "perspective(2200px) rotateY(" + (angle - 180) + "deg)"); }).on("dragend", function(event) { //拖拽結束 var deltaX = Math.max((direction == "left" ? -1 : 1) * event.gesture.deltaX, 0), time = event.gesture.deltaTime, progress = deltaX / winWidth, flipped = progress > 0.5 || deltaX / time > 0.5, //若是滑動距離超過屏幕的一半或者速度大於0.5就認爲頁面被翻過去了 duration = !flipped ? 1 - progress : progress, angle = !flipped ? 0 : _.direction == "left" ? -180 : 180; //經過css3 transition完成餘下動畫 _.$pageFront.css({ "transition": "all " + duration + "s ease-out", "transform": "perspective(2200px) rotateY(" + angel + "deg)" }); _.$pageBack.css({ "transition": "all " + duration + "s ease-out", "transform": "perspective(2200px) rotateY(" + (angel - 180) + "deg)" }); }); });
若是你的頁面包含視頻或者Canvas等元素,那還須要再作一些額外的工做,由於這些元素並不能以一樣的狀態被直接複製。
最後若是你須要兼容不支持CSS3瀏覽器。能夠藉助Modernizr判斷,以水平滑動的方式切換頁面。
if (Modernizr.csstransforms3d && Modernizr.csstransitions) {
//支持
} else {
//不支持
};
今天暫時寫到這裏吧,想看效果的同窗,能夠本身去 http://moonbear.animalsasia.org/ie/ 看一下。真的是很是漂亮,明天我會繼續剖析一下其餘效果的實現。