经过前面四个版本的迭代,我们已经制作了一个从视觉和听觉上都很舒服的H5微场景应用,没有看过的请戳下面:
V1.0——简单页面滑动切换
V2.0——多页切换,透明过渡及交互指示
V3.0——加入loading,music及自动切换
V4.0——加入文字并给文字加特效
但是,还没有完,这一次,我们将做一些十分重要的收尾工作,才能真正完成我们的第一个H5应用,所以,let’s do it!
1、加入后悔机制——页面上滑切换功能;
2、整理目录
3、压缩样式与脚本文件
4、模板化
1、世上没有后悔药,但是应用需要更好的用户体验,就要考虑到用户的后悔,为用户提供一种后悔机制,比如我们日常软件上有删除,就有撤销删除,一样地,我们的应用如果只有切换到下一页而没有切换到上一页的功能的话,对于用户来说,是没有安全感的,因为不可控,因为无法后悔,诚然,用户可以进行第二轮切换切换到上一页,但是这种操作成本本身太高不可取,所以我们一定要为用户加入后悔机制,在我们的应用里,表现为页面的向上切换。
2、一个良好的目录结构对于一个应用来说是必要的,它对于程序的可维护性,可扩展性十分重要,所以在项目正式上线发布前,我们要整理好文件目录,甚至,可以提前到项目开始阶段,就要计划好项目的目录结构。
3、对于用户体验来说,页面的第一次加载速度永远是最重要的,如果用户等待了十几秒你的页面还没加载完成,那么里面不管有多好的内容,多好看的样式,用户也不再感兴趣,所以,为了提高加载速度,我们有必要对样式文件和脚本问价进行压缩。
4、实际工作中,我们要做的很多项目可能都是使用同样的格式和功能,只是内容不一样罢了,这时候,你绝逼不会每一个项目都将前一个项目复制一份,然后钻到页面中改内容和样式,如果只有几份你还能忍受,可如果有一千份,你会累死!所以,将我们的项目模板化,以后所有的类似项目全都通过模板生成,是一个不错的选择。
我们已经有了一个页面切换函数,而且我们不想将这个函数复制一遍然后将里面的序号递增改为序号递减,所以,我们怎么做,对,给页面函数加一个参数,在函数体里根据参数值来决定它切换的方向,代码如下:
myfn.js
/** * Created by hjb2722404 on 2015/6/4. */
$(function(){
var curpage=1;
var totalpage,nextpage,prepage,lastpage,nexttotalpage,pretotalpage;
//获取总页数,以及总页数的+1/-1后的序号,供后面for循环使用
totalpage = $(".page").length;
nexttotalpage = totalpage + 1;
pretotalpage = totalpage - 1;
window.onload = function(){
$(".loader").css("z-index","1");
$(".upicon").css("z-index","1000");
initAudio("audio");
}
var audio;
function initAudio(id){
audio = document.getElementById(id);
}
document.addEventListener('touchmove',function(event){
event.preventDefault(); },false);
$(".page").swipeUp(function(){
swichpage("up");
})
$(".page").swipeDown(function(){
swichpage("down");
})
//控制音乐播放停止和音乐ico图标变换
$("#audioPlay").on('click',function(){
if(audio.paused){
audio.play();
this.style.backgroundImage="url(images/music_play.png)";
}else{
audio.pause();
this.style.backgroundImage="url(images/music_pause.png)";
}
});
function rnd(start, end){
return Math.floor(Math.random() * (end - start) + start);
}
var inClassArray = ['pt-page-flipInLeft','pt-page-rotatePullLeft','pt-page-rotateCubeTopIn'];
var temLength = inClassArray.length;
function swichpage(toward) {
//判断当前页是否为最后一页
//如果是最后一页,显示第一页,并移除所有page上的所有css效果类,否则显示下一页,并移除上一页的切换动画效果
if (curpage == totalpage && nextpage != pretotalpage ) {
for (var i = 1; i < nexttotalpage; i++) {
$(".page" + i).removeClass("hide");
$(".page" + i).removeClass("show");
$(".page" + i).removeClass("pt-page-moveFromBottomFade");
}
$(".page1").addClass("show");
$(".page1").addClass("pt-page-moveFromBottomFade");
curpage = 1;
} else {
if(toward=="up"){
console.log("up");
nextpage = curpage + 1;
lastpage = curpage - 1;
var inClass ="pt-page-moveFromBottomFade";
var outClass="pt-page-moveToTopFade";
}else if(toward=="down"){
if(curpage == 1){
return false;
}
console.log("down");
nextpage = curpage - 1;
lastpage = curpage + 1;
var outClass ="pt-page-moveToBottomFade";
var inClass="pt-page-moveFromTopFade";
}
$(".page" + curpage).removeClass(inClass);
$(".page" + curpage).addClass(outClass);
$(".page" + curpage).removeClass("show");
$(".page" + curpage).addClass("hide");
$(".page" + nextpage).removeClass("hide");
$(".page" + nextpage).addClass("show");
$(".page" + nextpage).addClass(inClass);
var randomNum = rnd(0,temLength);
setTimeout(function(){
$(".textbox"+nextpage).css('display','block');
$(".textbox"+nextpage).addClass(inClassArray[randomNum]);
},1000);
$(".page" + lastpage).removeClass(outClass);
curpage = nextpage;
}
}
setInterval(function(){
swichpage("up");
},8000);
})
整理后的目录结构如下:
别忘了修改各个文件中的引用
例如:index.html
<link rel="stylesheet" href="css/animate.css" type="text/css"/>
<link rel="stylesheet" href="css/animations.css" type="text/css"/>
<link rel="stylesheet" href="css/loading.css" type="text/css"/>
<link rel="stylesheet" href="css/style.css" type="text/css"/>
</head>
……
<script src="http://apps.bdimg.com/libs/zepto/1.1.4/zepto.min.js"></script>
<script src="js/touch.js"></script>
<script src="js/myfn.js"></script>
</body>
这里,我们要压缩的是CSS文件和JS文件,必要时候也可以利用工具将几个JS文件或CSS文件合并为一个文件,我们这里只演示一下压缩我们的主样式表style.css和主脚本文件myfn.js文件
首先来看看压缩前的style.css:
#pages { width: 100%; heigt: 100%; }
.page { width: 100%; height: 100%; position: absolute; top: 0; left: 0; color: white; z-index: 1; }
.page1 { background: blue; display: block; z-index: 100; }
.hide { z-index: 99; }
.show { z-index: 100; }
.upicon { width: 60px; height: 60px; position: absolute; left: 50%; bottom: 20px; margin-left: -30px; z-index: 1000; }
.upicon img { width: 60px; }
#audioPlay { width: 38px; height: 38px; background-image: url("../images/music_play.png"); background-repeat: no-repeat; background-size: 100% 100%; position: absolute; top: 5%; right: 5%; z-index: 9999999; }
然后是压缩后的style.min.css,我用的是在线压缩工具:
看看压缩前后的文件大小对比:
再来看看myfn.js的压缩,压缩前:
myfn.js
/** * Created by hjb2722404 on 2015/6/4. */
$(function() {
var curpage = 1;
var totalpage, nextpage, prepage, lastpage, nexttotalpage, pretotalpage;
//获取总页数,以及总页数的+1/-1后的序号,供后面for循环使用
totalpage = $(".page").length;
nexttotalpage = totalpage + 1;
pretotalpage = totalpage - 1;
window.onload = function() {
$(".loader").css("z-index", "1");
$(".upicon").css("z-index", "1000");
initAudio("audio");
}
var audio;
function initAudio(id) {
audio = document.getElementById(id);
}
document.addEventListener('touchmove', function(event) {
event.preventDefault();
}, false);
$(".page").swipeUp(function() {
swichpage("up");
})
$(".page").swipeDown(function() {
swichpage("down");
})
//控制音乐播放停止和音乐ico图标变换
$("#audioPlay").on('click', function() {
if (audio.paused) {
audio.play();
this.style.backgroundImage = "url(images/music_play.png)";
} else {
audio.pause();
this.style.backgroundImage = "url(images/music_pause.png)";
}
});
function rnd(start, end) {
return Math.floor(Math.random() * (end - start) + start);
}
var inClassArray = ['pt-page-flipInLeft', 'pt-page-rotatePullLeft', 'pt-page-rotateCubeTopIn'];
var temLength = inClassArray.length;
function swichpage(toward) {
//判断当前页是否为最后一页
//如果是最后一页,显示第一页,并移除所有page上的所有css效果类,否则显示下一页,并移除上一页的切换动画效果
if (curpage == totalpage && nextpage != pretotalpage) {
for (var i = 1; i < nexttotalpage; i++) {
$(".page" + i).removeClass("hide");
$(".page" + i).removeClass("show");
$(".page" + i).removeClass("pt-page-moveFromBottomFade");
}
$(".page1").addClass("show");
$(".page1").addClass("pt-page-moveFromBottomFade");
curpage = 1;
} else {
if (toward == "up") {
console.log("up");
nextpage = curpage + 1;
lastpage = curpage - 1;
var inClass = "pt-page-moveFromBottomFade";
var outClass = "pt-page-moveToTopFade";
} else if (toward == "down") {
if (curpage == 1) {
return false;
}
console.log("down");
nextpage = curpage - 1;
lastpage = curpage + 1;
var outClass = "pt-page-moveToBottomFade";
var inClass = "pt-page-moveFromTopFade";
}
$(".page" + curpage).removeClass(inClass);
$(".page" + curpage).addClass(outClass);
$(".page" + curpage).removeClass("show");
$(".page" + curpage).addClass("hide");
$(".page" + nextpage).removeClass("hide");
$(".page" + nextpage).addClass("show");
$(".page" + nextpage).addClass(inClass);
var randomNum = rnd(0, temLength);
setTimeout(function() {
$(".textbox" + nextpage).css('display', 'block');
$(".textbox" + nextpage).addClass(inClassArray[randomNum]);
}, 1000);
$(".page" + lastpage).removeClass(outClass);
curpage = nextpage;
}
}
setInterval(function() {
swichpage("up");
}, 8000);
})
压缩后的myfn.min.js:
myfn.min.js
看看压缩前后大小对比:
压缩后大小只是压缩前一半大小。
别忘了在index.html中把引用改了。
index.html
……
<link rel="stylesheet" href="css/style.min.css" type="text/css"/>
……
<script src="js/myfn.min.js"></script>
模板化的思路是将Index.html页面中所有的变量(比如图片路径,内部样式的值等等)用变量符号代替,将来由后端程序解析替换为数据库中的数据,动态生成最终静态页面。
模板化的另一个好处是,由于模板化支持循环输出,所以我们不必再在页面中将格式相同的元素复制N份。
这里我们约定所有由模板解析的变量格式为 {{$变量名}}
,for循环的写法为{{for n=N $array}}...{{for end}}
,if判断的写法为:{{if condition}}...{{if end}}
依据这个原则,我们将index.html模板化为index.htm,模板化之后的代码如下:
index.htm
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="renderer" content="webkit"> <title>{{$title}}</title> <link rel="stylesheet" href="css/animate.css" type="text/css"/> <link rel="stylesheet" href="css/animations.css" type="text/css"/> <link rel="stylesheet" href="css/loading.css" type="text/css"/> <link rel="stylesheet" href="css/style.min.css" type="text/css"/> <style> {{for n=9 $arrayPage}} .page{{n}}{background-image: url({{$array[n][imgurl]}}); background-repeat: {$array[n][bgrepeat]}; background-size: {{$array[n][bgsize]}};} {{for end}} .textbox {display:none;} {{for n=9 $arrayTextbox}} .textbox{{n}}{width:{{$arrayTextbox[n][width]}}; height: {{$arrayTextbox[n][height]}}; position: {{$arrayTextbox[n][position]}}; top:{{$arrayTextbox[n][top]}}; left: {{$arrayTextbox[n][left]}};right:{{$arrayTextbox[n][right]}}; margin-left: {{$arrayTextbox[n][maginleft]}}; margin-top: {{$arrayTextbox[n][marginright]}}; color:{{$arrayTextbox[n][color]}};-webkit-writing-mode:{{$arrayTextbox[n][horizontal-tb]}};writing-mode:{{$arrayTextbox[n][wrimod]}};writing-mode:{{$arrayTextbox[n][horizontal-tb]}};} {{for end}} </style> </head> <body> <div class='loader loader--spinningDisc'></div> <audio src="{{$mp3url}}" autoplay="autoplay" id="audio" hidden="hidden" loop="loop"></audio> <div id="audioPlay"></div> <div id="pages"> {{for n=9 $arrayPageCon}} <div class="page page{{n}}"> <div class="textbox{{n}} {{if n=1}} pt-page-rotateCubeTopIn {{if end}}"> {{$arrayPageCon[n][textCon]}} </div> </div> {{for end}} </div> <div class="upicon animated infinite bounce "><img src="images/upicon.png" alt=""/></div> <script src="http://apps.bdimg.com/libs/zepto/1.1.4/zepto.min.js"></script> <script src="js/touch.js"></script> <script src="js/myfn.min.js"></script> </body> </html>
这样,后端程序只需要从数据库取到相应的变量值和几个二维数组,就可以将模板中的变量全部替换,并生成新的静态页面了。
到此为止,我们的第一个H5应用就全部制作完成并完成了模板化,然后就可以去掉不要的文件(style.css,myfn.js,less文件等),打包上传至服务器了。
还要注意的一点是,如果你是要将此应用在微信里分享,还要在index.html的头部写好相关分享信息,并制作一张分享用的图片,这个下次会单独讲,与本文并无必然关联,就先不讲了。