Skip to content

Instantly share code, notes, and snippets.

@reinvanoyen
Created February 6, 2020 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reinvanoyen/42e8591b7dc855f0e7bd399628d5f04e to your computer and use it in GitHub Desktop.
Save reinvanoyen/42e8591b7dc855f0e7bd399628d5f04e to your computer and use it in GitHub Desktop.
Vanilla marquee
"use strict";
export default class Marquee {
constructor(el, speed) {
this.el = el;
this.scrollEl = this.el.querySelector('.marquee__scroll');
this.itemsEl = this.el.querySelector('.marquee__items');
this.speed = speed;
this.now = null;
this.last = null;
this.delta = null;
this.maxTranslateX = 0;
this.translateX = 0;
this.marqueeWidth = 0;
this.marqueeHeight = 0;
this.cloneAmount = 1;
this.cloneAmountPrev = 1;
this.isPlaying = false;
this.init();
}
init() {
this.play();
this.el.addEventListener('mouseover', this.pause.bind(this));
this.el.addEventListener('mouseout', this.play.bind(this));
}
calculate() {
this.marqueeWidth = this.el.offsetWidth;
this.marqueeHeight = ( ( Math.abs(this.scrollEl.offsetHeight - this.marqueeHeight) > 1 ) ? this.scrollEl.offsetHeight : this.marqueeHeight );
this.maxTranslateX = this.itemsEl.offsetWidth;
this.el.style.height = this.marqueeHeight+'px';
if (this.maxTranslateX && this.itemsEl.children.length) {
this.cloneAmount = Math.max(1, Math.ceil((this.marqueeWidth * 2)/this.maxTranslateX));
if (this.cloneAmount > this.cloneAmountPrev) {
let childrenAmount = this.itemsEl.children.length;
let multiplyDiff = this.cloneAmount - this.cloneAmountPrev;
for (let i = 0; i < multiplyDiff; i++) {
for (let j = 0; j < childrenAmount; j++) {
let clonedChild = this.itemsEl.children[j].cloneNode(true);
this.scrollEl.appendChild(clonedChild);
}
}
this.cloneAmountPrev = this.cloneAmount;
}
}
}
timestamp() {
return window.performance && window.performance.now ? window.performance.now() : new Date().getTime();
}
play() {
if (! this.isPlaying) {
this.last = this.timestamp();
this.isPlaying = true;
this.animateScroll();
}
}
pause() {
this.isPlaying = false;
}
animateScroll() {
if (this.isPlaying) {
this.calculate();
this.now = this.timestamp();
this.delta = (this.now - this.last) / 1000;
this.translateX = this.translateX + (this.delta * this.speed);
if (this.translateX >= this.maxTranslateX) {
this.translateX = 0;
}
this.scrollEl.style.transform = 'translateX(-'+this.translateX+'px)';
requestAnimationFrame(() => this.animateScroll());
this.last = this.timestamp();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment