forked from xiaogliu/pure-full-page
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpureFullPage.js
178 lines (165 loc) · 5.67 KB
/
pureFullPage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
const utils = require('./utils');
/**
* 全屏滚动逻辑
*/
class PureFullPage {
constructor(options) {
// 默认配置
const defaultOptions = {
isShowNav: true,
delay: 1000,
definePages: () => {},
};
utils.polyfill();
// 合并自定义配置
this.options = Object.assign(defaultOptions, options);
// 将用户自定义函数绑定到实例 this
this.options.definePages = this.options.definePages.bind(this);
// 获取翻页容器
this.container = document.querySelector('#pureFullPage');
// 获取总页数,创建右侧点导航时用
this.pages = document.querySelectorAll('.page');
this.pagesNum = this.pages.length;
// 初始化右侧点导航,以备后用
this.navDots = [];
// 获取当前视图高度
this.viewHeight = document.documentElement.clientHeight;
// 当前位置,负值表示相对视图窗口顶部向下的偏移量
this.currentPosition = 0;
// 截流/间隔函数延迟时间,毫秒
this.DELAY = this.options.delay;
// 检测滑动方向,只需要检测纵坐标
this.startY = undefined;
}
// window resize 时重新获取位置
getNewPosition() {
this.viewHeight = document.documentElement.clientHeight;
this.container.style.height = `${this.viewHeight}px`;
let activeNavIndex;
this.navDots.forEach((e, i) => {
if (e.classList.contains('active')) {
activeNavIndex = i;
}
});
this.currentPosition = -(activeNavIndex * this.viewHeight);
this.turnPage(this.currentPosition);
}
handleWindowResize(event) {
// 设置防抖动函数
utils.debounce(this.getNewPosition, this, event, this.DELAY);
}
// 页面跳转
turnPage(height) {
this.container.style.top = `${height}px`;
}
// 随页面滚动改变样式
changeNavStyle(height) {
if (this.options.isShowNav) {
this.navDots.forEach(el => {
utils.deleteClassName(el, 'active');
});
const i = -(height / this.viewHeight);
this.navDots[i].classList.add('active');
}
}
// 创建右侧点式导航
createNav() {
const nav = document.createElement('div');
nav.className = 'nav';
this.container.appendChild(nav);
// 有几页,显示几个点
for (let i = 0; i < this.pagesNum; i++) {
nav.innerHTML += '<p class="nav-dot"><span></span></p>';
}
const navDots = document.querySelectorAll('.nav-dot');
this.navDots = Array.prototype.slice.call(navDots);
// 添加初始样式
this.navDots[0].classList.add('active');
// 添加点式导航点击事件
this.navDots.forEach((el, i) => {
el.addEventListener('click', () => {
// 页面跳转
this.currentPosition = -(i * this.viewHeight);
// 处理用户自定义函数
this.options.definePages();
this.turnPage(this.currentPosition);
// 更改样式
this.navDots.forEach(el => {
utils.deleteClassName(el, 'active');
});
el.classList.add('active');
});
});
}
goUp() {
// 只有页面顶部还有页面时页面向上滚动
if (-this.container.offsetTop >= this.viewHeight) {
// 重新指定当前页面距视图顶部的距离 currentPosition,实现全屏滚动,currentPosition 为负值,越大表示超出顶部部分越少
this.currentPosition = this.currentPosition + this.viewHeight;
this.turnPage(this.currentPosition);
this.changeNavStyle(this.currentPosition);
// 处理用户自定义函数
this.options.definePages();
}
}
goDown() {
// 只有页面底部还有页面时页面向下滚动
if (-this.container.offsetTop <= this.viewHeight * (this.pagesNum - 2)) {
// 重新指定当前页面距视图顶部的距离 currentPosition,实现全屏滚动,currentPosition 为负值,越小表示超出顶部部分越多
this.currentPosition = this.currentPosition - this.viewHeight;
this.turnPage(this.currentPosition);
this.changeNavStyle(this.currentPosition);
// 处理用户自定义函数
this.options.definePages();
}
}
// 鼠标滚动逻辑(全屏滚动关键逻辑)
scrollMouse(event) {
const delta = utils.getWheelDelta(event);
// delta < 0,鼠标往前滚动,页面向下滚动
if (delta < 0) {
this.goDown();
} else {
this.goUp();
}
}
// 触屏事件
touchEnd(event) {
const endY = event.changedTouches[0].pageY;
if (endY - this.startY < 0) {
// 手指向上滑动,对应页面向下滚动
this.goDown();
} else {
// 手指向下滑动,对应页面向上滚动
this.goUp();
}
}
// 初始化函数
init() {
this.container.style.height = `${this.viewHeight}px`;
// 创建点式导航
if (this.options.isShowNav) {
this.createNav();
}
// 设置截流函数
const handleMouseWheel = utils.throttle(this.scrollMouse, this, this.DELAY);
// 鼠标滚轮监听,火狐鼠标滚动事件不同其他
if (navigator.userAgent.toLowerCase().indexOf('firefox') === -1) {
document.addEventListener('mousewheel', handleMouseWheel);
} else {
document.addEventListener('DOMMouseScroll', handleMouseWheel);
}
// 手机触屏屏幕
document.addEventListener('touchstart', event => {
this.startY = event.touches[0].pageY;
});
const handleTouchEnd = utils.throttle(this.touchEnd, this, 500);
document.addEventListener('touchend', handleTouchEnd);
document.addEventListener('touchmove', event => {
event.preventDefault();
});
// 窗口尺寸变化时重置位置
window.addEventListener('resize', this.handleWindowResize.bind(this));
}
}
module.exports = PureFullPage;