pcBeta 发表于 2013-12-25 15:39

《月熊志》技术解析——沉浸式的翻阅体验

《月熊志》为大家提供了一个沉浸式的翻阅体验,用户可以在页面切换时体验到真实的3D翻书效果,非常的酷炫。而要实现这个效果,需要用到CSS3 3D transform和JavaScript,同时为了实现跨浏览器和跨设备的统一体验,用到hammer.js库去处理滑动操作。
file:///C:\Users\慧\AppData\Local\Packages\oice_15_974fa576_32c1d314_3016\AC\Temp\msohtmlclip1\01\clip_image002.jpg http://static.cdn.pcbeta.com/data/attachment/album/201312/25/153835sqbks9kyv0oxr0vg.png示例效果:file:///C:\Users\慧\AppData\Local\Packages\oice_15_974fa576_32c1d314_3016\AC\Temp\msohtmlclip1\01\clip_image004.jpg http://static.cdn.pcbeta.com/data/attachment/album/201312/25/1538354uw3uiincuzt27c2.png网页的结构十分简单,整个杂志是一个ID为magazine的div,子元素. page即页面元素,其中还需要包含一层.page-content层。HTML:<div id="magazine">         <divclass="page">                   <divclass="page-content">                            <!--... -->                   </div>         </div>         <!--pages -->         <divclass="page">                   <divclass="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 http://static.cdn.pcbeta.com/data/attachment/album/201312/25/153836zn33y34tnette14b.pngfile:///C:\Users\慧\AppData\Local\Packages\oice_15_974fa576_32c1d314_3016\AC\Temp\msohtmlclip1\01\clip_image006.jpg
除了当前页的其他页面,为了只显示页面一半,需要将外层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='pageback/>").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;
      //通过css3transition完成余下动画      _.$pageFront.css({         "transition": "all " + duration + "sease-out",         "transform": "perspective(2200px) rotateY(" + angel+ "deg)"      });      _.$pageBack.css({         "transition": "all " + duration + "sease-out",         "transform": "perspective(2200px) rotateY(" + (angel- 180) + "deg)"      });    });});
如果你的页面包含视频或者Canvas等元素,那还需要再做一些额外的工作,因为这些元素并不能以同样的状态被直接复制。
最后如果你需要兼容不支持CSS3浏览器。可以借助Modernizr判断,以水平滑动的方式切换页面。if (Modernizr.csstransforms3d && Modernizr.csstransitions) {    //支持} else {    //不支持};
页: [1]
查看完整版本: 《月熊志》技术解析——沉浸式的翻阅体验