实现小小的fullpage

本文来自 @小强 的投稿,非常感谢!


需求背景

今天运营给了一个需求,要做个引导页,也就是全屏滚动。考虑到只有3张图,就自己码个吧!说干就干。

思路

设置一个外层container, 用户的可见区域,也就是全屏

container内有3个层次,每个层次大小都跟container一样大小

每次滚动时候通过css的transform属性进行偏移,并结合transition过渡一下效果

*{
    margin: 0;
    padding: 0;
}
.container{
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 99999;
    overflow: hidden;
}
.scrollContainer{
    display: none;
    transition: all ease 1s;
}
.slide1{
    background-color: rgb(27, 188, 155);
}
.slide2{
    background-color: rgb(255, 153, 0);
}
.slide3{
    background-color: rgb(123, 170, 190);
}
<div class="container">
    <div class="scrollContainer">
        <div class="slide slide1">
        </div>
        <div class="slide slide2">
        </div>
        <div class="slide slide3">
        </div>
    </div>
</div>

scrollContainer是用来滚动内容的,所以在页面进入的时候要获取用户区域

var $container = $('.container');
var $scroll = $container.find('.scrollContainer');
var height = $container.height();
var len = 3;
var current = 1;
$container.find('.slide').css('height', height + 'px');
$scroll.show();

逻辑部分

为了防止滚动多次滚动,需要通过一个变量来控制是否滚动,这里的动画是1s执行完,使用setTimeout延迟1s后解锁,这样大体逻辑差不多

// page控制器
var len = 3;
var current = 1;
var page = {
    isScrolling: false,
    next: function() {
        if((current + 1)  0) {
            current -= 1;
            page.move(current);
        }
    },
    move: function(index) {
        page.isScrolling = true;
        var di = -(index-1)*height + 'px';
        page.start = +new Date();
        $scroll.css('transform', 'translateY('+di+')');
        setTimeout(function(){
            page.isScrolling = false;
        }, 1010);
    }
};
// 滚动事件绑定
function bindMouseWheel (page) {
    var  type = 'mousewheel';
    var  deltaY = 0;
    function mouseWheelHandle (event) {
        if (page.isScrolling) {// 加锁部分
            return false;
        }
        var e = event.originalEvent || event;
        deltaY = e.deltaY;
        if (deltaY > 0) {
            page.next();
        } else if (deltaY < 0) {
            page.pre();
        }
    }
    $(document).on('mousewheel', mouseWheelHandle);
}

差不多了,大体已经完成,在浏览器中运行也几乎完美!但是我们是一家千牛应用,在千牛里面运行,看似不错,但是鼠标快速移动就会出现闪屏、多滚动问题。

解决问题

出现这个问题,第一反应是代码写错了,没有兼容浏览器,但是一想千牛就是chrome内核,不需要写兼容代码啊!

方案1

不采用css动画,采用jquery动画。改变top值。

也尝试了这个方案,选择800毫秒效果相对最佳。

方案2

继续思考一开始的思路为啥出现问题。经过老大提醒,并结合千牛之前出现的css动画问题,感觉是动画结束和js控制没有达到一致。为了验证这个假设,去除setTimeout延迟,添加webkitTransitionEnd事件,并打印出每次滚动时间。

// page控制更改
 move: function(index) {
    page.isScrolling = true;
    var di = -(index-1)*height + 'px';
    page.start = +new Date();
    $scroll.css('transform', 'translateY('+di+')');
},
// 添加了滚动结束控制
moveEnd: function() {
    page.end = +new Date();
    console.log('end', (page.end - page.start)/1000);
    page.isScrolling = false;
}
// 给添加滚动结束事件
$scroll.on('webkitTransitionEnd', page.moveEnd);

最终结果了滚动出现的问题,再查看每次滚动时间

end 1.022
end 1.055
end 2.344
end 2.273

在chrome里面查看滚动时间

end 0.999
end 0.994
end 1.006
end 1.023
end 0.991
end 0.997
end 1.005
end 1.046

结论

从结果来看在chrome里面css动画几乎没有延迟的跟设定1s过渡时间基本吻合,但是在千牛应用里面能够看出css动画会受其他条件影响,比如上面所遇到的鼠标滚动过快等因素。

所以在css动画这方面就应该用css动画事件来控制。除了过渡有且只有webkitTransitionEnd事件,动画开始webkitAnimationStart,动画结束事件webkitAnimationEnd,动画重复运动事件 webkitAnimationIteration。后面再玩玩

演示地址


本文由 w3cmark_前端笔记 版权所有,转载时请注明出处。
注明出处格式:w3cmark (http://www.w3cmark.com/2016/fullpage.html)

分享到:

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
关注w3cmark
微信公众号 w3cmark_com