-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscript.js
152 lines (127 loc) · 3.98 KB
/
script.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
const AnimateOnScroll = function ({ offset } = { offset: 10 }) {
// 定义屏幕的顶部、底部和侧面
const windowTop = offset * window.innerHeight / 100;
const windowBottom = window.innerHeight - windowTop;
const windowLeft = 0;
const windowRight = window.innerWidth;
this.start = element => {
window.requestAnimationFrame(() => {
// 设置自定义属性
element.style.animationDelay = element.dataset.animationDelay;
element.style.animationDuration = element.dataset.animationDuration;
// 通过将类设置为动画来启动动画
element.classList.add(element.dataset.animation);
// 将元素设置为动画
element.dataset.animated = "true";
});
};
this.inViewport = element => {
// 获取元素的边界框
const elementRect = element.getBoundingClientRect();
const elementTop =
elementRect.top + parseInt(element.dataset.animationOffset) ||
elementRect.top;
const elementBottom =
elementRect.bottom - parseInt(element.dataset.animationOffset) ||
elementRect.bottom;
const elementLeft = elementRect.left;
const elementRight = elementRect.right;
// 检查元素是否在屏幕上
return (
elementTop <= windowBottom &&
elementBottom >= windowTop &&
elementLeft <= windowRight &&
elementRight >= windowLeft);
};
// 遍历元素数组,检查元素是否在屏幕上并开始动画
this.verifyElementsInViewport = (els = elements) => {
for (let i = 0, len = els.length; i < len; i++) {
// 如果元素已经动画,则移至下一个循环
if (els[i].dataset.animated) continue;
this.inViewport(els[i]) && this.start(els[i]);
}
};
// 获取所有要动画的元素
this.getElements = () =>
document.querySelectorAll("[data-animation]:not([data-animated])");
// 更新要动画的元素列表
this.update = () => {
elements = this.getElements();
elements && this.verifyElementsInViewport(elements);
};
// 开始
window.addEventListener("load", this.update, false);
window.addEventListener(
"scroll",
() => this.verifyElementsInViewport(elements),
{ passive: true });
window.addEventListener(
"resize",
() => this.verifyElementsInViewport(elements),
{ passive: true });
};
// Initialize
const options = {
offset: 15 // percentage of the window
};
const animation = new AnimateOnScroll(options);
const MIN_SPEED = 1.5
const MAX_SPEED = 2.5
function randomNumber(min, max) {
return Math.random() * (max - min) + min
}
class Blob {
constructor(el) {
this.el = el
const boundingRect = this.el.getBoundingClientRect()
this.size = boundingRect.width
this.initialX = randomNumber(0, window.innerWidth - this.size)
this.initialY = randomNumber(0, window.innerHeight - this.size)
this.el.style.top = `${this.initialY}px`
this.el.style.left = `${this.initialX}px`
this.vx =
randomNumber(MIN_SPEED, MAX_SPEED) * (Math.random() > 0.5 ? 1 : -1)
this.vy =
randomNumber(MIN_SPEED, MAX_SPEED) * (Math.random() > 0.5 ? 1 : -1)
this.x = this.initialX
this.y = this.initialY
}
update() {
this.x += this.vx
this.y += this.vy
if (this.x >= window.innerWidth - this.size) {
this.x = window.innerWidth - this.size
this.vx *= -1
}
if (this.y >= window.innerHeight - this.size) {
this.y = window.innerHeight - this.size
this.vy *= -1
}
if (this.x <= 0) {
this.x = 0
this.vx *= -1
}
if (this.y <= 0) {
this.y = 0
this.vy *= -1
}
}
move() {
this.el.style.transform = `translate(${this.x - this.initialX}px, ${
this.y - this.initialY
}px)`
}
}
function initBlobs() {
const blobEls = document.querySelectorAll('.bouncing-blob')
const blobs = Array.from(blobEls).map((blobEl) => new Blob(blobEl))
function update() {
requestAnimationFrame(update)
blobs.forEach((blob) => {
blob.update()
blob.move()
})
}
requestAnimationFrame(update)
}
initBlobs();