Skip to content

Commit eb5c4cb

Browse files
committed
Feature: adding Marquee script
1 parent d804987 commit eb5c4cb

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

Dist/Functional/Marquee.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
'use strict';
2+
3+
class Marquee {
4+
constructor(_container) {
5+
try {
6+
this.container = _container;
7+
this.elements = Array.from(this.container.children);
8+
if (this.elements.length === 0) throw new Error("No elements found inside the marquee container.");
9+
this.speed =_container.getAttribute('wt-marquee-speed') || 50;
10+
this.direction = _container.getAttribute('wt-marquee-direction') || 'left'
11+
this.viewportWidth = window.innerWidth;
12+
this.parentWidth = this.container.parentElement.offsetWidth;
13+
this.totalWidth = this.calculateTotalWidth();
14+
this.scrollPosition = 0;
15+
this.gapSize = this.getGapSize();
16+
17+
this.fillContainer();
18+
this.startMarquee();
19+
this.handleResize();
20+
} catch (err) {
21+
console.error(`Error initializing Marquee: ${err.message}`);
22+
}
23+
}
24+
25+
calculateTotalWidth() {
26+
const gapTotal = (this.elements.length - 1) * this.gapSize;
27+
return this.elements.reduce((total, el) => total + el.offsetWidth, 0) + gapTotal;
28+
}
29+
30+
getGapSize() {
31+
const styles = getComputedStyle(this.container);
32+
return parseFloat(styles.gap) || 0;
33+
}
34+
35+
fillContainer() {
36+
let totalWidth = this.calculateTotalWidth();
37+
const targetWidth = this.parentWidth * 1.5;
38+
39+
while (totalWidth < targetWidth) {
40+
this.elements.forEach(el => {
41+
const clone = el.cloneNode(true);
42+
this.container.appendChild(clone);
43+
});
44+
this.elements = Array.from(this.container.children);
45+
totalWidth = this.calculateTotalWidth();
46+
}
47+
}
48+
49+
startMarquee() {
50+
this.marqueeInterval = setInterval(() => {
51+
this.scrollPosition += this.direction === 'left' ? -1 : 1;
52+
53+
this.moveOffscreenElement();
54+
55+
this.container.style.transform = `translateX(${this.scrollPosition}px)`;
56+
}, this.speed);
57+
}
58+
59+
moveOffscreenElement() {
60+
const firstElement = this.container.firstElementChild;
61+
const firstElementWidth = firstElement.offsetWidth + this.gapSize;
62+
63+
if (this.direction === 'left' && this.scrollPosition <= -firstElementWidth) {
64+
this.container.style.transition = 'none';
65+
this.container.appendChild(firstElement);
66+
this.scrollPosition += firstElementWidth;
67+
requestAnimationFrame(() => {
68+
this.container.style.transition = '';
69+
});
70+
} else if (this.direction === 'right' && this.scrollPosition >= -firstElementWidth / 2) {
71+
const lastElement = this.container.lastElementChild;
72+
this.container.style.transition = 'none';
73+
this.container.insertBefore(lastElement, firstElement);
74+
this.scrollPosition -= firstElementWidth;
75+
requestAnimationFrame(() => {
76+
this.container.style.transition = '';
77+
});
78+
}
79+
}
80+
81+
handleResize() {
82+
window.addEventListener('resize', () => {
83+
clearInterval(this.marqueeInterval);
84+
this.viewportWidth = window.innerWidth;
85+
this.parentWidth = this.container.parentElement.offsetWidth;
86+
this.totalWidth = this.calculateTotalWidth();
87+
this.fillContainer();
88+
this.startMarquee();
89+
});
90+
}
91+
92+
stopMarquee() {
93+
clearInterval(this.marqueeInterval);
94+
}
95+
}
96+
97+
const InitializeMarquee = () => {
98+
try {
99+
const marqueeContainers = document.querySelectorAll('[wt-marquee-element="container"]');
100+
if (!marqueeContainers || marqueeContainers.length === 0) throw new Error("No marquee containers found.");
101+
102+
marqueeContainers.forEach(container => {
103+
new Marquee(container);
104+
});
105+
} catch (err) {
106+
console.error(`Error in InitializeMarquee: ${err.message}`);
107+
}
108+
};
109+
110+
if (/complete|interactive|loaded/.test(document.readyState)) {
111+
InitializeMarquee();
112+
} else {
113+
window.addEventListener('DOMContentLoaded', InitializeMarquee);
114+
}

0 commit comments

Comments
 (0)