import { gsap } from 'gsap'; /** * Class representing an image that has the repetitive hover effect */ export class ImageHover { // DOM elements DOM = { // main element (.image) el: null, // .image__element innerElems: null, } // Background image path bgImage; // Total inner image elments totalInnerElems; // Hover timeline hoverTimeline; /** * Constructor. * @param {Element} DOM_el - the .image element */ constructor(DOM_el) { this.DOM = {el: DOM_el}; // Get bg image url this.bgImage = /(?:\(['"]?)(.*?)(?:['"]?\))/.exec(this.DOM.el.style.backgroundImage)[1] // Remove bg image gsap.set(this.DOM.el, {backgroundImage: 'none'}); // Add the .image__element inner elements (data-repetition-elems times) // First inner element will have a wrapper with overflow hidden so it's image child can scale up or down this.totalInnerElems = +this.DOM.el.dataset.repetitionElems || 4; // Minimum of two inner elments this.totalInnerElems = this.totalInnerElems <= 1 ? 2 : this.totalInnerElems; let innerHTML = ''; for (let i = 0, len = this.totalInnerElems || 1; i <= len - 1; ++i) { innerHTML += i === 0 ? `
` : `
` } // Append this.DOM.el.innerHTML = innerHTML; // Get inner .image__element this.DOM.innerElems = this.DOM.el.querySelectorAll('.image__element'); // transform origin gsap.set([this.DOM.el, this.DOM.innerElems[0]], {transformOrigin: this.DOM.el.dataset.repetitionOrigin || '50% 50%'}); // Hover timeline this.createHoverTimeline(); this.initEvents(); } /** * Create the gsap timeline for the hover in/out animation */ createHoverTimeline() { const property = this.DOM.el.dataset.repetitionAnimate || 'scale'; let animationProperties = { duration: this.DOM.el.dataset.repetitionDuration || 0.8, ease: this.DOM.el.dataset.repetitionEase || 'power2.inOut', stagger: this.DOM.el.dataset.repetitionStagger || -0.1 }, firstInnerElementProperties = {}; animationProperties[property] = i => +!i; // initial scale of first inner element firstInnerElementProperties[property] = this.DOM.el.dataset.repetitionInitialScale || 2; this.hoverTimeline = gsap.timeline({paused: true}) .set(this.DOM.innerElems[0], firstInnerElementProperties) .to([this.DOM.innerElems], animationProperties, 0) } /** * Initializes the events on the image elemment */ initEvents() { this.onMouseEnterFn = () => this.mouseEnter(); this.onMouseLeaveFn = () => this.mouseLeave(); this.DOM.el.addEventListener('mouseenter', this.onMouseEnterFn); this.DOM.el.addEventListener('mouseleave', this.onMouseLeaveFn); } /** * mouse enter */ mouseEnter() { this.hoverTimeline.play(); } /** * mouse leave */ mouseLeave() { this.hoverTimeline.reverse(); } }