-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
117 lines (99 loc) · 3.86 KB
/
index.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
function createProgressSlider(containerId, options = {}) {
const defaultOptions = {
navContainerId: `${containerId}-nav`,
slideDuration: 5000,
sliderOptions: {}
};
const config = { ...defaultOptions, ...options };
document.addEventListener("DOMContentLoaded", function() {
const slider = tns({
container: `#${containerId}`,
items: 1,
slideBy: 'page',
autoplay: false,
controls: false,
nav: false,
...config.sliderOptions
});
const slideCount = slider.getInfo().slideCount;
const navContainer = document.getElementById(config.navContainerId);
let progressTimer = null;
let isPaused = false;
function createNavButton(index) {
let button = document.createElement('button');
button.className = 'w-2 h-2 rounded-full bg-slate-100';
button.addEventListener('click', () => {
slider.goTo(index);
resetProgress();
updateActiveButton();
});
return button;
}
function createProgressBar() {
let progressBar = document.createElement('div');
progressBar.className = 'relative h-2 w-16 rounded-full overflow-hidden bg-slate-400';
let progressInner = document.createElement('div');
progressInner.className = 'h-full absolute bg-slate-100 progress-inner';
progressInner.style.width = '0%';
progressBar.appendChild(progressInner);
return progressBar;
}
function updateActiveButton() {
let info = slider.getInfo();
let index = info.index % slideCount;
Array.from(navContainer.children).forEach((btn, idx) => {
if (idx === index) {
let progressBar = createProgressBar();
navContainer.replaceChild(progressBar, btn);
if (!isPaused) {
startProgress(progressBar.querySelector('.progress-inner'));
}
} else if (btn.tagName === 'DIV') {
let newButton = createNavButton(idx);
navContainer.replaceChild(newButton, btn);
}
});
}
function startProgress(progressInner) {
resetProgress();
if (isPaused) return;
let startTime = Date.now();
let pausedTime = 0;
function animate() {
if (isPaused) {
pausedTime = Date.now() - startTime;
return;
}
let elapsed = Date.now() - startTime - pausedTime;
let progress = Math.min((elapsed / config.slideDuration) * 100, 100);
progressInner.style.width = `${progress}%`;
if (progress < 100) {
progressTimer = requestAnimationFrame(animate);
} else {
slider.goTo('next');
}
}
progressTimer = requestAnimationFrame(animate);
}
function resetProgress() {
if (progressTimer) {
cancelAnimationFrame(progressTimer);
progressTimer = null;
}
}
for (let i = 0; i < slideCount; i++) {
navContainer.appendChild(createNavButton(i));
}
const sliderElement = document.getElementById(containerId);
sliderElement.addEventListener('mouseenter', () => {
isPaused = true;
resetProgress();
});
sliderElement.addEventListener('mouseleave', () => {
isPaused = false;
updateActiveButton();
});
slider.events.on('indexChanged', updateActiveButton);
updateActiveButton();
});
}