原生JS写全屏滚动插件教程
第二节
让每一屏有点不同
我们简单的给第一屏和第二屏加个class以示区分
<!-- 每一屏滚动的容器-page1 -->
<div class="page-item page1">
<h2>Page1</h2>
</div>
<!-- 每一屏滚动的容器-page2 -->
<div class="page-item page2">
<h2>Page1</h2>
</div>
加点样式
为每个page设置不同的背景色以示区分
.page-item.page1 {
background: #99CC33;
}
.page-item.page2 {
background: #99CCCC;
}
再把h2标签的样式处理一下
.page-item h2 {
margin: 0;
padding: 20px 0;
text-align: center;
}
这时候再看看效果,第一屏和第二屏是有点背景色区别的,文字位置也更合理了
全屏滚动所需样式
想要实现全屏滚动,必须要禁用传统滚动条的平滑滚动,所以我们需要让滚动容器设为绝对定位,并相对于上层的容器。
.page-container {
width: 100%;
height: 100%;
overflow: hidden; /*禁用滚动条*/
position: relative; /*相对定位*/
}
.page-item {
position: absolute; /*绝对定位*/
top: 0;
left: 0;
width: 100%;
height: 100%;
transform: translate3d(0,100%,0); /*设置每一屏的初始位置*/
}
/* .page-item容器必须要有.transition 定义滚动时的过渡动画 */
.page-item.transition {
transition: all 500ms cubic-bezier(0.550, 0.085, 0.000, 0.990);
}
transform: translate3d(0,100%,0);这句的意思是让元素向下位移100%高度的位置,也就是初始的时候所有屏都是在屏幕的下方蓄势待发的,等加载出来的时候会让第一屏优先移到第一位置,或者可以自由的决定进入页面时想从第二屏开始都可以。
.page-item.transition是为了控制没有滚动的时候(比如初始化的时候)可以移除过渡效果,设置translate3d时可以迅速就位
cubic-bezier(0.550, 0.085, 0.000, 0.990)表示过渡时的速度曲线,即贝塞尔曲线,具体可了解关于transition属性的文档 transition-timing-function
初始化过渡动画及元素位置
首先定义所需变量
var pageContainer = document.querySelector('.page-container');
var pageItems = document.querySelectorAll('.page-item');
var count = pageItems.length;
var page = 1; // 记录当前屏序号,默认第1屏开始
var canNext = false, canPrev = false; // 控制能否继续滚下一屏或者上一屏的开关
var canSlide = true; // 控制阻止滚动的开关
然后定义初始化过渡动画及元素位置的函数
// 初始化过渡动画
function initAnimation() {
// 循环遍历每一屏,设置初始位置和过渡动画属性
for (var i = 0, len=count; i < len; i++) {
var item = pageItems[i];
// 使第一屏置于屏幕中
if (i === page-1) {
item.style.transform = 'translate3d(0, 0, 0)';
} else {
// 通过js设置元素的css样式属性transform,达到动态的控制每一屏的位置。
if (i < page-1) {
item.style.transform = 'translate3d(0, -100%, 0)';
} else if (i > page-1) {
item.style.transform = 'translate3d(0, 100%, 0)';
}
}
// 让所有屏都加上过渡动画class
item.classList.add('transition');
}
// 初始允许滚动
canSlide = true;
if (page <= 1){
canNext = true;
} else if (page >= count){
canPrev = true;
}
}
上下滚动函数
首先在滚动之前需要准确的控制应该在什么时候可以滚动、什么时候可以向下滚动、什么时候可以向上滚动。
// 控制滚动限制函数
function slideCtrl() {
// 触发全屏滚动时阻止多次触发, 得等一屏滚动结束后才可以继续滚动
canSlide = false;
// 控制各种情况的可上下滚动限制。
if (page == count) {
canNext = false;
canPrev = true;
} else if (page == 1) {
canNext = true;
canPrev = false;
} else {
canNext = true;
canPrev = true;
}
}
然后定义上下滚动的方法函数,并调用控制滚动限制函数
// 滚动下一屏
function slideNext() {
pageItems[page - 1].style.transform = 'translate3d(0, -100%, 0)';
pageItems[page].style.transform = 'translate3d(0, 0, 0)';
page++;
slideCtrl()
}
// 滚动上一屏
function slidePrev() {
pageItems[page - 2].style.transform = 'translate3d(0, 0, 0)';
pageItems[page - 1].style.transform = 'translate3d(0, 100%, 0)';
page--;
slideCtrl()
}
鼠标滚轮事件完成全屏滚动
我们需要初始化事件,
// 初始化事件
function initEvent() {
// 添加鼠标滚轮事件,为了兼容firefox浏览器多监听了DOMMouseScroll
document.addEventListener('DOMMouseScroll', wheelFunc);
document.addEventListener('mousewheel', wheelFunc);
// 当每次滑动结束后的触发的事件
pageContainer.addEventListener('transitionend', transitionend);
}
// 鼠标滚轮事件
function wheelFunc(e){
// 参数e代表当前事件的event对象,会给出当前事件的所有信息。
var e = e || window.event;
// 用事件对象给出的信息判断是滚轮向上或者向下
if (e.wheelDeltaY < 0 || e.wheelDelta < 0 || e.detail > 0) {
// 每次滚动前都需要确认滚动开关是否都为true
// xx && xx && xx() 等同于 if (xx && xx) { xx() };
canSlide && canNext && slideNext();
} else if (e.wheelDeltaY > 0 || e.wheelDelta > 0 || e.detail < 0) {
canSlide && canPrev && slidePrev();
}
}
// 这里对应了前面的slideCtrl函数,滚动时阻止多次滚轮触发,滚动结束时才可继续触发。
// 如果不理解可以把slideCtrl函数里的canSlide = false;这句去掉,再查看效果便知。
function transitionend() {
canSlide = true;
}
// 启动初始化动画和事件,完成全屏滚动的实现
function start() {
initAnimation()
initEvent()
}
start()
至此,我们已经实现了一个最简单版的全屏滚动,往下翻看看编辑器里的效果如何。
查看效果
编辑器区域太小可以点击 全屏展示
这时你可以在Html面板里加多一些page-item,再次运行可以进行更多屏的滚动效果。
<!-- 增加更多的page-item -->
<div class="page-item">
<h2>Page more</h2>
</div>
请认真理解清楚你在编辑器里的Js代码,如有不清楚的api(比如:document.addEventListener、document.querySelectorAll),请一定要查文档了解清楚,因为后面会涉及到javascript更高级的语法,本教程不会太细致讲解每一个知识点,实验出真理才是最重要的。
本节到此结束
下一节:完善更多功能
如有疑问或建议请发送到此邮箱反馈lipten@foxmail.com