近期写一个项目,想模仿爱分享公众号实现一个移动端垂直翻页同时带动画的效果,由于经验不足遇到了不少困难,暂时实现了一个版本后决定将经验总结出来分享并作为笔记:
先上代码
window.onload = function () {
var car = {
pages: $(".page"),
startY: 0,
currY: 0,
upY: 0,
pageNow: 0,
pageHeight:0,
pageStart : 0,
//moveStart:true,
//mouseDown:false,
page_touch_start: function (e) {
//if(!car._moveStart) return;
car.pageStart = Math.abs(parseInt($(".page1")[0].style.marginTop))||0;
if (e.type == "touchstart") {
car.startY = window.event.touches[0].pageY;
} else {
car.startY = e.pageY || e.y;
}
},
page_touch_move: function (e) {
e.preventDefault();
if (e.type == "touchmove") {
car.currY = window.event.touches[0].pageY;
} else{
car.currY = e.pageY || e.y;
};
currPage = e.currentTarget;
pageNow = parseInt(currPage.className.substring(currPage.className.length-1,currPage.className.length));
if((car.startY - car.currY)>0 && pageNow != "5"){
currPage.nextElementSibling.style.visibility = 'hidden';
$(".page1")[0].style.marginTop = '-' + ((car.startY - car.currY)+car.pageStart) + 'px';
}else if((car.startY - car.currY)>0 && pageNow == 5){
$(".page1")[0].style.marginTop = '-' + ((car.startY - car.currY)+car.pageStart) + 'px';
}else if((car.startY - car.currY)<0 && pageNow != 1){
currPage.previousElementSibling.style.visibility = 'hidden';
$(".page1")[0].style.marginTop = '-' + (car.pageStart - (car.currY-car.startY)) + 'px';
}else if((car.startY - car.currY)<0 && pageNow == 1){
$(".page1")[0].style.marginTop = '-' + (car.pageStart - (car.currY-car.startY)) + 'px';
}
},
page_touch_end: function (e) {
//car.pageHeight =car.pageHeight+ $(e.currentTarget).outerHeight();
pageNow = parseInt(e.currentTarget.className.substring(e.currentTarget.className.length-1,currPage.className.length));
car.upY = car.currY;
if((car.startY - car.currY) >= 20){
// 滚动到下一页
var indexUp = setInterval(function () {
$(".page1")[0].style.marginTop = parseInt($(".page1")[0].style.marginTop)-20 +"px";
if(Math.abs(parseInt($(".page1")[0].style.marginTop)) >= (car.pageStart+$(e.currentTarget).outerHeight()-20)&& pageNow!=5){
$(".page1")[0].style.marginTop = "-"+(car.pageStart+$(e.currentTarget).outerHeight())+"px";
clearInterval(indexUp);
$(".animation").removeClass("on");
setTimeout(function () {
$(".animation").addClass("on");
e.currentTarget.nextElementSibling.style.visibility = 'visible';
},100);
// },30);
}else if(Math.abs(parseInt($(".page1")[0].style.marginTop)) >= (car.pageStart+$(e.currentTarget).outerHeight()-20)&& pageNow == 5){
$(".page1")[0].style.marginTop = 0;
$(".page1")[0].style.visibility = 'hidden';
//car.pageHeight = 0;
clearInterval(indexUp);
$(".animation").removeClass("on");
setTimeout(function () {
$(".animation").addClass("on");
$(".page1")[0].style.visibility = 'visible';
},100);
}
},30)
}else if((car.startY - car.currY)>=0 && (car.startY - car.currY) < 20){
var indexWithholdUp = setInterval(function () {
$(".page1")[0].style.marginTop = parseInt($(".page1")[0].style.marginTop)+20 +"px";
if(Math.abs(parseInt($(".page1")[0].style.marginTop)) <= (car.pageStart+20)){
$(".page1")[0].style.marginTop = "-"+car.pageStart+"px";
clearInterval(indexWithholdUp);
$(".animation").removeClass("on");
e.currentTarget.nextElementSibling.style.visibility = 'visible';
}
},30)
} else if((car.startY-car.currY)<= -20){
var indexDown = setInterval(function () {
$(".page1")[0].style.marginTop = parseInt($(".page1")[0].style.marginTop) + 20 + 'px';
var pageInvertHeight = car.pageStart - $(e.currentTarget).outerHeight();
if(Math.abs(parseInt($(".page1")[0].style.marginTop)) <= (car.pageStart - $(e.currentTarget).outerHeight()+20)&& pageNow!=1){
$(".page1")[0].style.marginTop = "-" + pageInvertHeight + "px";
clearInterval(indexDown);
$(".animation").removeClass("on");
setTimeout(function () {
$(".animation").addClass("on");
e.currentTarget.previousElementSibling.style.visibility = 'visible';
},100);
}else if(Math.abs(parseInt($(".page1")[0].style.marginTop)) >= ($(e.currentTarget).outerHeight()-20)&& pageNow == 1){
$(".page1")[0].style.marginTop ="-" + ($(".page1").outerHeight()+$(".page2").outerHeight()+$(".page3").outerHeight()+$(".page4").outerHeight()) + "px";
$(".page5")[0].style.visibility = 'hidden';
clearInterval(indexDown);
$(".animation").removeClass("on");
setTimeout(function () {
$(".animation").addClass("on");
$(".page5")[0].style.visibility = 'visible';
},100);
}
},30)
}else if((car.startY-car.currY)<0 && (car.startY-car.currY)>-20){
var indexWithholdDown = setInterval(function () {
$(".page1")[0].style.marginTop = parseInt($(".page1")[0].style.marginTop) - 20 + 'px';
var pageInvertHeight = car.pageStart - $(e.currentTarget).outerHeight();
if(Math.abs(parseInt($(".page1")[0].style.marginTop)) >= (car.pageStart-20)){
$(".page1")[0].style.marginTop = "-" + car.pageStart + "px";
clearInterval(indexWithholdDown);
$(".animation").removeClass("on");
e.currentTarget.previousElementSibling.style.visibility = 'visible';
}
},30)
}
}
};
car.pages.on("touchstart mousedown", car.page_touch_start);
car.pages.on("touchmove mousemove", car.page_touch_move);
car.pages.on("touchend mouseup", car.page_touch_end);
};
用专业的眼光看问题不能浮于表面。
下面以移动端翻页为例,引导分析问题的过程:
(touchstart/touchmove/touchend)搜索会有很多结果;
例如:
1)start的时候要获取页面位置;
2)move的时候要让网页整体跟着手指的移动而移动;
3)end的时候要根据临界条件(比如100px的移动距离)实现上滑和下滑;
1)移动:个人采用margin-top的方案来实现各种移动
2)move阶段:直接改变margin-top的值
因为touchmove和mousemove一样在移动过程中会连续触发事件,也就是说我们认为的一次移动实际上进行了无数次的touchmove事件,因此直接改变值不会出现卡顿现象。
3)end阶段:要实现翻页的功能而且不能突然出现或隐藏。暂时没有考虑用animation,而依然利用margin-top实现。但是touchend事件只会触发一次,所以选择利用定时器定时改变margin-top的值,来实现平滑移动。
分析问题对我来说无疑是最困难的,所以当思路理清楚以后,以后遇到的问题自己也有了自己思考的路线和解决问题的方法
jquery和原生js不能函数公用,这就需要对一些对象进行类型转换(jquery封装后的对象和原生js对象)
原生对象转jquery对象:$(原生对象);
jquery对象转原生对象:$(".page")[0]
要通过`window.event.touches[0].pageY`
parseInt():字符数字转数字
nextElementSibling:下一个兄弟元素
outerHeight():包括padding的div元素的高度
target是事件触发时直接作用的对象;currentTarget是事件绑定的那个对象
1)方法一:给整个html页面包裹一个div,命名id(如animation)和class(on),其中id用来获取元素,class用来添加和删除动画。
注意:css3关于动画部分的处理要小心;
2)方法二:给每个设置动画的元素添加两个类,其中一个用来获取元素(如animation),一个用来添加和删除动画(如on)。
注意:css处理时关于同级class定义动画同时需要时,将
.animation .on .某个类名
这几个类名中间的空格去掉表示同级class,不去掉表示层级class
方法二:通过css3的transform来实现移动可能流畅性更好