UNPKG

minsky-kit

Version:
274 lines (223 loc) 7.16 kB
// imports import Component from 'minsky-kit/js/components/Component'; import Ticker from 'minsky-kit/js/managers/Ticker'; import MarqueeItem from './MarqueeItem'; // class definition export default class Marquee extends Component { // constructor constructor (args, objectName = 'Marquee') { args.debug = args.debug || false; // call super constructor super(args, objectName); this._useParent = args.useParent || false; this._speed = args.speed || 1.25; this._timing = args.timing || 1000 / 60; this._drawTiming = args.drawTiming || 1000 / 30; this._autoStart = (typeof args.autoStart === 'boolean') ? args.autoStart : true; this._running = true; this._paused = false; this._currentPageWidth = window.innerWidth; this._pauseOnHover = null; this._items = []; // prepare if (!this._useParent) { this.prepareNormal(); } else { this.prepareUsingParent(); } // generate items this.generateItems(); // launch ticker this._ticker = new Ticker({ timeout: 1000 / 60, isInterval: true, }); this._drawTicker = new Ticker({ timeout: this._drawTiming, isInterval: true, }); this._ticker.on('interval', this.blm.add('onTick', onTick)); this._drawTicker.on('interval', this.blm.add('onDrawTick', onDrawTick)); // add resize listener window.addEventListener( 'resize', this.blm.add('marquee.onWindowResize', onWindowResize), ); window.addEventListener( 'scroll', this.blm.add('marquee.onWindowScroll', onWindowScroll), ); // show marquee when ready this.$el.setAttribute('style', 'opacity: 1;'); // autostart if (this._autoStart) this.start(); // hover listener this.pauseOnHover = args.pauseOnHover; } tick (factor = 1, force = false) { if (this._running) { if (this._resized) { this._resized = false; this.regenerate(); } if (!this._paused || force) { for (let i = 0; i < this._items.length; i++) { this._items[i].tick(factor); } this.dispatch('tick'); } } } draw () { this._items.forEach((item) => item.draw()); } start () { this.running = true; } stop () { this.running = false; } generateItems () { let contentWidth = 0; // get width of content by adding it to the page first this.$el.appendChild(this._$content); contentWidth = this._$content.offsetWidth || 1; this._$content.parentNode.removeChild(this._$content); if (contentWidth > 0) { // calculated nr of items neded for screen width const nrItems = Math.ceil(this.$el.clientWidth / contentWidth) + 1; // generate this._items.length = 0; for (let i = 0; i < nrItems; i++) { this._items.push(new MarqueeItem({ $el: this._$content.cloneNode(true), parent: this, width: contentWidth, speed: this._speed, offset: this.offset, })); } } else { this.log('warn', 'Marquee Item width was 0, generation ignored as number of items would be infinite.'); } } prepareNormal () { // create content base (will be used to clone) this._$content = document.createElement('span'); this._$content.classList.add('marquee-item'); this._$content.innerHTML = this.$el.innerHTML; // clear el this.$el.innerHTML = ''; } prepareUsingParent () { // move el to content and set el as parent this._$content = this.$el; this.$el = this.$el.parentNode; // clear el this.$el.innerHTML = ''; } regenerate () { this.destroy(true); this.generateItems(); } update () { } // destroy destroy (itemsOnly) { for (let i = 0; i < this._items.length; i++) { this._items[i].destroy(); } if (!itemsOnly) { // continue destroying window.removeEventListener('resize', this.blm.remove('marquee.onWindowResize', this.onWindowResize)); window.removeEventListener('scroll', this.blm.remove('marquee.onWindowScroll', this.onWindowScroll)); this._ticker.destroy(); } } refresh () { this._resize = true; } // getters & setters get running () { return this._ticker.running; } set running (value) { if (this.running !== value) { if (value) { this._ticker.start(true); this._drawTicker.start(true); } else { this._ticker.stop(true); this._drawTicker.stop(true); } } } get pauseOnHover () { return this._pauseOnHover; } set pauseOnHover (value) { if (value !== this.pauseOnHover) { if (value) { this.$el.addEventListener('mouseenter', this.blm.addOnce('onMouseEnter', onMouseEnter)); this.$el.addEventListener('mouseleave', this.blm.addOnce('onMouseLeave', onMouseLeave)); } else { this._paused = false; this.$el.removeEventListener('mouseenter', this.blm.remove('onMouseEnter', onMouseEnter)); this.$el.removeEventListener('mouseleave', this.blm.remove('onMouseLeave', onMouseLeave)); } this._pauseOnHover = value; } } get paused () { return this._paused; } set paused (value) { if (this.paused !== value) { if (value) { if (this.running) { this._ticker.stop(); } } else { if (!this.running) { this._ticker.start(true); } } this._paused = value; } } get items () { return this._items; } get speed () { return this._speed; } set speed (value) { if (this.speed !== value) { this._speed = value; } } } function onTick () { this.tick(1); } function onDrawTick () { this.draw(); } function onWindowResize () { if (this._currentPageWidth !== window.innerWidth) { this._resized = true; this._currentPageWidth = window.innerWidth; } } function onWindowScroll () { if (!this._running) this.tick(1); } function onMouseEnter () { if (this._running && !this._paused) { this._paused = true; } } function onMouseLeave () { if (this._running && this._paused) { this._paused = false; } }