《月熊志》技术解析——沉浸式的翻阅体验
《月熊志》为大家提供了一个沉浸式的翻阅体验,用户可以在页面切换时体验到真实的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]