前言:

现在移动互联网发展火热,手机上网的用户越来越多,甚至大有超过pc访问的趋势。所以,用web程序做出仿原生效果的移动应用,也变得越来越流行了。这种程序也就是我们常说的单页应用程序,它也有一个英文缩写,叫SPA; 它最大的特点就是可以利用前端技术做出跨平台的移动应用。技术难点在于理解虚拟页面与物理页面之间的变换关系。一个偶然的机会,我由php程序员转为web前端开发,主攻javascript编程,不知不觉,已经快两年了。一直有一种想写一个webapp应用框架的冲动,但是各种原因,终究没有付出实践。于是打算从做一个简单的webapp应用开始,万事开头难,今天就搭一个简单的界面。

HTML代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>单页应用</title>
<link rel="stylesheet" href="css/common.css" type="text/css"/>
</head>
<body>
<div class="container">
<header>
<h3>sameple test </h3>
</header>
<ul class="root">
<li class="page">1</li>
<li class="page">2</li>
<li class="page">3</li>
<li class="page">4</li>
<li class="page">5</li>
<li class="page">6</li>
<li class="page">7</li>
<li class="page">8</li>
<li class="page">9</li>
<li class="page">10</li>
</ul>
<div class="left">prev</div>
<div class="right">next</div>
<footer>
<h4>(c)2015 by ouyangli</h4>
</footer>
</div>
</body>
<script type="text/javascript" src="lib/core.js"></script>
</html>

css:

 ul , li {
margin:;
padding:;
list-style: none;
}
h3,h4,p {
margin:;
padding:;
}
header {
position: absolute;
width:100%;
top:;
left:;
z-index:;
} header h3 {
text-align: center;
height: 3em;
line-height: 3em;
border-bottom: 1px solid green;
} .container {
position: absolute;
width :320px;
height: 480px;
left:320px;
top:2em;
} .root {
position: absolute;
width :100%;
height: 100%;
top :;
left:;
overflow:hidden;
-webkit-perspective:;
-webkit-user-select: none;
-webkit-transform-style:preserve-3d;
} .page {
position: absolute;
width: 318px;
height: 100%;
overflow: hidden;
border:1px solid green;
} .left {
left :2px;
}
.right {
right:2px;
} .left,.right {
position: absolute;
top:45%;
width:3em;
height: 3em;
line-height: 3em;
text-align: center;
border-radius: 15%;
border:1px dashed blue;
} .left:hover,.right:hover {
background-color: #33ff44;
cursor:pointer;
} footer {
position: absolute;
width: 100%;
bottom:;
} h4 {
height: 3em;
line-height: 3em;
text-align: center;
border-top: 1px solid green;
}

以上源码将会在页底提供打包下载,这里贴出中间过程,只是想让大家能明白,我是怎么一步一步把这个程序写出来的。如果有疑问的地方就给我留言好了,我会尽量回复。

演示地址:http://runjs.cn/detail/o4ql6f6a

细心的话,你会发现左上角有一个“乱码”,其实那是因为所有的页面都堆叠在一起,造成页数看不清了。这正是我们接下来要解决的问题之一。

js:

 //初始化
;(function(){
var pages = document.querySelectorAll('li');
var width = 320;
var len = pages.length;
var setpost = function(element){
element.style.transform = 'translate3d('+width+'px, 0, 0)';
} //把除1以外的页堆在右边
while(--len){
setpost(pages[len]);
}
}());

好了,现在看起来仅管还是很丑,但是至少已经符合我预期的样子了。在这里我把第一页已外的页面全部摆到了屏幕的右边,你看不到它们。这样做的目的是要模拟手机上的翻页效果。接下来,就要实现这个非常令人期待的滑动翻页效果。现在该javascript发挥威力的时候了。这是一个简单的应用,我尽量把所有的js写在core.js中,并采用最普通的函数式编程。

 //初始化
;(function(){
var pages = document.querySelectorAll('li');
var width = 320;
var len = pages.length;
var setpost = function(element){
element.style.transform = 'translate3d('+width+'px, 0, 0)';
} //把除1以外的页堆在右边
while(--len){
setpost(pages[len]);
}
}()); //控制逻辑
;(function(){
//这里直接使用了新的api,因为移动应用可以这样任性。
var pages = document.querySelectorAll('li');
//左右翻页按钮
var left = document.querySelector('.left');
var right = document.querySelector('.right');
//取得所有的子页面
var pagesLen = pages.length-1; //标记当前页面
var currIndex = 0; //移动页面
var move = function(index,pos){
var width = 320 * pos;
var page = pages[index];
page.style.transform = 'translate3d('+width+'px, 0, 0)';
} //向左翻页
var toLeft = function(){ if(currIndex!==pagesLen){
move(currIndex,-1);
move(++currIndex,0);
}
} //向右翻页
var toRight = function(){
if(currIndex!==0){
move(currIndex,1);
move(--currIndex,0);
}
} //监听动作
left.onclick = function(){
toLeft();
} right.onclick = function(){
toRight();
} }())

现在我们的程序可以左右翻页了,不过除了页码发生了变化之外,用户好像感觉不到有翻页的效果。左右翻页按钮的作用与我们期望的效果不一致,所以初始化时,把页面堆在右边其实是不太好的,改为左边会更好一些。嗯,还要继续完善。

 //初始化
;(function(){
var pages = document.querySelectorAll('li');
var width = 320;
var len = pages.length;
var setpost = function(element){
element.style.transform = 'translate3d(-'+width+'px, 0, 0)';
} //把除1以外的页堆在左边
while(--len){
setpost(pages[len]);
}
}()); //控制逻辑
;(function(){
//这里直接使用了新的api,因为移动应用可以这样任性。
var pages = document.querySelectorAll('li');
//左右翻页按钮
var left = document.querySelector('.left');
var right = document.querySelector('.right');
//取得所有的子页面
var pagesLen = pages.length-1; //标记当前页面
var currIndex = 0; //移动页面
var move = function(index,pos){
var width = 320 * pos;
var page = pages[index];
page.style.transform = 'translate3d('+width+'px, 0, 0)';
page.style.transitionDuration = '300ms';
} //上一页
var toLeft = function(){
if(currIndex >0){
move(currIndex,-1);
move(--currIndex,0);
}
} //下一页
var toRight = function(){
if(currIndex < pagesLen){
move(currIndex,1);
move(++currIndex,0);
}
} //监听动作
left.onclick = function(){
toLeft();
} right.onclick = function(){
toRight();
} }())

现在终于看起来像是在翻页的样子了,不过呢,我们在手机上操作的时候,是可以滑动翻页的,这个效果自然也要支持才行。我们先在pc上用鼠标拖动来模拟这一个过程,等逻辑跑通后,再加入触摸事件即可。

继续下一步之前,我们先小结一下:

首先在初始化代码时,顺道把所有不可见的页面全部堆叠到左边,放在左边的原因是因为我们习惯右边的按钮作为下一页,所以这样摆放,实现起来最简单,我当然要选择最有利于我编码的方式来摆放啦。其次呢,每一次翻页,其实都要移动两个页面。拿点击下一页按钮来说,首先要把当前页移动到不可见的屏幕右边,然后把上一页移到屏幕中间来。上一页的过程正好与之相反。我们发现,点击翻页和滑动翻页,其实都会调用相同的功能。所以在这里可先抽出公共方法,方便代码复用。

接下来,我们实现鼠标拖动翻页的效果。

 //初始化
;(function(){
var pages = document.querySelectorAll('li');
var width = 320;
var len = pages.length;
var setpost = function(element){
element.style.transform = 'translate3d(-'+width+'px, 0, 0)';
} //把除1以外的页堆在左边
while(--len){
setpost(pages[len]);
}
}()); //控制逻辑
;(function(){
//这里直接使用了新的api,因为移动应用可以这样任性。
var pages = document.querySelectorAll('li');
//左右翻页按钮
var left = document.querySelector('.left');
var right = document.querySelector('.right');
//取得所有的子页面
var pagesLen = pages.length-1;
//屏宽
var screenWidth = 320; //标记当前页面
var currIndex = 0; //标记是否触发滑动
var isTouch = false;
//记录当前位置
var axis = {
x:0,
y:0
} //移动页面
var move = function(index,width,time){
var page = pages[index];
page.style.transform = 'translate3d('+width+'px, 0, 0)';
page.style.transitionDuration = time+'ms';
} //上一页
var toLeft = function(){
if(currIndex >0){
move(currIndex,-screenWidth,300);
move(--currIndex,0,300);
}
} //下一页
var toRight = function(){
if(currIndex < pagesLen){
move(currIndex,screenWidth,300);
move(++currIndex,0,300);
}
} //监听动作
left.onclick = function(){
toLeft();
} right.onclick = function(){
toRight();
} document.addEventListener('mousedown',function(e){
isTouch = true;
axis.x = e.clientX;
axis.y = e.clientY;
}); document.addEventListener('mousemove',function(e){
if(isTouch){
var distance = e.clientX - axis.x;
if(distance>0){
//next
//此时需要看到实时移动效果,所以时间为0
move(currIndex,distance,0);
//当前页与上一页之间总是相差一个屏宽
move(currIndex+1,distance-screenWidth,0);
}else{
//prev
move(currIndex,distance,0);
move(currIndex-1,screenWidth+distance,0); }
}
}); document.addEventListener('mouseup',function(e){
isTouch = false;
}); }())

这一步我们已经实现了拖动滑页效果,但是感觉怪怪的,对比一下手机上的滑动翻页效果发现,真机上只要我们滑动一定距离之后,页面就自动翻过去了,而不是要我们从一边一直滑到另一边,这样也太不实际了,而且如果我们只滑了一点距离,那么页面会自动归位,也就是常说的反弹效果。要实现这些也不难,我们继续完善代码。

 //初始化
;(function(){
var pages = document.querySelectorAll('li');
var width = 320;
var len = pages.length;
var setpost = function(element){
element.style.transform = 'translate3d(-'+width+'px, 0, 0)';
} //把除1以外的页堆在左边
while(--len){
setpost(pages[len]);
}
}()); //控制逻辑
;(function(){
//这里直接使用了新的api,因为移动应用可以这样任性。
var pages = document.querySelectorAll('li');
//左右翻页按钮
var left = document.querySelector('.left');
var right = document.querySelector('.right');
//取得所有的子页面
var pagesLen = pages.length-1;
//屏宽
var screenWidth = 320;
//反弹时间
var time = 300;
//滑动距离
var distance=0;
//标记当前页面
var currIndex = 0; //标记是否触发滑动
var isTouch = false;
//记录当前位置
var axis = {
x:0,
y:0
} //移动页面
var move = function(index,width,time){
var page = pages[index];
page.style.transform = 'translate3d('+width+'px, 0, 0)';
page.style.transitionDuration = time+'ms';
} //上一页
var toLeft = function(){
if(currIndex >0){
move(currIndex,-screenWidth,time);
move(--currIndex,0,time);
}
} //下一页
var toRight = function(){
if(currIndex < pagesLen){
move(currIndex,screenWidth,time);
move(++currIndex,0,time);
}
} //监听动作
//prev
left.onclick = function(){
toLeft();
}
//next
right.onclick = function(){
toRight();
} document.addEventListener('mousedown',function(e){
isTouch = true;
axis.x = e.clientX;
axis.y = e.clientY;
}); document.addEventListener('mousemove',function(e){
if(isTouch){
distance = e.clientX - axis.x;
if(distance>0){
//next
if(currIndex<pagesLen){
//此时需要看到实时移动效果,所以时间为0
move(currIndex,distance,0);
//当前页与上一页之间总是相差一个屏宽
move(currIndex+1,distance-screenWidth,0);
}
}else{
if(currIndex>0){
//prev
move(currIndex,distance,0);
move(currIndex-1,screenWidth+distance,0);
}
}
}
}); document.addEventListener('mouseup',function(e){
isTouch = false;
//反弹条件
var band = Math.ceil(screenWidth * 0.3);
//next
if(distance >0 && currIndex < pagesLen){
if(distance > band){
toRight();
}else{
//滑动距离太小,页面反弹
move(currIndex,0,time);
move(currIndex+1,-screenWidth,time);
}
return;
}
//prev
if(distance < 0 && currIndex > 0){
if(-distance > band){
toLeft();
}else{
//反弹
move(currIndex,0,time);
move(currIndex-1,screenWidth,time);
}
}
}); }())

最后发现有一点小问题,滑动之后再点翻页按钮,乱套了。仔细分析之后,找出了问题所在,松手时的移动距离不应该用滑动时的最后距离,所以修复很容易。

 //初始化
;(function(){
var pages = document.querySelectorAll('li');
var width = 320;
var len = pages.length;
var setpost = function(element){
element.style.transform = 'translate3d(-'+width+'px, 0, 0)';
} //把除1以外的页堆在左边
while(--len){
setpost(pages[len]);
}
}()); //控制逻辑
;(function(){
//获取所有页面
var pages = document.querySelectorAll('li');
//左右翻页按钮
var left = document.querySelector('.left');
var right = document.querySelector('.right');
//取得所有的子页面
var pagesLen = pages.length-1;
//屏宽
var screenWidth = 320;
//反弹时间
var time = 300; //标记当前页面
var currIndex = 0; //标记是否触发滑动
var isTouch = false;
//记录当前位置
var axis = {
x:0,
y:0
} //移动页面
var move = function(index,width,time){
var page = pages[index];
page.style.transform = 'translate3d('+width+'px, 0, 0)';
page.style.transitionDuration = time+'ms';
} //上一页
var toLeft = function(){
if(currIndex >0){
move(currIndex,-screenWidth,time);
move(--currIndex,0,time);
}
} //下一页
var toRight = function(){
if(currIndex < pagesLen){
move(currIndex,screenWidth,time);
move(++currIndex,0,time);
}
} //监听动作
//prev
left.onclick = function(){
toLeft();
}
//next
right.onclick = function(){
toRight();
} document.addEventListener('mousedown',function(e){
isTouch = true;
axis.x = e.clientX;
axis.y = e.clientY;
}); document.addEventListener('mousemove',function(e){
if(isTouch){
//滑动距离
var distance = e.clientX - axis.x;
if(distance>0){
//next
if(currIndex<pagesLen){
//此时需要看到实时移动效果,所以时间为0
move(currIndex,distance,0);
//当前页与上一页之间总是相差一个屏宽
move(currIndex+1,distance-screenWidth,0);
}
}else{
if(currIndex>0){
//prev
move(currIndex,distance,0);
move(currIndex-1,screenWidth+distance,0);
}
}
}
}); document.addEventListener('mouseup',function(e){
//松手时的移动距离
var distance = e.clientX - axis.x;
//反弹条件
var band = Math.ceil(screenWidth * 0.3);
isTouch = false;
//next
if(distance >0 && currIndex < pagesLen){
if(distance > band){
toRight();
}else{
//滑动距离太小,页面反弹
move(currIndex,0,time);
move(currIndex+1,-screenWidth,time);
}
return;
}
//prev
if(distance < 0 && currIndex > 0){
if(-distance > band){
toLeft();
}else{
//反弹
move(currIndex,0,time);
move(currIndex-1,screenWidth,time);
}
}
}); }())

到此,这个简易的移动应用就建好了。发现这其实只是搭好了一个架子,里边还有很多内容可以填。比如,给每页加点背景和文字,让页面看起来更加丰满,给标题栏加点工具图标,让它看起来更像是一个原生的apk程序。当我们双击或长按页面空白区域的时候,自动隐藏或显示翻页按钮,增加对更多浏览器的支持,增加对移动设备的支持........

可以发挥的地方太多太多了,锦上添花的事就只好交给各位了。

一步一步做下来,收获了些什么呢?总结一下:

首先要有一个清晰的思路,先确定要实现什么功能,在脑海里有一个整的印象。把UI先建起来,这一步很容易实现,在此基础上,我们就可以看到,有哪些功能需要js去做,哪些效果需要css去做。先易后难。先整体后局部。在做的过程中,一步一步的完善,扩展,优化。一开始就想着要多完美,多优化,结果只是不断的否定自己的想法。不要怕出错,前面的演示中,我们发现,每一步都有些小错误,但是只要我们的整体思路是符合预期的,修正起来就会很快,这个修错的过程,也是一次学习的机地,总结的多了,以后就可以少出错,少被坑。

效果图:

加点内容,是不是立马显得高大上了呀!

源码打包下载:https://github.com/bjtqti/swipe.git

本文系原创,如果喜欢就砸个赞吧!

webapp应用--模拟电子书翻页效果的更多相关文章

  1. javascript移动端 电子书 翻页效果

    1.后端给一长串的纯文本 2.前端根据屏幕的高度,将文本切割为 n 页 3.使用插件 turn.js 将切割好的每页,加上翻书效果 <!DOCTYPE html> <html lan ...

  2. Android电子书翻页效果实现

    这篇文章是在参考了别人的博客基础上,修改了其中一个翻页bug,并且加了详细注释 先看效果 其中使用了贝赛尔曲线原理,关于贝赛尔曲线的知识,推荐大家看下http://blog.csdn.net/hmg2 ...

  3. 6个超炫酷的HTML5电子书翻页动画

    相信大家一定遇到过一些电子书网站,我们可以通过像看书一样翻页来浏览电子书的内容.今天我们要分享的HTML5应用跟电子书翻页有关,我们精选出来的6个电子书翻页动画都非常炫酷,而且都提供源码下载,有需要的 ...

  4. c#翻页效果

    用c#和GDI+实现杂志翻页动画效果时间:2010-01-13 blog.csdn.net 周公 - 说明:以前本人参与个一个电子杂志项目,当时要求实现模拟现实生活中的杂志翻页动画效果,别人推荐了这篇 ...

  5. Android 实现书籍翻页效果----完结篇

    By 何明桂(http://blog.csdn.net/hmg25) 转载请注明出处 之前由于种种琐事,暂停了这个翻页效果的实现,终于在这周末完成了大部分功能,但是这里只是给出了一个基本的雏形,没有添 ...

  6. Android 实现书籍翻页效果----升级篇

    自从之前发布了<Android 实现书籍翻页效果----完结篇 >之后,收到了很多朋友给我留言,前段时间由于事情较多,博客写得太匆忙很多细节地方没有描述清楚.所以不少人对其中的地方有不少不 ...

  7. Android 滑动效果高级篇(七)—— 华丽翻页效果

    By 何明桂(http://blog.csdn.net/hmg25) 转载请注明出处 之前看到像ipad上的ibook的模拟书籍翻页的特效感觉很炫,在android上也有像laputa和ireader ...

  8. HTML5开发的翻页效果实例

    简介2010年F-i.com和Google Chrome团队合力致力于主题为<20 Things I Learned about Browsers and the Web>(www.20t ...

  9. 微信里经常看到的滑动翻页效果,slide

    上个星期我们的产品姐姐让我帮她写个微信里经常看到的滑动翻页效果,今天抽空写了3个小demo(只写了webkit需要chrome模拟手机看 开启touch事件), 故此写个随笔. 1.demo1,整个大 ...

随机推荐

  1. 百度 flash html5自切换 多文件异步上传控件webuploader基本用法

    双核浏览器下在chrome内核中使用uploadify总有302问题,也不知道如何修复,之所以喜欢360浏览器是因为帮客户控制渲染内核: 若页面需默认用极速核,增加标签:<meta name=& ...

  2. WebAPi之SelfHost自创建证书启动Https疑难解惑及无法正确返回结果

    前言 话说又来需求了,之前对于在SelfHost中需要嵌套页面并操作为非正常需求,这回来正常需求了,客户端现在加了https,老大过来说WebAPi访问不了了,这是什么情况,我去试了试,还真是这个情况 ...

  3. TypeScript Vs2013 下提示Can not compile modules unless '--module' flag is provided

    VS在开发TypeScript程序时候,如果import了模块有的时候会有如下提示: 这种情况下,只需要对当前TypeScript项目生成设置为AMD规范即可!

  4. CRL快速开发框架系列教程六(分布式缓存解决方案)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  5. Consul 服务注册与服务发现

    上一篇:Mac OS.Ubuntu 安装及使用 Consul 1. 服务注册 对 Consul 进行服务注册之前,需要先部署一个服务站点,我们可以使用 ASP.NET Core 创建 Web 应用程序 ...

  6. 自定义搭建PHP开发环境

    学习了一段时间php了,因为之前是刚接触php,所以用的是集成安装包(wamp).现在想进一步了解apache.mysql.php之间的关系以及提升自己所以进行自定义搭建PHP开发环境.废话不多说,请 ...

  7. Oracle数据库该如何着手优化一个SQL

    这是个终极问题,因为优化本身的复杂性实在是难以总结的,很多时候优化的方法并不是用到了什么高深莫测的技术,而只是一个思想意识层面的差异,而这些都很可能连带导致性能表现上的巨大差异. 所以有时候我们应该先 ...

  8. npm 使用小结

    本文内容基于 npm 4.0.5 概述 npm (node package manager),即 node 包管理器.这里的 node 包就是指各种 javascript 库. npm 是随同 Nod ...

  9. LINQ to SQL Where条件

    1. 适用场景 实现条件的过滤和查询等功能. 2. 说明 跟SQL语句中的where作用相似,都起到了范围的限定即过滤的作用,而判断条件是紧跟后面的条件子句.where主要分为三种形式:简单形式.条件 ...

  10. JavaScript事件代理和委托(Delegation)

    JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委 ...