copy from http://ued.ctrip.com/blog/webapp-horizontal-sliding-mode-based-on-css3-evolution.html
前言
随着移动网络速率和设备硬件水平的不断提升,webapp的发展更加的native化,其表现效果和性能也会越来越好,在可预计的未来很有可能替代native或者平起平坐,那么我们研究更好的交互体验是非常有必要的。
目前我们所常见的webapp越来越多的是以SPA(single page application)的模式进行开发,同时嵌套在android或者ios本地壳里面,也就是hybrid应用,这种开发方式所带来的优势就不多讨论,本文研究的重点是在SPA模式中,页面间横向滑动切换场景时模式是怎样设计的。在这篇文章里,笔者将展示并阐述四种横向滑动模式的架构布局及CSS设计方案,供大家参考(多图请耐心加载)。
一、容器整体滑动(DEMO只演示A-B-C-B,下同)
模拟动画效果见下图(上),滑动分解见下图(下):
id="iframe_0.6513784203093491" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.elonglau.com/wp-content/uploads/2014/11/slider1.gif?_=5522513%22%20style=%22border:none;max-width:1504px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.6513784203093491',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; width: 320px; height: 568px;">
id="iframe_0.4788707621338957" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.elonglau.com/wp-content/uploads/2014/11/slider1.png?_=5522513%22%20style=%22border:none;max-width:1504px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.4788707621338957',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; width: 720px; height: 720px;">
DEMO地址:http://nirvana.sinaapp.com/demo_slider/slider_1.html
布局方式:父容器相对定位并撑满整个device的viewport,子页面绝对定位并依次并排排列在viewport中(从左到右)
.view-container { // 父容器布局方式 position: relative; width: 100%; height: 100%; padding-top: 44px; box-sizing: border-box; -webkit-transform: translate3d(0,0,0); //激活GPU 3D加速 -webkit-backface-visibility: hidden; } .page-container { // 子页面布局方式 position: absolute; z-index: 1; top: 0; left: 0; // 初始化为0,动态计算第N个page,并赋值(N-1)*100% width: 100%; height: 100%; overflow: hidden; background-color: #F8F8F8; }
滑动方式:父容器利用CSS3的动画transform3D进行X轴的滑动(JS控制直接喷到DOM节点中)
-webkit-transform: translate3d(-100%, 0px, 0px); -webkit-transition: 300ms; transition: 300ms;
二、单个页面滑动
模拟动画效果,见下图:
id="iframe_0.6908539655307635" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.elonglau.com/wp-content/uploads/2014/11/slider2.gif?_=5522513%22%20style=%22border:none;max-width:1504px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.6908539655307635',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; width: 320px; height: 568px;">
id="iframe_0.3574528629663687" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.elonglau.com/wp-content/uploads/2014/11/slider2.png?_=5522513%22%20style=%22border:none;max-width:1504px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.3574528629663687',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; width: 720px; height: 720px;">
DEMO地址:http://nirvana.sinaapp.com/demo_slider/slider_2.html
布局方式:父容器高度100%,子容器正常文档流布局(X轴隐藏,Y轴默认原生滚动)
.view-container { height: 100%; } .page-container { position: relative; width: 100%; min-height: 100%; overflow-x: hidden; background-color: #F8F8F8; }
滑动方式:利用class添加动画样式(keyframes animation),左右进出各一种
@-webkit-keyframes sliderightout{from{-webkit-transform:translateX(0px);opacity:1}to{-webkit-transform:translateX(50%);opacity:0}} @-webkit-keyframes slideleftin{from{-webkit-transform:translateX(-50%);opacity:0}to{-webkit-transform:translateX(0px);opacity:1}} @-webkit-keyframes slideleftout{from{-webkit-transform:translateX(0px);opacity:1}to{-webkit-transform:translateX(-50%);opacity:0}} @-webkit-keyframes sliderightin{from{-webkit-transform:translateX(50%);opacity:0}to{-webkit-transform:translateX(0px);opacity:1}} .slideleftout{-webkit-animation:slideleftout 350ms ease-in-out;} .slideleftin{-webkit-animation:slideleftin 350ms ease-in-out;} .sliderightout{-webkit-animation:sliderightout 350ms ease-in-out;} .sliderightin{-webkit-animation:sliderightin 350ms ease-in-out;} .animatestart{position:absolute;top:0;left:0;z-index:3;width:100%;height:100%;overflow-x:hidden} .animatestart.page-container{overflow-x:hidden;-webkit-transform:translate3d(0,0,0);-webkit-backface-visibility:hidden;background-color:#f5f5f5}
三、双页联动滑动
模拟动画效果,见下图:
id="iframe_0.1280356095796542" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.elonglau.com/wp-content/uploads/2014/11/slider3.gif?_=5522513%22%20style=%22border:none;max-width:1504px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.1280356095796542',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; width: 320px; height: 568px;">
id="iframe_0.4280392632650296" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.elonglau.com/wp-content/uploads/2014/11/slider3.png?_=5522513%22%20style=%22border:none;max-width:1504px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.4280392632650296',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; width: 720px; height: 720px;">
DEMO地址:http://nirvana.sinaapp.com/demo_slider/slider_3.html
布局方式:类似于第一种,父容器和子容器都绝对定位于viewport中,不同点是父类的上级布局更加细分,且大胆使用了webkit-box弹性盒子;子容器没有并排显示,而是重叠隐藏
.view-container { position: absolute; width: 100%; height: 100%; top: 0; left: 0; } .page-container { position: absolute; z-index: 1; top: 0; left: 0; bottom: 0; right: 0; width: 100%; height: 100%; overflow: hidden; background-color: #F8F8F8; -webkit-transform:translate3d(0,0,0); -webkit-backface-visibility:hidden; }
滑动方式:滑动开始时先将隐藏的下一个子页面拉到viewport右侧与当前子页面平行,然后紧接着两个子页面同步滑动,最后回归样式,中间的时间差事件均有JS控制(详见demo逻辑)
四、三舞台双页视差滑动
模拟动画效果见下图(上),分解逻辑图见下图(下):
id="iframe_0.8453990746956359" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.elonglau.com/wp-content/uploads/2014/11/slider4.gif?_=5522513%22%20style=%22border:none;max-width:1504px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.8453990746956359',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; width: 320px; height: 568px;">
id="iframe_0.0025432484175835768" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.elonglau.com/wp-content/uploads/2014/11/slider4.png?_=5522513%22%20style=%22border:none;max-width:1504px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.0025432484175835768',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-width: initial; border-style: none; width: 720px; height: 720px;">
DEMO地址:http://nirvana.sinaapp.com/demo_slider/slider_4.html
布局方式:这里我设定了三舞台(stage)的概念,其实就是当前viewport的左右侧各虚拟一个同样大小的viewport,当然,正常情况下我们只能看到当前舞台的子页面,leftstage是-100%的位置,rightstage是100%的位置,我们分别用三个class来定义:pageOld、pageInit、pageNew来代替
.pageInt { -webkit-transform: translateX(0); transform: translateX(0); } .pageOld { -webkit-transform: translateX(-100%); transform: translateX(-100%); } .pageNew { -webkit-transform: translateX(100%); transform: translateX(100%); } }
滑动方式:
1,定义正向(向左滑)和反向(向右滑)两个概念,;
2,定义快速和慢速两个概念;
则就是四种动态两种组合:正向快速+正向慢速、反向快速+反向慢速;
.slideSlow { -webkit-transition: -webkit-transform 400ms cubic-bezier(0.42, 0, 0.58, 1.0) 0.1s; -ms-transition: transform 400ms cubic-bezier(0.42, 0, 0.58, 1.0) 0.1s; } .slideFast { -webkit-transition: -webkit-transform 300ms cubic-bezier(0.42, 0, 0.58, 1.0); -ms-transition: transform 300ms cubic-bezier(0.42, 0, 0.58, 1.0); } .slideSlowBack { -webkit-transition: -webkit-transform 400ms cubic-bezier(0.42, 0, 0.58, 1.0); -ms-transition: transform 400ms cubic-bezier(0.42, 0, 0.58, 1.0); } .slideFastBack { -webkit-transition: -webkit-transform 300ms cubic-bezier(0.42, 0, 0.58, 1.0) 0.1s; -ms-transition: transform 300ms cubic-bezier(0.42, 0, 0.58, 1.0) 0.1s; }
其中在三舞台视差滑动中的滑动曲线是经过数次的真机实验后找到的参数(cubic-bezier(0.42, 0, 0.58, 1.0)),这条曲线的滑动形态最接近IOS APP页面的滑动,希望对大家有用,鉴于时间精力有限,这四种模式只能从架构布局和样式设计层面探讨