最近坐地鐵發現“亞洲動物基金”在地鐵上做了很多公益廣告,比較吸引人的是一個月熊的廣告。做的很可愛。回去就搜了一下,發現這個網站是Html5做的,非常炫。
所以想學習一下,方法就是傳統的學習辦法,模仿、剖析,看看人家是怎麼做的。
這個網站提供的是了一個沉浸式的翻閱體驗,用戶可以在頁面切換時體驗到真實的3D翻書效果,非常的酷炫。而要實現這個效果,需要用到CSS3 3D transform和JavaScript,同時為了實現跨浏覽器和跨設備的統一體驗,用到hammer.JS庫去處理滑動操作。就是下面這個樣子的,非 常漂亮:
示例效果:
查看代碼發現,網頁的結構十分簡單,整個雜志是一個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翻頁的元素存在,層之間的關系如下:
$currentPage -> 當前頁
$newPage -> 新的一頁(上一頁/下一頁)
$pageBack -> 克隆的$newPage
$pageFront -> 克隆的$currentPage
除了當前頁的其他頁面,為了只顯示頁面一半,需要將外層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 {
//不支持
};