移动端垂直翻页+css3动画经验总结

近期写一个项目,想模仿爱分享公众号实现一个移动端垂直翻页同时带动画的效果,由于经验不足遇到了不少困难,暂时实现了一个版本后决定将经验总结出来分享并作为笔记:
先上代码

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);
};

一、学会分析问题,

用专业的眼光看问题不能浮于表面。
下面以移动端翻页为例,引导分析问题的过程:

1、首先要弄清楚几个主要的鼠标事件:

(touchstart/touchmove/touchend)搜索会有很多结果;

2、其次,分析事件触发过程以及在这个过程中需要得到的网页信息

例如:
1)start的时候要获取页面位置;
2)move的时候要让网页整体跟着手指的移动而移动;
3)end的时候要根据临界条件(比如100px的移动距离)实现上滑和下滑;

3、再次,怎样实现上一阶段的需求,一条一条的解决

1)移动:个人采用margin-top的方案来实现各种移动
2)move阶段:直接改变margin-top的值

因为touchmove和mousemove一样在移动过程中会连续触发事件,也就是说我们认为的一次移动实际上进行了无数次的touchmove事件,因此直接改变值不会出现卡顿现象。

3)end阶段:要实现翻页的功能而且不能突然出现或隐藏。暂时没有考虑用animation,而依然利用margin-top实现。但是touchend事件只会触发一次,所以选择利用定时器定时改变margin-top的值,来实现平滑移动。

二、当中遇到的主要问题:

分析问题对我来说无疑是最困难的,所以当思路理清楚以后,以后遇到的问题自己也有了自己思考的路线和解决问题的方法

1、原生js对象和jquery对象之间的转换:

jquery和原生js不能函数公用,这就需要对一些对象进行类型转换(jquery封装后的对象和原生js对象)

原生对象转jquery对象:$(原生对象);
jquery对象转原生对象:$(".page")[0]

2、touch事件的pageY属性不能直接通过e对象获得:

要通过`window.event.touches[0].pageY`

3、个人新接触或者不熟悉的一些方法和属性:

parseInt():字符数字转数字
nextElementSibling:下一个兄弟元素
outerHeight():包括padding的div元素的高度

4、target和currentTarget的区别:

target是事件触发时直接作用的对象;currentTarget是事件绑定的那个对象

5、js动态控制css3动画的开始和结束:通过类名的添加和删除来实现

具体实现过程中考虑的问题:

1)方法一:给整个html页面包裹一个div,命名id(如animation)和class(on),其中id用来获取元素,class用来添加和删除动画。

注意:css3关于动画部分的处理要小心;

2)方法二:给每个设置动画的元素添加两个类,其中一个用来获取元素(如animation),一个用来添加和删除动画(如on)。

注意:css处理时关于同级class定义动画同时需要时,将.animation .on .某个类名这几个类名中间的空格去掉表示同级class,不去掉表示层级class

3、补充

方法二:通过css3的transform来实现移动可能流畅性更好

你可能感兴趣的:(案例总结)