/** * Class representing a Trail element, * an element that has [trailElems] children/clones (of type image or text) * and that we can use to stagger it's translation so it looks like a trail or dragging effect */ class Trail { // DOM elements DOM = { // Main element (.trail) el: null, // Trail child elements (.trail__img or .trail__text) trailElems: null, }; // option defaults defaults = { // 3d perspective: false, // Total number of inner image elements totalTrailElements: 4, }; /** * Constructor. * @param {Element} DOM_el - the .trail element */ constructor(DOM_el, options) { this.DOM.el = DOM_el; this.options = Object.assign(this.defaults, options); // 3d if ( this.options.perspective ) { this.DOM.el.style.perspective = `${this.options.perspective}px` } } } /** * Class representing an image trail element */ export class TrailImage extends Trail { // the image path bgImage; /** * Constructor. * @param {Element} DOM_el - the .trail element */ constructor(DOM_el, options) { super(DOM_el, options); // Get the main element's background image url this.bgImage = /(?:\(['"]?)(.*?)(?:['"]?\))/.exec(this.DOM.el.style.backgroundImage)[1]; // Create the HTML markup for the trail elements this.layout(); } /** * Creates the HTML markup for the trail elements */ layout() { // Remove the background image from the main element this.DOM.el.style.backgroundImage = 'none'; let innerHTML = ''; for (let i = 0; i <= this.options.totalTrailElements - 1; ++i) { const opacityVal = i === this.options.totalTrailElements - 1 ? 1 : 0.8;//1/this.options.totalTrailElements * i + 1/this.options.totalTrailElements innerHTML += ``; } // Append to the main element this.DOM.el.innerHTML = innerHTML; // Get inner .trail__img elements this.DOM.trailElems = this.DOM.el.querySelectorAll('.trail__img'); this.DOM.el.classList.add('trail'); } reset() { this.DOM.el.classList.remove('trail'); this.DOM.el.style.backgroundImage = `url(${this.bgImage})`; this.DOM.el.innerHTML = ''; if ( this.options.perspective ) { this.DOM.el.style.perspective = 'none'; } } } /** * Class representing a text trail element */ export class TrailText extends Trail { /** * Constructor. * @param {Element} DOM_el - the .trail element */ constructor(DOM_el, options) { super(DOM_el, options); // Create the HTML markup for the trail elements this.layout(); } /** * Creates the HTML markup for the trail elements */ layout() { // Get the main element's innerHTML this.content = this.DOM.el.innerHTML; let innerHTML = ''; for (let i = 0; i <= this.options.totalTrailElements - 1; ++i) { const opacityVal = i === this.options.totalTrailElements - 1 ? 1 : 1/this.options.totalTrailElements * i + 1/this.options.totalTrailElements innerHTML += `${this.content}`; } // Append to the main element this.DOM.el.innerHTML = innerHTML; // Get inner .trail__text elements this.DOM.trailElems = this.DOM.el.querySelectorAll('.trail__text'); this.DOM.el.classList.add('trail'); } reset() { this.DOM.el.classList.remove('trail'); this.DOM.el.innerHTML = this.content; if ( this.options.perspective ) { this.DOM.el.style.perspective = 'none'; } } }