diff --git a/dist/esm/constants.d.ts b/dist/esm/constants.d.ts index 9a6e8e5..0b992ee 100644 --- a/dist/esm/constants.d.ts +++ b/dist/esm/constants.d.ts @@ -3,3 +3,4 @@ export declare const PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE = "pushinBreakpoints"; export declare const PUSH_IN_SPEED_DATA_ATTRIBUTE = "pushinSpeed"; export declare const PUSH_IN_TO_DATA_ATTRIBUTE = "pushinTo"; export declare const PUSH_IN_FROM_DATA_ATTRIBUTE = "pushinFrom"; +export declare const PUSH_IN_DEFAULT_BREAKPOINTS: number[]; diff --git a/dist/esm/pushInLayer.d.ts b/dist/esm/pushInLayer.d.ts new file mode 100644 index 0000000..1bc6104 --- /dev/null +++ b/dist/esm/pushInLayer.d.ts @@ -0,0 +1,68 @@ +import { PushInScene } from './pushInScene'; +import { LayerOptions } from './types'; +export declare class PushInLayer { + private element; + private index; + private scene; + private options; + private originalScale; + private ref; + private params; + constructor(element: HTMLElement, index: number, scene: PushInScene, options: LayerOptions | null); + /** + * Get all inpoints for the layer. + */ + private getInpoints; + /** + * Get all outpoints for the layer. + */ + private getOutpoints; + /** + * Get the push-in speed for the layer. + */ + private getSpeed; + /** + * Set the z-index of each layer so they overlap correctly. + */ + setZIndex(total: number): void; + /** + * Reset all the layer parameters. + * + * This is used if the window is resized + * and things need to be recalculated. + */ + resetLayerParams(): void; + /** + * Get the initial scale of the element at time of DOM load. + */ + private getElementScaleX; + /** + * Whether or not a layer should currently be zooming. + */ + private isActive; + /** + * Get the current inpoint for a layer, + * depending on window breakpoint. + */ + private getInpoint; + /** + * Get the current outpoint for a layer, + * depending on window breakpoint. + */ + private getOutpoint; + /** + * Get the scaleX value for the layer. + */ + private getScaleValue; + /** + * Set element scale. + */ + private setScale; + /** + * Set CSS styles to control the effect on each layer. + * + * This will control the scale and opacity of the layer + * as the user scrolls. + */ + setLayerStyle(): void; +} diff --git a/dist/esm/pushInScene.d.ts b/dist/esm/pushInScene.d.ts new file mode 100644 index 0000000..018b850 --- /dev/null +++ b/dist/esm/pushInScene.d.ts @@ -0,0 +1,27 @@ +import { PushInLayer } from './pushInLayer'; +import { PushIn } from './pushin'; +import { SceneOptions } from './types'; +export declare class PushInScene { + pushin: PushIn; + private container; + layers: PushInLayer[]; + speedDelta: number; + transitionLength: number; + layerDepth: number; + options: SceneOptions; + constructor(pushin: PushIn); + /** + * Set breakpoints for responsive design settings. + */ + private setBreakpoints; + /** + * Find all layers on the page and store them with their parameters + */ + private getLayers; + /** + * Get the array index of the current window breakpoint. + */ + getBreakpointIndex(breakpoints: number[]): number; + getTop(): number; + getInpoints(): number[]; +} diff --git a/dist/esm/pushin.d.ts b/dist/esm/pushin.d.ts index 83d897d..9ffea91 100644 --- a/dist/esm/pushin.d.ts +++ b/dist/esm/pushin.d.ts @@ -1,4 +1,4 @@ -import { PushInOptions } from './types'; +import { PushInOptions, SceneOptions } from './types'; /** * PushIn object * @@ -6,22 +6,15 @@ import { PushInOptions } from './types'; * bind events to begin interacting with dom. */ export declare class PushIn { - private container; + container: HTMLElement; private scene; private pushinDebug?; - private layerOptions; - private sceneOptions; - private scrollY; - private scrollEnd; - private touchStart; - private pageHeight; + sceneOptions: SceneOptions; + scrollY: number; private readonly layers; private readonly debug; - private speedDelta; - private transitionLength; - private layerDepth; private lastAnimationFrameId; - private readonly cleanupFns; + cleanupFns: VoidFunction[]; constructor(container: HTMLElement, options?: PushInOptions); /** * Initialize the object to start everything up. @@ -38,54 +31,10 @@ export declare class PushIn { * Otherwise default to 0. */ private getScrollY; - /** - * Get the "scene" element from the DOM. - * If it doesn't exist, make one. - */ - private addScene; - /** - * Set breakpoints for responsive design settings. - */ - private setBreakpoints; - /** - * Find all layers on the page and store them with their parameters - */ - private getLayers; - /** - * Get all inpoints for the layer. - */ - private getInpoints; - /** - * Get all outpoints for the layer. - */ - private getOutpoints; - /** - * Get the push-in speed for the layer. - */ - private getSpeed; - /** - * Get the array index of the current window breakpoint. - */ - private getBreakpointIndex; - /** - * Set the z-index of each layer so they overlap correctly. - */ - private setZIndex; /** * Bind event listeners to watch for page load and user interaction. */ bindEvents(): void; - /** - * Reset all the layer parameters. - * - * This is used if the window is resized - * and things need to be recalculated. - */ - private resetLayerParams; - /** - * Get the initial scale of the element at time of DOM load. - */ - private getElementScaleX; /** * Animation effect, mimicking a camera dolly on the webpage. */ @@ -94,35 +43,6 @@ export declare class PushIn { * Show or hide layers and set their scale, depending on if active. */ private toggleLayers; - /** - * Whether or not a layer should currently be zooming. - */ - private isActive; - /** - * Get the current inpoint for a layer, - * depending on window breakpoint. - */ - private getInpoint; - /** - * Get the current outpoint for a layer, - * depending on window breakpoint. - */ - private getOutpoint; - /** - * Get the scaleX value for the layer. - */ - private getScaleValue; - /** - * Set element scale. - */ - private setScale; - /** - * Set CSS styles to control the effect on each layer. - * - * This will control the scale and opacity of the layer - * as the user scrolls. - */ - private setLayerStyle; /** * Set the default container height based on a few factors: * 1. Number of layers present diff --git a/dist/esm/pushin.js b/dist/esm/pushin.js index c4e5d63..a966638 100644 --- a/dist/esm/pushin.js +++ b/dist/esm/pushin.js @@ -1,4 +1,4 @@ -/* Pushin.js - v4.0.3 +/* Pushin.js - v4.1.0 Author: Nathan Blair (https://natehub.net) License: MIT */ const DEFAULT_SPEED = 8; @@ -10,176 +10,66 @@ const PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE = 'pushinBreakpoints'; const PUSH_IN_SPEED_DATA_ATTRIBUTE = 'pushinSpeed'; const PUSH_IN_TO_DATA_ATTRIBUTE = 'pushinTo'; const PUSH_IN_FROM_DATA_ATTRIBUTE = 'pushinFrom'; +const PUSH_IN_DEFAULT_BREAKPOINTS = [768, 1440, 1920]; -/** - * PushIn object - * - * Once new object is created, it will initialize itself and - * bind events to begin interacting with dom. - */ -class PushIn { - constructor(container, options) { - var _a, _b, _c; - this.container = container; - this.scrollY = 0; - this.scrollEnd = null; - this.touchStart = null; - this.pageHeight = null; - this.layers = []; - this.speedDelta = 100; - this.transitionLength = 200; - this.layerDepth = 1000; - this.lastAnimationFrameId = -1; - this.cleanupFns = []; - this.debug = (_a = options === null || options === void 0 ? void 0 : options.debug) !== null && _a !== void 0 ? _a : false; - this.layerOptions = (_b = options === null || options === void 0 ? void 0 : options.layers) !== null && _b !== void 0 ? _b : []; - this.sceneOptions = (_c = options === null || options === void 0 ? void 0 : options.scene) !== null && _c !== void 0 ? _c : { breakpoints: [], inpoints: [] }; - } - /** - * Initialize the object to start everything up. - */ - start() { - if (this.container) { - this.scrollY = this.getScrollY(); - if (this.debug) { - this.showDebugger(); - } - this.addScene(); - this.setBreakpoints(); - this.getLayers(); - this.setScrollLength(); - if (typeof window !== 'undefined') { - this.bindEvents(); - } - // Set layer initial state - this.toggleLayers(); - } - else { - // eslint-disable-next-line no-console - console.error('No container element provided to pushIn.js. Effect will not be applied.'); - } - } - /** - * Does all necessary cleanups by removing event listeners. - */ - destroy() { - cancelAnimationFrame(this.lastAnimationFrameId); - while (this.cleanupFns.length) { - this.cleanupFns.pop()(); - } - } - /** - * If there is a window object, - * get the current scroll position. - * - * Otherwise default to 0. - */ - getScrollY() { - return typeof window !== 'undefined' ? window.scrollY : 0; - } - /** - * Get the "scene" element from the DOM. - * If it doesn't exist, make one. - */ - addScene() { - const scene = this.container.querySelector('.pushin-scene'); - if (scene) { - this.scene = scene; - } - else { - this.scene = document.createElement('div'); - this.scene.classList.add('pushin-scene'); - this.scene.innerHTML = this.container.innerHTML; - this.container.innerHTML = ''; - this.container.appendChild(this.scene); - // We register the cleanup function only for the manually created scene. - this.cleanupFns.push(() => this.container.removeChild(this.scene)); - } - } - /** - * Set breakpoints for responsive design settings. - */ - setBreakpoints() { - if (this.sceneOptions.breakpoints.length === 0) { - this.sceneOptions.breakpoints = [768, 1440, 1920]; - } - if (this.scene.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE]) { - this.sceneOptions.breakpoints = this.scene.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE].split(',').map(breakpoint => parseInt(breakpoint.trim(), 10)); - } - // Always include break point 0 for anything under first breakpoint - this.sceneOptions.breakpoints.unshift(0); - } - /** - * Find all layers on the page and store them with their parameters - */ - getLayers() { - const layers = Array.from(this.container.getElementsByClassName('pushin-layer')); - for (let index = 0; index < layers.length; index++) { - const element = layers[index]; - const inpoints = this.getInpoints(element, index); - const outpoints = this.getOutpoints(element, inpoints[0], index); - const speed = this.getSpeed(element, index); - const layer = { - element, - index, - originalScale: this.getElementScaleX(element), - ref: { inpoints, outpoints, speed }, - params: { - inpoint: this.getInpoint(inpoints), - outpoint: this.getOutpoint(outpoints), - speed, - }, - }; - this.layers.push(layer); - this.setZIndex(layer, layers.length); - } +class PushInLayer { + constructor(element, index, scene, options) { + this.element = element; + this.index = index; + this.scene = scene; + this.options = options; + const inpoints = this.getInpoints(this.element, this.index); + const outpoints = this.getOutpoints(this.element, inpoints[0]); + const speed = this.getSpeed(this.element); + this.originalScale = this.getElementScaleX(element); + this.ref = { inpoints, outpoints, speed }; + this.params = { + inpoint: this.getInpoint(inpoints), + outpoint: this.getOutpoint(outpoints), + speed, + }; } /** * Get all inpoints for the layer. */ getInpoints(element, index) { - var _a, _b; - const { top } = this.scene.getBoundingClientRect(); - let inpoints = [top]; + var _a; + let inpoints = [this.scene.getTop()]; if (element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { inpoints = element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE].split(',').map(inpoint => parseInt(inpoint.trim(), 10)); } - else if ((_a = this.layerOptions[index]) === null || _a === void 0 ? void 0 : _a.inpoints) { - inpoints = this.layerOptions[index].inpoints; + else if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.inpoints) { + inpoints = this.options.inpoints; } - else if (index === 0 && this.scene.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { - // Custom inpoint - inpoints = this.scene.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE].split(',').map(inpoint => parseInt(inpoint.trim(), 10)); - } - else if (index === 0 && ((_b = this.sceneOptions) === null || _b === void 0 ? void 0 : _b.inpoints.length) > 0) { - inpoints = this.sceneOptions.inpoints; + else if (index === 0) { + inpoints = this.scene.getInpoints(); } else if (index > 0) { // Set default for middle layers if none provided - const { outpoint } = this.layers[index - 1].params; - inpoints = [outpoint - this.speedDelta]; + const { outpoint } = this.scene.layers[index - 1].params; + inpoints = [outpoint - this.scene.speedDelta]; } return inpoints; } /** * Get all outpoints for the layer. */ - getOutpoints(element, inpoint, index) { + getOutpoints(element, inpoint) { var _a; - let outpoints = [inpoint + this.layerDepth]; + let outpoints = [inpoint + this.scene.layerDepth]; if (element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]) { const values = element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE].split(','); outpoints = values.map(value => parseInt(value.trim(), 10)); } - else if ((_a = this.layerOptions[index]) === null || _a === void 0 ? void 0 : _a.outpoints) { - outpoints = this.layerOptions[index].outpoints; + else if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.outpoints) { + outpoints = this.options.outpoints; } return outpoints; } /** * Get the push-in speed for the layer. */ - getSpeed(element, index) { + getSpeed(element) { var _a; let speed = null; if (element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]) { @@ -188,60 +78,16 @@ class PushIn { speed = DEFAULT_SPEED; } } - else if (typeof index === 'number' && ((_a = this.layerOptions[index]) === null || _a === void 0 ? void 0 : _a.speed)) { - speed = this.layerOptions[index].speed; + else if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.speed) { + speed = this.options.speed; } return speed || DEFAULT_SPEED; } - /** - * Get the array index of the current window breakpoint. - */ - getBreakpointIndex() { - const windowWidth = typeof window !== 'undefined' ? window.innerWidth : 0; - const searchIndex = this.sceneOptions.breakpoints - .reverse() - .findIndex(bp => bp <= windowWidth); - return searchIndex === -1 - ? 0 - : this.sceneOptions.breakpoints.length - 1 - searchIndex; - } /** * Set the z-index of each layer so they overlap correctly. */ - setZIndex(layer, total) { - layer.element.style.zIndex = (total - layer.index).toString(); - } - /** - * Bind event listeners to watch for page load and user interaction. - */ - bindEvents() { - const onScroll = () => { - this.scrollY = this.getScrollY(); - this.dolly(); - }; - window.addEventListener('scroll', onScroll); - this.cleanupFns.push(() => window.removeEventListener('scroll', onScroll)); - let resizeTimeout; - const onResize = () => { - clearTimeout(resizeTimeout); - resizeTimeout = window.setTimeout(() => { - this.resetLayerParams(); - this.setScrollLength(); - this.toggleLayers(); - }, 300); - }; - window.addEventListener('resize', onResize); - this.cleanupFns.push(() => window.removeEventListener('resize', onResize)); - if (this.pushinDebug) { - window.addEventListener('scroll', () => { - var _a; - const scrollY = typeof window !== 'undefined' ? window.scrollY : 0; - const content = (_a = this.pushinDebug) === null || _a === void 0 ? void 0 : _a.querySelector('.pushin-debug__content'); - if (content) { - content.textContent = `Scroll position: ${Math.round(scrollY)}px`; - } - }); - } + setZIndex(total) { + this.element.style.zIndex = (total - this.index).toString(); } /** * Reset all the layer parameters. @@ -250,13 +96,11 @@ class PushIn { * and things need to be recalculated. */ resetLayerParams() { - this.layers.forEach(layer => { - layer.params = { - inpoint: this.getInpoint(layer.ref.inpoints), - outpoint: this.getOutpoint(layer.ref.outpoints), - speed: layer.ref.speed, - }; - }); + this.params = { + inpoint: this.getInpoint(this.ref.inpoints), + outpoint: this.getOutpoint(this.ref.outpoints), + speed: this.ref.speed, + }; } /** * Get the initial scale of the element at time of DOM load. @@ -275,48 +119,36 @@ class PushIn { } return scaleX; } - /** - * Animation effect, mimicking a camera dolly on the webpage. - */ - dolly() { - cancelAnimationFrame(this.lastAnimationFrameId); - this.lastAnimationFrameId = requestAnimationFrame(() => { - this.toggleLayers(); - }); - } - /** - * Show or hide layers and set their scale, depending on if active. - */ - toggleLayers() { - this.layers.forEach(layer => this.setLayerStyle(layer)); - } /** * Whether or not a layer should currently be zooming. */ - isActive(layer) { - const { inpoint } = layer.params; - const { outpoint } = layer.params; - return this.scrollY >= inpoint && this.scrollY <= outpoint; + isActive() { + const { inpoint } = this.params; + const { outpoint } = this.params; + return (this.scene.pushin.scrollY >= inpoint && + this.scene.pushin.scrollY <= outpoint); } /** * Get the current inpoint for a layer, * depending on window breakpoint. */ getInpoint(inpoints) { - return inpoints[this.getBreakpointIndex()] || inpoints[0]; + const { breakpoints } = this.scene.options; + return inpoints[this.scene.getBreakpointIndex(breakpoints)] || inpoints[0]; } /** * Get the current outpoint for a layer, * depending on window breakpoint. */ getOutpoint(outpoints) { - return outpoints[this.getBreakpointIndex()] || outpoints[0]; + const { breakpoints } = this.scene.options; + return (outpoints[this.scene.getBreakpointIndex(breakpoints)] || outpoints[0]); } /** * Get the scaleX value for the layer. */ getScaleValue(layer) { - const distance = this.scrollY - layer.params.inpoint; + const distance = this.scene.pushin.scrollY - layer.params.inpoint; const speed = Math.min(layer.params.speed, 100) / 100; const delta = (distance * speed) / 100; return Math.max(layer.originalScale + delta, 0); @@ -338,35 +170,225 @@ class PushIn { * This will control the scale and opacity of the layer * as the user scrolls. */ - setLayerStyle(layer) { + setLayerStyle() { let opacity = 0; - const isFirst = layer.index === 0; - const isLast = layer.index + 1 === this.layers.length; - const { inpoint } = layer.params; - const { outpoint } = layer.params; - if (isFirst && this.scrollY < inpoint) { + const isFirst = this.index === 0; + const isLast = this.index + 1 === this.scene.layers.length; + const { inpoint } = this.params; + const { outpoint } = this.params; + if (isFirst && this.scene.pushin.scrollY < inpoint) { opacity = 1; } - else if (isLast && this.scrollY > outpoint) { + else if (isLast && this.scene.pushin.scrollY > outpoint) { opacity = 1; } - else if (this.isActive(layer)) { - this.setScale(layer.element, this.getScaleValue(layer)); - let inpointDistance = Math.max(Math.min(this.scrollY - inpoint, this.transitionLength), 0) / - this.transitionLength; + else if (this.isActive()) { + this.setScale(this.element, this.getScaleValue(this)); + let inpointDistance = Math.max(Math.min(this.scene.pushin.scrollY - inpoint, this.scene.transitionLength), 0) / this.scene.transitionLength; // Set opacity to 1 if its the first layer and it is active (no fading in here) if (isFirst) { inpointDistance = 1; } - let outpointDistance = Math.max(Math.min(outpoint - this.scrollY, this.transitionLength), 0) / - this.transitionLength; + let outpointDistance = Math.max(Math.min(outpoint - this.scene.pushin.scrollY, this.scene.transitionLength), 0) / this.scene.transitionLength; // Set opacity to 1 if its the last layer and it is active (no fading out) if (isLast) { outpointDistance = 1; } opacity = Math.min(inpointDistance, outpointDistance); } - layer.element.style.opacity = opacity.toString(); + this.element.style.opacity = opacity.toString(); + } +} + +class PushInScene { + constructor(pushin) { + var _a, _b, _c; + this.pushin = pushin; + const container = this.pushin.container.querySelector('.pushin-scene'); + if (container) { + this.container = container; + } + else { + this.container = document.createElement('div'); + this.container.classList.add('pushin-scene'); + this.container.innerHTML = this.pushin.container.innerHTML; + this.pushin.container.innerHTML = ''; + this.pushin.container.appendChild(this.container); + this.pushin.cleanupFns.push(() => { + this.pushin.container.innerHTML = this.container.innerHTML; + }); + } + this.options = pushin.sceneOptions; + this.speedDelta = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.speedDelta) || 100; + this.layerDepth = ((_b = this.options) === null || _b === void 0 ? void 0 : _b.layerDepth) || 1000; + this.transitionLength = ((_c = this.options) === null || _c === void 0 ? void 0 : _c.transitionLength) || 200; + this.layers = []; + this.setBreakpoints(); + this.getLayers(); + } + /** + * Set breakpoints for responsive design settings. + */ + setBreakpoints() { + var _a; + if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.breakpoints.length) === 0) { + this.options.breakpoints = [...PUSH_IN_DEFAULT_BREAKPOINTS]; + } + if (this.container.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE]) { + this.options.breakpoints = this.container.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE].split(',').map(breakpoint => parseInt(breakpoint.trim(), 10)); + } + // Always include break point 0 for anything under first breakpoint + this.options.breakpoints.unshift(0); + } + /** + * Find all layers on the page and store them with their parameters + */ + getLayers() { + var _a; + const layers = Array.from(this.container.getElementsByClassName('pushin-layer')); + for (let index = 0; index < layers.length; index++) { + const element = layers[index]; + let options = {}; + if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.layers) && this.options.layers.length > index) { + options = this.options.layers[index]; + } + const layer = new PushInLayer(element, index, this, options); + this.layers.push(layer); + layer.setZIndex(layers.length); + } + } + /** + * Get the array index of the current window breakpoint. + */ + getBreakpointIndex(breakpoints) { + const searchIndex = breakpoints + .reverse() + .findIndex(bp => bp <= window.innerWidth); + return searchIndex === -1 ? 0 : breakpoints.length - 1 - searchIndex; + } + getTop() { + return this.container.getBoundingClientRect().top; + } + getInpoints() { + var _a, _b; + let inpoints = [this.getTop()]; + if (this.container.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { + const pushInFrom = (this.container.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]); + inpoints.push(parseInt(pushInFrom, 10)); + } + else if (((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.inpoints) === null || _b === void 0 ? void 0 : _b.length) > 0) { + inpoints = this.options.inpoints; + } + return inpoints; + } +} + +/** + * PushIn object + * + * Once new object is created, it will initialize itself and + * bind events to begin interacting with dom. + */ +class PushIn { + constructor(container, options) { + var _a; + this.container = container; + this.scrollY = 0; + this.layers = []; + this.lastAnimationFrameId = -1; + this.cleanupFns = []; + this.debug = (_a = options === null || options === void 0 ? void 0 : options.debug) !== null && _a !== void 0 ? _a : false; + this.sceneOptions = { breakpoints: [], inpoints: [] }; + if (options === null || options === void 0 ? void 0 : options.scene) { + Object.assign(this.sceneOptions, options.scene); + } + if (options === null || options === void 0 ? void 0 : options.layers) { + Object.assign(this.sceneOptions, options.layers); + } + } + /** + * Initialize the object to start everything up. + */ + start() { + this.scrollY = this.getScrollY(); + if (this.debug) { + this.showDebugger(); + } + if (this.container) { + this.scene = new PushInScene(this); + this.setScrollLength(); + if (typeof window !== 'undefined') { + this.bindEvents(); + } + // Set layer initial state + this.toggleLayers(); + } + else { + // eslint-disable-next-line no-console + console.error('No container element provided to pushIn.js. Effect will not be applied.'); + } + } + /** + * Does all necessary cleanups by removing event listeners. + */ + destroy() { + cancelAnimationFrame(this.lastAnimationFrameId); + while (this.cleanupFns.length) { + this.cleanupFns.pop()(); + } + } + /** + * If there is a window object, + * get the current scroll position. + * + * Otherwise default to 0. + */ + getScrollY() { + return typeof window !== 'undefined' ? window.scrollY : 0; + } + /** + * Bind event listeners to watch for page load and user interaction. + */ + bindEvents() { + const onScroll = () => { + var _a; + this.scrollY = this.getScrollY(); + this.dolly(); + if (this.pushinDebug) { + const content = (_a = this.pushinDebug) === null || _a === void 0 ? void 0 : _a.querySelector('.pushin-debug__content'); + if (content) { + content.textContent = `Scroll position: ${Math.round(this.scrollY)}px`; + } + } + }; + window.addEventListener('scroll', onScroll); + this.cleanupFns.push(() => window.removeEventListener('scroll', onScroll)); + let resizeTimeout; + const onResize = () => { + clearTimeout(resizeTimeout); + resizeTimeout = window.setTimeout(() => { + this.scene.layers.forEach(layer => layer.resetLayerParams()); + this.setScrollLength(); + this.toggleLayers(); + }, 300); + }; + window.addEventListener('resize', onResize); + this.cleanupFns.push(() => window.removeEventListener('resize', onResize)); + } + /** + * Animation effect, mimicking a camera dolly on the webpage. + */ + dolly() { + cancelAnimationFrame(this.lastAnimationFrameId); + this.lastAnimationFrameId = requestAnimationFrame(() => { + this.toggleLayers(); + }); + } + /** + * Show or hide layers and set their scale, depending on if active. + */ + toggleLayers() { + this.scene.layers.forEach(layer => layer.setLayerStyle()); } /** * Set the default container height based on a few factors: @@ -379,8 +401,9 @@ class PushIn { */ setScrollLength() { const containerHeight = getComputedStyle(this.container).height.replace('px', ''); - const transitions = (this.layers.length - 1) * this.speedDelta; - const scrollLength = this.layers.length * (this.layerDepth + this.transitionLength); + const transitions = (this.scene.layers.length - 1) * this.scene.speedDelta; + const scrollLength = this.scene.layers.length * + (this.scene.layerDepth + this.scene.transitionLength); this.container.style.height = `${Math.max(parseFloat(containerHeight), scrollLength - transitions)}px`; } /** @@ -393,10 +416,9 @@ class PushIn { const scrollTitle = document.createElement('p'); scrollTitle.innerText = 'Pushin.js Debugger'; scrollTitle.classList.add('pushin-debug__title'); - const scrollY = typeof window !== 'undefined' ? window.scrollY : 0; const debuggerContent = document.createElement('div'); debuggerContent.classList.add('pushin-debug__content'); - debuggerContent.innerText = `Scroll position: ${scrollY}px`; + debuggerContent.innerText = `Scroll position: ${this.scrollY}px`; this.pushinDebug.appendChild(scrollTitle); this.pushinDebug.appendChild(debuggerContent); document.body.appendChild(this.pushinDebug); diff --git a/dist/esm/pushin.js.map b/dist/esm/pushin.js.map index 0ed146d..1a11619 100644 --- a/dist/esm/pushin.js.map +++ b/dist/esm/pushin.js.map @@ -1 +1 @@ -{"version":3,"file":"pushin.js","sources":["../../src/constants.ts","../../src/pushin.ts","../../src/helpers.ts"],"sourcesContent":[null,null,null],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pushin.js","sources":["../../src/constants.ts","../../src/pushInLayer.ts","../../src/pushInScene.ts","../../src/pushin.ts","../../src/helpers.ts"],"sourcesContent":[null,null,null,null,null],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/esm/types.d.ts b/dist/esm/types.d.ts index e80f6a6..0613897 100644 --- a/dist/esm/types.d.ts +++ b/dist/esm/types.d.ts @@ -4,8 +4,12 @@ export interface LayerOptions { speed: number; } export interface SceneOptions { + speedDelta?: number; + layerDepth?: number; + transitionLength?: number; breakpoints: number[]; inpoints: number[]; + layers?: LayerOptions[]; } export interface PushInOptions { debug?: boolean; @@ -16,14 +20,14 @@ export interface PushInLayer { element: HTMLElement; index: number; originalScale: number; - ref: { - inpoints: number[]; - outpoints: number[]; - speed: number; - }; - params: { - inpoint: number; - outpoint: number; - speed: number; - }; +} +export interface LayerRef { + inpoints: number[]; + outpoints: number[]; + speed: number; +} +export interface LayerParams { + inpoint: number; + outpoint: number; + speed: number; } diff --git a/dist/umd/pushin.js b/dist/umd/pushin.js index d880b82..0612263 100644 --- a/dist/umd/pushin.js +++ b/dist/umd/pushin.js @@ -1,4 +1,4 @@ -/* Pushin.js - v4.0.3 +/* Pushin.js - v4.1.0 Author: Nathan Blair (https://natehub.net) License: MIT */ (function (global, factory) { @@ -16,176 +16,66 @@ License: MIT */ const PUSH_IN_SPEED_DATA_ATTRIBUTE = 'pushinSpeed'; const PUSH_IN_TO_DATA_ATTRIBUTE = 'pushinTo'; const PUSH_IN_FROM_DATA_ATTRIBUTE = 'pushinFrom'; + const PUSH_IN_DEFAULT_BREAKPOINTS = [768, 1440, 1920]; - /** - * PushIn object - * - * Once new object is created, it will initialize itself and - * bind events to begin interacting with dom. - */ - class PushIn { - constructor(container, options) { - var _a, _b, _c; - this.container = container; - this.scrollY = 0; - this.scrollEnd = null; - this.touchStart = null; - this.pageHeight = null; - this.layers = []; - this.speedDelta = 100; - this.transitionLength = 200; - this.layerDepth = 1000; - this.lastAnimationFrameId = -1; - this.cleanupFns = []; - this.debug = (_a = options === null || options === void 0 ? void 0 : options.debug) !== null && _a !== void 0 ? _a : false; - this.layerOptions = (_b = options === null || options === void 0 ? void 0 : options.layers) !== null && _b !== void 0 ? _b : []; - this.sceneOptions = (_c = options === null || options === void 0 ? void 0 : options.scene) !== null && _c !== void 0 ? _c : { breakpoints: [], inpoints: [] }; - } - /** - * Initialize the object to start everything up. - */ - start() { - if (this.container) { - this.scrollY = this.getScrollY(); - if (this.debug) { - this.showDebugger(); - } - this.addScene(); - this.setBreakpoints(); - this.getLayers(); - this.setScrollLength(); - if (typeof window !== 'undefined') { - this.bindEvents(); - } - // Set layer initial state - this.toggleLayers(); - } - else { - // eslint-disable-next-line no-console - console.error('No container element provided to pushIn.js. Effect will not be applied.'); - } - } - /** - * Does all necessary cleanups by removing event listeners. - */ - destroy() { - cancelAnimationFrame(this.lastAnimationFrameId); - while (this.cleanupFns.length) { - this.cleanupFns.pop()(); - } - } - /** - * If there is a window object, - * get the current scroll position. - * - * Otherwise default to 0. - */ - getScrollY() { - return typeof window !== 'undefined' ? window.scrollY : 0; - } - /** - * Get the "scene" element from the DOM. - * If it doesn't exist, make one. - */ - addScene() { - const scene = this.container.querySelector('.pushin-scene'); - if (scene) { - this.scene = scene; - } - else { - this.scene = document.createElement('div'); - this.scene.classList.add('pushin-scene'); - this.scene.innerHTML = this.container.innerHTML; - this.container.innerHTML = ''; - this.container.appendChild(this.scene); - // We register the cleanup function only for the manually created scene. - this.cleanupFns.push(() => this.container.removeChild(this.scene)); - } - } - /** - * Set breakpoints for responsive design settings. - */ - setBreakpoints() { - if (this.sceneOptions.breakpoints.length === 0) { - this.sceneOptions.breakpoints = [768, 1440, 1920]; - } - if (this.scene.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE]) { - this.sceneOptions.breakpoints = this.scene.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE].split(',').map(breakpoint => parseInt(breakpoint.trim(), 10)); - } - // Always include break point 0 for anything under first breakpoint - this.sceneOptions.breakpoints.unshift(0); - } - /** - * Find all layers on the page and store them with their parameters - */ - getLayers() { - const layers = Array.from(this.container.getElementsByClassName('pushin-layer')); - for (let index = 0; index < layers.length; index++) { - const element = layers[index]; - const inpoints = this.getInpoints(element, index); - const outpoints = this.getOutpoints(element, inpoints[0], index); - const speed = this.getSpeed(element, index); - const layer = { - element, - index, - originalScale: this.getElementScaleX(element), - ref: { inpoints, outpoints, speed }, - params: { - inpoint: this.getInpoint(inpoints), - outpoint: this.getOutpoint(outpoints), - speed, - }, - }; - this.layers.push(layer); - this.setZIndex(layer, layers.length); - } + class PushInLayer { + constructor(element, index, scene, options) { + this.element = element; + this.index = index; + this.scene = scene; + this.options = options; + const inpoints = this.getInpoints(this.element, this.index); + const outpoints = this.getOutpoints(this.element, inpoints[0]); + const speed = this.getSpeed(this.element); + this.originalScale = this.getElementScaleX(element); + this.ref = { inpoints, outpoints, speed }; + this.params = { + inpoint: this.getInpoint(inpoints), + outpoint: this.getOutpoint(outpoints), + speed, + }; } /** * Get all inpoints for the layer. */ getInpoints(element, index) { - var _a, _b; - const { top } = this.scene.getBoundingClientRect(); - let inpoints = [top]; + var _a; + let inpoints = [this.scene.getTop()]; if (element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { inpoints = element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE].split(',').map(inpoint => parseInt(inpoint.trim(), 10)); } - else if ((_a = this.layerOptions[index]) === null || _a === void 0 ? void 0 : _a.inpoints) { - inpoints = this.layerOptions[index].inpoints; + else if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.inpoints) { + inpoints = this.options.inpoints; } - else if (index === 0 && this.scene.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { - // Custom inpoint - inpoints = this.scene.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE].split(',').map(inpoint => parseInt(inpoint.trim(), 10)); - } - else if (index === 0 && ((_b = this.sceneOptions) === null || _b === void 0 ? void 0 : _b.inpoints.length) > 0) { - inpoints = this.sceneOptions.inpoints; + else if (index === 0) { + inpoints = this.scene.getInpoints(); } else if (index > 0) { // Set default for middle layers if none provided - const { outpoint } = this.layers[index - 1].params; - inpoints = [outpoint - this.speedDelta]; + const { outpoint } = this.scene.layers[index - 1].params; + inpoints = [outpoint - this.scene.speedDelta]; } return inpoints; } /** * Get all outpoints for the layer. */ - getOutpoints(element, inpoint, index) { + getOutpoints(element, inpoint) { var _a; - let outpoints = [inpoint + this.layerDepth]; + let outpoints = [inpoint + this.scene.layerDepth]; if (element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]) { const values = element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE].split(','); outpoints = values.map(value => parseInt(value.trim(), 10)); } - else if ((_a = this.layerOptions[index]) === null || _a === void 0 ? void 0 : _a.outpoints) { - outpoints = this.layerOptions[index].outpoints; + else if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.outpoints) { + outpoints = this.options.outpoints; } return outpoints; } /** * Get the push-in speed for the layer. */ - getSpeed(element, index) { + getSpeed(element) { var _a; let speed = null; if (element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]) { @@ -194,60 +84,16 @@ License: MIT */ speed = DEFAULT_SPEED; } } - else if (typeof index === 'number' && ((_a = this.layerOptions[index]) === null || _a === void 0 ? void 0 : _a.speed)) { - speed = this.layerOptions[index].speed; + else if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.speed) { + speed = this.options.speed; } return speed || DEFAULT_SPEED; } - /** - * Get the array index of the current window breakpoint. - */ - getBreakpointIndex() { - const windowWidth = typeof window !== 'undefined' ? window.innerWidth : 0; - const searchIndex = this.sceneOptions.breakpoints - .reverse() - .findIndex(bp => bp <= windowWidth); - return searchIndex === -1 - ? 0 - : this.sceneOptions.breakpoints.length - 1 - searchIndex; - } /** * Set the z-index of each layer so they overlap correctly. */ - setZIndex(layer, total) { - layer.element.style.zIndex = (total - layer.index).toString(); - } - /** - * Bind event listeners to watch for page load and user interaction. - */ - bindEvents() { - const onScroll = () => { - this.scrollY = this.getScrollY(); - this.dolly(); - }; - window.addEventListener('scroll', onScroll); - this.cleanupFns.push(() => window.removeEventListener('scroll', onScroll)); - let resizeTimeout; - const onResize = () => { - clearTimeout(resizeTimeout); - resizeTimeout = window.setTimeout(() => { - this.resetLayerParams(); - this.setScrollLength(); - this.toggleLayers(); - }, 300); - }; - window.addEventListener('resize', onResize); - this.cleanupFns.push(() => window.removeEventListener('resize', onResize)); - if (this.pushinDebug) { - window.addEventListener('scroll', () => { - var _a; - const scrollY = typeof window !== 'undefined' ? window.scrollY : 0; - const content = (_a = this.pushinDebug) === null || _a === void 0 ? void 0 : _a.querySelector('.pushin-debug__content'); - if (content) { - content.textContent = `Scroll position: ${Math.round(scrollY)}px`; - } - }); - } + setZIndex(total) { + this.element.style.zIndex = (total - this.index).toString(); } /** * Reset all the layer parameters. @@ -256,13 +102,11 @@ License: MIT */ * and things need to be recalculated. */ resetLayerParams() { - this.layers.forEach(layer => { - layer.params = { - inpoint: this.getInpoint(layer.ref.inpoints), - outpoint: this.getOutpoint(layer.ref.outpoints), - speed: layer.ref.speed, - }; - }); + this.params = { + inpoint: this.getInpoint(this.ref.inpoints), + outpoint: this.getOutpoint(this.ref.outpoints), + speed: this.ref.speed, + }; } /** * Get the initial scale of the element at time of DOM load. @@ -281,48 +125,36 @@ License: MIT */ } return scaleX; } - /** - * Animation effect, mimicking a camera dolly on the webpage. - */ - dolly() { - cancelAnimationFrame(this.lastAnimationFrameId); - this.lastAnimationFrameId = requestAnimationFrame(() => { - this.toggleLayers(); - }); - } - /** - * Show or hide layers and set their scale, depending on if active. - */ - toggleLayers() { - this.layers.forEach(layer => this.setLayerStyle(layer)); - } /** * Whether or not a layer should currently be zooming. */ - isActive(layer) { - const { inpoint } = layer.params; - const { outpoint } = layer.params; - return this.scrollY >= inpoint && this.scrollY <= outpoint; + isActive() { + const { inpoint } = this.params; + const { outpoint } = this.params; + return (this.scene.pushin.scrollY >= inpoint && + this.scene.pushin.scrollY <= outpoint); } /** * Get the current inpoint for a layer, * depending on window breakpoint. */ getInpoint(inpoints) { - return inpoints[this.getBreakpointIndex()] || inpoints[0]; + const { breakpoints } = this.scene.options; + return inpoints[this.scene.getBreakpointIndex(breakpoints)] || inpoints[0]; } /** * Get the current outpoint for a layer, * depending on window breakpoint. */ getOutpoint(outpoints) { - return outpoints[this.getBreakpointIndex()] || outpoints[0]; + const { breakpoints } = this.scene.options; + return (outpoints[this.scene.getBreakpointIndex(breakpoints)] || outpoints[0]); } /** * Get the scaleX value for the layer. */ getScaleValue(layer) { - const distance = this.scrollY - layer.params.inpoint; + const distance = this.scene.pushin.scrollY - layer.params.inpoint; const speed = Math.min(layer.params.speed, 100) / 100; const delta = (distance * speed) / 100; return Math.max(layer.originalScale + delta, 0); @@ -344,35 +176,225 @@ License: MIT */ * This will control the scale and opacity of the layer * as the user scrolls. */ - setLayerStyle(layer) { + setLayerStyle() { let opacity = 0; - const isFirst = layer.index === 0; - const isLast = layer.index + 1 === this.layers.length; - const { inpoint } = layer.params; - const { outpoint } = layer.params; - if (isFirst && this.scrollY < inpoint) { + const isFirst = this.index === 0; + const isLast = this.index + 1 === this.scene.layers.length; + const { inpoint } = this.params; + const { outpoint } = this.params; + if (isFirst && this.scene.pushin.scrollY < inpoint) { opacity = 1; } - else if (isLast && this.scrollY > outpoint) { + else if (isLast && this.scene.pushin.scrollY > outpoint) { opacity = 1; } - else if (this.isActive(layer)) { - this.setScale(layer.element, this.getScaleValue(layer)); - let inpointDistance = Math.max(Math.min(this.scrollY - inpoint, this.transitionLength), 0) / - this.transitionLength; + else if (this.isActive()) { + this.setScale(this.element, this.getScaleValue(this)); + let inpointDistance = Math.max(Math.min(this.scene.pushin.scrollY - inpoint, this.scene.transitionLength), 0) / this.scene.transitionLength; // Set opacity to 1 if its the first layer and it is active (no fading in here) if (isFirst) { inpointDistance = 1; } - let outpointDistance = Math.max(Math.min(outpoint - this.scrollY, this.transitionLength), 0) / - this.transitionLength; + let outpointDistance = Math.max(Math.min(outpoint - this.scene.pushin.scrollY, this.scene.transitionLength), 0) / this.scene.transitionLength; // Set opacity to 1 if its the last layer and it is active (no fading out) if (isLast) { outpointDistance = 1; } opacity = Math.min(inpointDistance, outpointDistance); } - layer.element.style.opacity = opacity.toString(); + this.element.style.opacity = opacity.toString(); + } + } + + class PushInScene { + constructor(pushin) { + var _a, _b, _c; + this.pushin = pushin; + const container = this.pushin.container.querySelector('.pushin-scene'); + if (container) { + this.container = container; + } + else { + this.container = document.createElement('div'); + this.container.classList.add('pushin-scene'); + this.container.innerHTML = this.pushin.container.innerHTML; + this.pushin.container.innerHTML = ''; + this.pushin.container.appendChild(this.container); + this.pushin.cleanupFns.push(() => { + this.pushin.container.innerHTML = this.container.innerHTML; + }); + } + this.options = pushin.sceneOptions; + this.speedDelta = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.speedDelta) || 100; + this.layerDepth = ((_b = this.options) === null || _b === void 0 ? void 0 : _b.layerDepth) || 1000; + this.transitionLength = ((_c = this.options) === null || _c === void 0 ? void 0 : _c.transitionLength) || 200; + this.layers = []; + this.setBreakpoints(); + this.getLayers(); + } + /** + * Set breakpoints for responsive design settings. + */ + setBreakpoints() { + var _a; + if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.breakpoints.length) === 0) { + this.options.breakpoints = [...PUSH_IN_DEFAULT_BREAKPOINTS]; + } + if (this.container.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE]) { + this.options.breakpoints = this.container.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE].split(',').map(breakpoint => parseInt(breakpoint.trim(), 10)); + } + // Always include break point 0 for anything under first breakpoint + this.options.breakpoints.unshift(0); + } + /** + * Find all layers on the page and store them with their parameters + */ + getLayers() { + var _a; + const layers = Array.from(this.container.getElementsByClassName('pushin-layer')); + for (let index = 0; index < layers.length; index++) { + const element = layers[index]; + let options = {}; + if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.layers) && this.options.layers.length > index) { + options = this.options.layers[index]; + } + const layer = new PushInLayer(element, index, this, options); + this.layers.push(layer); + layer.setZIndex(layers.length); + } + } + /** + * Get the array index of the current window breakpoint. + */ + getBreakpointIndex(breakpoints) { + const searchIndex = breakpoints + .reverse() + .findIndex(bp => bp <= window.innerWidth); + return searchIndex === -1 ? 0 : breakpoints.length - 1 - searchIndex; + } + getTop() { + return this.container.getBoundingClientRect().top; + } + getInpoints() { + var _a, _b; + let inpoints = [this.getTop()]; + if (this.container.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { + const pushInFrom = (this.container.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]); + inpoints.push(parseInt(pushInFrom, 10)); + } + else if (((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.inpoints) === null || _b === void 0 ? void 0 : _b.length) > 0) { + inpoints = this.options.inpoints; + } + return inpoints; + } + } + + /** + * PushIn object + * + * Once new object is created, it will initialize itself and + * bind events to begin interacting with dom. + */ + class PushIn { + constructor(container, options) { + var _a; + this.container = container; + this.scrollY = 0; + this.layers = []; + this.lastAnimationFrameId = -1; + this.cleanupFns = []; + this.debug = (_a = options === null || options === void 0 ? void 0 : options.debug) !== null && _a !== void 0 ? _a : false; + this.sceneOptions = { breakpoints: [], inpoints: [] }; + if (options === null || options === void 0 ? void 0 : options.scene) { + Object.assign(this.sceneOptions, options.scene); + } + if (options === null || options === void 0 ? void 0 : options.layers) { + Object.assign(this.sceneOptions, options.layers); + } + } + /** + * Initialize the object to start everything up. + */ + start() { + this.scrollY = this.getScrollY(); + if (this.debug) { + this.showDebugger(); + } + if (this.container) { + this.scene = new PushInScene(this); + this.setScrollLength(); + if (typeof window !== 'undefined') { + this.bindEvents(); + } + // Set layer initial state + this.toggleLayers(); + } + else { + // eslint-disable-next-line no-console + console.error('No container element provided to pushIn.js. Effect will not be applied.'); + } + } + /** + * Does all necessary cleanups by removing event listeners. + */ + destroy() { + cancelAnimationFrame(this.lastAnimationFrameId); + while (this.cleanupFns.length) { + this.cleanupFns.pop()(); + } + } + /** + * If there is a window object, + * get the current scroll position. + * + * Otherwise default to 0. + */ + getScrollY() { + return typeof window !== 'undefined' ? window.scrollY : 0; + } + /** + * Bind event listeners to watch for page load and user interaction. + */ + bindEvents() { + const onScroll = () => { + var _a; + this.scrollY = this.getScrollY(); + this.dolly(); + if (this.pushinDebug) { + const content = (_a = this.pushinDebug) === null || _a === void 0 ? void 0 : _a.querySelector('.pushin-debug__content'); + if (content) { + content.textContent = `Scroll position: ${Math.round(this.scrollY)}px`; + } + } + }; + window.addEventListener('scroll', onScroll); + this.cleanupFns.push(() => window.removeEventListener('scroll', onScroll)); + let resizeTimeout; + const onResize = () => { + clearTimeout(resizeTimeout); + resizeTimeout = window.setTimeout(() => { + this.scene.layers.forEach(layer => layer.resetLayerParams()); + this.setScrollLength(); + this.toggleLayers(); + }, 300); + }; + window.addEventListener('resize', onResize); + this.cleanupFns.push(() => window.removeEventListener('resize', onResize)); + } + /** + * Animation effect, mimicking a camera dolly on the webpage. + */ + dolly() { + cancelAnimationFrame(this.lastAnimationFrameId); + this.lastAnimationFrameId = requestAnimationFrame(() => { + this.toggleLayers(); + }); + } + /** + * Show or hide layers and set their scale, depending on if active. + */ + toggleLayers() { + this.scene.layers.forEach(layer => layer.setLayerStyle()); } /** * Set the default container height based on a few factors: @@ -385,8 +407,9 @@ License: MIT */ */ setScrollLength() { const containerHeight = getComputedStyle(this.container).height.replace('px', ''); - const transitions = (this.layers.length - 1) * this.speedDelta; - const scrollLength = this.layers.length * (this.layerDepth + this.transitionLength); + const transitions = (this.scene.layers.length - 1) * this.scene.speedDelta; + const scrollLength = this.scene.layers.length * + (this.scene.layerDepth + this.scene.transitionLength); this.container.style.height = `${Math.max(parseFloat(containerHeight), scrollLength - transitions)}px`; } /** @@ -399,10 +422,9 @@ License: MIT */ const scrollTitle = document.createElement('p'); scrollTitle.innerText = 'Pushin.js Debugger'; scrollTitle.classList.add('pushin-debug__title'); - const scrollY = typeof window !== 'undefined' ? window.scrollY : 0; const debuggerContent = document.createElement('div'); debuggerContent.classList.add('pushin-debug__content'); - debuggerContent.innerText = `Scroll position: ${scrollY}px`; + debuggerContent.innerText = `Scroll position: ${this.scrollY}px`; this.pushinDebug.appendChild(scrollTitle); this.pushinDebug.appendChild(debuggerContent); document.body.appendChild(this.pushinDebug); diff --git a/dist/umd/pushin.js.map b/dist/umd/pushin.js.map index 509eef2..e7a4689 100644 --- a/dist/umd/pushin.js.map +++ b/dist/umd/pushin.js.map @@ -1 +1 @@ -{"version":3,"file":"pushin.js","sources":["../../src/constants.ts","../../src/pushin.ts","../../src/helpers.ts"],"sourcesContent":["export const DEFAULT_SPEED = 8;\n\n// The data attribute which may be defined on the elemenet in the following way:\n// `
`.\nexport const PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE = 'pushinBreakpoints';\n\n// The data attribute which may be defined on the elemenet in the following way:\n// `
`.\nexport const PUSH_IN_SPEED_DATA_ATTRIBUTE = 'pushinSpeed';\n\nexport const PUSH_IN_TO_DATA_ATTRIBUTE = 'pushinTo';\nexport const PUSH_IN_FROM_DATA_ATTRIBUTE = 'pushinFrom';\n","import {\n DEFAULT_SPEED,\n PUSH_IN_TO_DATA_ATTRIBUTE,\n PUSH_IN_FROM_DATA_ATTRIBUTE,\n PUSH_IN_SPEED_DATA_ATTRIBUTE,\n PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE,\n} from './constants';\nimport {\n PushInLayer,\n PushInOptions,\n LayerOptions,\n SceneOptions,\n} from './types';\n\n/**\n * PushIn object\n *\n * Once new object is created, it will initialize itself and\n * bind events to begin interacting with dom.\n */\nexport class PushIn {\n private scene!: HTMLElement;\n private pushinDebug?: HTMLElement;\n private layerOptions: LayerOptions[];\n private sceneOptions: SceneOptions;\n\n private scrollY = 0;\n private scrollEnd: number | null = null;\n private touchStart: number | null = null;\n private pageHeight: number | null = null;\n\n private readonly layers: PushInLayer[] = [];\n private readonly debug: boolean;\n\n private speedDelta = 100;\n private transitionLength = 200;\n private layerDepth = 1000;\n\n private lastAnimationFrameId = -1;\n private readonly cleanupFns: VoidFunction[] = [];\n\n constructor(private container: HTMLElement, options?: PushInOptions) {\n this.debug = options?.debug ?? false;\n this.layerOptions = options?.layers ?? [];\n this.sceneOptions = options?.scene ?? { breakpoints: [], inpoints: [] };\n }\n\n /**\n * Initialize the object to start everything up.\n */\n start(): void {\n if (this.container) {\n this.scrollY = this.getScrollY();\n\n if (this.debug) {\n this.showDebugger();\n }\n\n this.addScene();\n this.setBreakpoints();\n this.getLayers();\n this.setScrollLength();\n\n if (typeof window !== 'undefined') {\n this.bindEvents();\n }\n\n // Set layer initial state\n this.toggleLayers();\n } else {\n // eslint-disable-next-line no-console\n console.error(\n 'No container element provided to pushIn.js. Effect will not be applied.'\n );\n }\n }\n\n /**\n * Does all necessary cleanups by removing event listeners.\n */\n destroy(): void {\n cancelAnimationFrame(this.lastAnimationFrameId);\n\n while (this.cleanupFns.length) {\n this.cleanupFns.pop()!();\n }\n }\n\n /**\n * If there is a window object,\n * get the current scroll position.\n *\n * Otherwise default to 0.\n */\n private getScrollY(): number {\n return typeof window !== 'undefined' ? window.scrollY : 0;\n }\n\n /**\n * Get the \"scene\" element from the DOM.\n * If it doesn't exist, make one.\n */\n private addScene(): void {\n const scene = this.container.querySelector('.pushin-scene');\n\n if (scene) {\n this.scene = scene;\n } else {\n this.scene = document.createElement('div');\n this.scene.classList.add('pushin-scene');\n\n this.scene.innerHTML = this.container.innerHTML;\n this.container.innerHTML = '';\n this.container.appendChild(this.scene);\n // We register the cleanup function only for the manually created scene.\n this.cleanupFns.push(() => this.container.removeChild(this.scene));\n }\n }\n\n /**\n * Set breakpoints for responsive design settings.\n */\n private setBreakpoints(): void {\n if (this.sceneOptions.breakpoints.length === 0) {\n this.sceneOptions.breakpoints = [768, 1440, 1920];\n }\n\n if (this.scene.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE]) {\n this.sceneOptions.breakpoints = this.scene.dataset[\n PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE\n ]!.split(',').map(breakpoint => parseInt(breakpoint.trim(), 10));\n }\n\n // Always include break point 0 for anything under first breakpoint\n this.sceneOptions.breakpoints.unshift(0);\n }\n\n /**\n * Find all layers on the page and store them with their parameters\n */\n private getLayers(): void {\n const layers = Array.from(\n this.container.getElementsByClassName('pushin-layer')\n );\n\n for (let index = 0; index < layers.length; index++) {\n const element = layers[index];\n const inpoints = this.getInpoints(element, index);\n const outpoints = this.getOutpoints(element, inpoints[0], index);\n const speed = this.getSpeed(element, index);\n\n const layer: PushInLayer = {\n element,\n index,\n originalScale: this.getElementScaleX(element),\n ref: { inpoints, outpoints, speed },\n params: {\n inpoint: this.getInpoint(inpoints),\n outpoint: this.getOutpoint(outpoints),\n speed,\n },\n };\n\n this.layers.push(layer);\n this.setZIndex(layer, layers.length);\n }\n }\n\n /**\n * Get all inpoints for the layer.\n */\n private getInpoints(element: HTMLElement, index: number): number[] {\n const { top } = this.scene.getBoundingClientRect();\n\n let inpoints = [top];\n if (element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) {\n inpoints = element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]!.split(',').map(\n inpoint => parseInt(inpoint.trim(), 10)\n );\n } else if (this.layerOptions[index]?.inpoints) {\n inpoints = this.layerOptions[index].inpoints;\n } else if (index === 0 && this.scene.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) {\n // Custom inpoint\n inpoints = this.scene.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]!.split(\n ','\n ).map(inpoint => parseInt(inpoint.trim(), 10));\n } else if (index === 0 && this.sceneOptions?.inpoints.length > 0) {\n inpoints = this.sceneOptions.inpoints;\n } else if (index > 0) {\n // Set default for middle layers if none provided\n const { outpoint } = this.layers[index - 1].params;\n inpoints = [outpoint - this.speedDelta];\n }\n\n return inpoints;\n }\n\n /**\n * Get all outpoints for the layer.\n */\n private getOutpoints(\n element: HTMLElement,\n inpoint: number,\n index: number\n ): number[] {\n let outpoints = [inpoint + this.layerDepth];\n\n if (element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]) {\n const values = element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]!.split(',');\n outpoints = values.map(value => parseInt(value.trim(), 10));\n } else if (this.layerOptions[index]?.outpoints) {\n outpoints = this.layerOptions[index].outpoints;\n }\n\n return outpoints;\n }\n\n /**\n * Get the push-in speed for the layer.\n */\n private getSpeed(element: HTMLElement, index?: number): number {\n let speed: number | null = null;\n\n if (element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]) {\n speed = parseInt(element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]!, 10);\n if (Number.isNaN(speed)) {\n speed = DEFAULT_SPEED;\n }\n } else if (typeof index === 'number' && this.layerOptions[index]?.speed) {\n speed = this.layerOptions[index].speed;\n }\n\n return speed || DEFAULT_SPEED;\n }\n\n /**\n * Get the array index of the current window breakpoint.\n */\n private getBreakpointIndex(): number {\n const windowWidth = typeof window !== 'undefined' ? window.innerWidth : 0;\n const searchIndex = this.sceneOptions.breakpoints\n .reverse()\n .findIndex(bp => bp <= windowWidth);\n return searchIndex === -1\n ? 0\n : this.sceneOptions.breakpoints.length - 1 - searchIndex;\n }\n\n /**\n * Set the z-index of each layer so they overlap correctly.\n */\n private setZIndex(layer: PushInLayer, total: number): void {\n layer.element.style.zIndex = (total - layer.index).toString();\n }\n\n /**\n * Bind event listeners to watch for page load and user interaction.\n */\n bindEvents(): void {\n const onScroll = () => {\n this.scrollY = this.getScrollY();\n this.dolly();\n };\n window.addEventListener('scroll', onScroll);\n this.cleanupFns.push(() => window.removeEventListener('scroll', onScroll));\n\n let resizeTimeout: number;\n const onResize = () => {\n clearTimeout(resizeTimeout);\n\n resizeTimeout = window.setTimeout(() => {\n this.resetLayerParams();\n this.setScrollLength();\n this.toggleLayers();\n }, 300);\n };\n window.addEventListener('resize', onResize);\n this.cleanupFns.push(() => window.removeEventListener('resize', onResize));\n\n if (this.pushinDebug) {\n window.addEventListener('scroll', () => {\n const scrollY = typeof window !== 'undefined' ? window.scrollY : 0;\n const content = this.pushinDebug?.querySelector(\n '.pushin-debug__content'\n );\n if (content) {\n content!.textContent = `Scroll position: ${Math.round(scrollY)}px`;\n }\n });\n }\n }\n\n /**\n * Reset all the layer parameters.\n *\n * This is used if the window is resized\n * and things need to be recalculated.\n */\n private resetLayerParams(): void {\n this.layers.forEach(layer => {\n layer.params = {\n inpoint: this.getInpoint(layer.ref.inpoints),\n outpoint: this.getOutpoint(layer.ref.outpoints),\n speed: layer.ref.speed,\n };\n });\n }\n\n /**\n * Get the initial scale of the element at time of DOM load.\n */\n private getElementScaleX(element: HTMLElement): number {\n const transform = window\n .getComputedStyle(element)\n .getPropertyValue('transform');\n\n let scaleX = 1;\n if (transform && transform !== 'none') {\n const match = transform.match(/[matrix|scale]\\(([\\d,.\\s]+)/);\n if (match && match[1]) {\n const matrix = match[1].split(', ');\n scaleX = parseFloat(matrix[0]);\n }\n }\n\n return scaleX;\n }\n\n /**\n * Animation effect, mimicking a camera dolly on the webpage.\n */\n private dolly(): void {\n cancelAnimationFrame(this.lastAnimationFrameId);\n\n this.lastAnimationFrameId = requestAnimationFrame(() => {\n this.toggleLayers();\n });\n }\n\n /**\n * Show or hide layers and set their scale, depending on if active.\n */\n private toggleLayers(): void {\n this.layers.forEach(layer => this.setLayerStyle(layer));\n }\n\n /**\n * Whether or not a layer should currently be zooming.\n */\n private isActive(layer: PushInLayer): boolean {\n const { inpoint } = layer.params;\n const { outpoint } = layer.params;\n return this.scrollY >= inpoint && this.scrollY <= outpoint;\n }\n\n /**\n * Get the current inpoint for a layer,\n * depending on window breakpoint.\n */\n private getInpoint(inpoints: number[]): number {\n return inpoints[this.getBreakpointIndex()] || inpoints[0];\n }\n\n /**\n * Get the current outpoint for a layer,\n * depending on window breakpoint.\n */\n private getOutpoint(outpoints: number[]): number {\n return outpoints[this.getBreakpointIndex()] || outpoints[0];\n }\n\n /**\n * Get the scaleX value for the layer.\n */\n private getScaleValue(layer: PushInLayer): number {\n const distance = this.scrollY - layer.params.inpoint;\n const speed = Math.min(layer.params.speed, 100) / 100;\n const delta = (distance * speed) / 100;\n\n return Math.max(layer.originalScale + delta, 0);\n }\n\n /**\n * Set element scale.\n */\n private setScale({ style }: HTMLElement, value: number): void {\n const scaleString = `scale(${value})`;\n style.webkitTransform = scaleString;\n (style as unknown as { mozTransform: string }).mozTransform = scaleString;\n (style as unknown as { msTransform: string }).msTransform = scaleString;\n (style as unknown as { oTransform: string }).oTransform = scaleString;\n style.transform = scaleString;\n }\n\n /**\n * Set CSS styles to control the effect on each layer.\n *\n * This will control the scale and opacity of the layer\n * as the user scrolls.\n */\n private setLayerStyle(layer: PushInLayer): void {\n let opacity = 0;\n const isFirst = layer.index === 0;\n const isLast = layer.index + 1 === this.layers.length;\n const { inpoint } = layer.params;\n const { outpoint } = layer.params;\n\n if (isFirst && this.scrollY < inpoint) {\n opacity = 1;\n } else if (isLast && this.scrollY > outpoint) {\n opacity = 1;\n } else if (this.isActive(layer)) {\n this.setScale(layer.element, this.getScaleValue(layer));\n\n let inpointDistance =\n Math.max(Math.min(this.scrollY - inpoint, this.transitionLength), 0) /\n this.transitionLength;\n\n // Set opacity to 1 if its the first layer and it is active (no fading in here)\n if (isFirst) {\n inpointDistance = 1;\n }\n\n let outpointDistance =\n Math.max(Math.min(outpoint - this.scrollY, this.transitionLength), 0) /\n this.transitionLength;\n\n // Set opacity to 1 if its the last layer and it is active (no fading out)\n if (isLast) {\n outpointDistance = 1;\n }\n\n opacity = Math.min(inpointDistance, outpointDistance);\n }\n\n layer.element.style.opacity = opacity.toString();\n }\n\n /**\n * Set the default container height based on a few factors:\n * 1. Number of layers present\n * 2. The transition length between layers\n * 3. The length of scrolling time during each layer\n *\n * If this calculation is smaller than the container's current height,\n * the current height will be used instead.\n */\n private setScrollLength(): void {\n const containerHeight = getComputedStyle(this.container).height.replace(\n 'px',\n ''\n );\n\n const transitions = (this.layers.length - 1) * this.speedDelta;\n const scrollLength =\n this.layers.length * (this.layerDepth + this.transitionLength);\n\n this.container.style.height = `${Math.max(\n parseFloat(containerHeight),\n scrollLength - transitions\n )}px`;\n }\n\n /**\n * Show a debugging tool appended to the frontend of the page.\n * Can be used to determine best \"pushin-from\" and \"pushin-to\" values.\n */\n private showDebugger(): void {\n this.pushinDebug = document.createElement('div');\n this.pushinDebug.classList.add('pushin-debug');\n\n const scrollTitle = document.createElement('p');\n scrollTitle.innerText = 'Pushin.js Debugger';\n scrollTitle.classList.add('pushin-debug__title');\n\n const scrollY = typeof window !== 'undefined' ? window.scrollY : 0;\n\n const debuggerContent = document.createElement('div');\n debuggerContent.classList.add('pushin-debug__content');\n debuggerContent.innerText = `Scroll position: ${scrollY}px`;\n\n this.pushinDebug.appendChild(scrollTitle);\n this.pushinDebug.appendChild(debuggerContent);\n\n document.body.appendChild(this.pushinDebug);\n }\n}\n","import { PushIn } from './pushin';\nimport { PushInOptions } from './types';\n\ndeclare global {\n interface Window {\n pushInStart(options?: PushInOptions | string): void;\n }\n}\n\n/**\n * Helper function: Set up and start push-in effect on all elements\n * matching the provided selector.\n */\nconst pushInStart = (options?: PushInOptions): PushIn[] => {\n const pushInOptions = options ?? {};\n\n const elements = document.querySelectorAll('.pushin');\n const instances: PushIn[] = [];\n for (const element of elements) {\n const instance = new PushIn(element, pushInOptions);\n instance.start();\n\n instances.push(instance);\n }\n\n return instances;\n};\n\nif (typeof window !== 'undefined') {\n window.pushInStart = pushInStart;\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pushin.js","sources":["../../src/constants.ts","../../src/pushInLayer.ts","../../src/pushInScene.ts","../../src/pushin.ts","../../src/helpers.ts"],"sourcesContent":["export const DEFAULT_SPEED = 8;\n\n// The data attribute which may be defined on the elemenet in the following way:\n// `
`.\nexport const PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE = 'pushinBreakpoints';\n\n// The data attribute which may be defined on the elemenet in the following way:\n// `
`.\nexport const PUSH_IN_SPEED_DATA_ATTRIBUTE = 'pushinSpeed';\n\nexport const PUSH_IN_TO_DATA_ATTRIBUTE = 'pushinTo';\nexport const PUSH_IN_FROM_DATA_ATTRIBUTE = 'pushinFrom';\n\nexport const PUSH_IN_DEFAULT_BREAKPOINTS = [768, 1440, 1920];\n","import {\n DEFAULT_SPEED,\n PUSH_IN_TO_DATA_ATTRIBUTE,\n PUSH_IN_FROM_DATA_ATTRIBUTE,\n PUSH_IN_SPEED_DATA_ATTRIBUTE,\n} from './constants';\nimport { PushInScene } from './pushInScene';\n\nimport { LayerOptions, LayerRef, LayerParams } from './types';\n\nexport class PushInLayer {\n private originalScale: number;\n private ref: LayerRef;\n private params: LayerParams;\n\n constructor(\n private element: HTMLElement,\n private index: number,\n private scene: PushInScene,\n private options: LayerOptions | null\n ) {\n const inpoints = this.getInpoints(this.element, this.index);\n const outpoints = this.getOutpoints(this.element, inpoints[0]);\n const speed = this.getSpeed(this.element);\n\n this.originalScale = this.getElementScaleX(element);\n this.ref = { inpoints, outpoints, speed };\n\n this.params = {\n inpoint: this.getInpoint(inpoints),\n outpoint: this.getOutpoint(outpoints),\n speed,\n };\n }\n\n /**\n * Get all inpoints for the layer.\n */\n private getInpoints(element: HTMLElement, index: number): number[] {\n let inpoints = [this.scene.getTop()];\n if (element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) {\n inpoints = element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]!.split(',').map(\n inpoint => parseInt(inpoint.trim(), 10)\n );\n } else if (this.options?.inpoints) {\n inpoints = this.options.inpoints;\n } else if (index === 0) {\n inpoints = this.scene.getInpoints();\n } else if (index > 0) {\n // Set default for middle layers if none provided\n const { outpoint } = this.scene.layers[index - 1].params;\n inpoints = [outpoint - this.scene.speedDelta];\n }\n\n return inpoints;\n }\n\n /**\n * Get all outpoints for the layer.\n */\n private getOutpoints(element: HTMLElement, inpoint: number): number[] {\n let outpoints = [inpoint + this.scene.layerDepth];\n\n if (element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]) {\n const values = element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]!.split(',');\n outpoints = values.map(value => parseInt(value.trim(), 10));\n } else if (this.options?.outpoints) {\n outpoints = this.options.outpoints;\n }\n\n return outpoints;\n }\n\n /**\n * Get the push-in speed for the layer.\n */\n private getSpeed(element: HTMLElement): number {\n let speed: number | null = null;\n\n if (element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]) {\n speed = parseInt(element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]!, 10);\n if (Number.isNaN(speed)) {\n speed = DEFAULT_SPEED;\n }\n } else if (this.options?.speed) {\n speed = this.options.speed;\n }\n\n return speed || DEFAULT_SPEED;\n }\n\n /**\n * Set the z-index of each layer so they overlap correctly.\n */\n setZIndex(total: number): void {\n this.element.style.zIndex = (total - this.index).toString();\n }\n\n /**\n * Reset all the layer parameters.\n *\n * This is used if the window is resized\n * and things need to be recalculated.\n */\n resetLayerParams(): void {\n this.params = {\n inpoint: this.getInpoint(this.ref.inpoints),\n outpoint: this.getOutpoint(this.ref.outpoints),\n speed: this.ref.speed,\n };\n }\n\n /**\n * Get the initial scale of the element at time of DOM load.\n */\n private getElementScaleX(element: HTMLElement): number {\n const transform = window\n .getComputedStyle(element)\n .getPropertyValue('transform');\n\n let scaleX = 1;\n if (transform && transform !== 'none') {\n const match = transform.match(/[matrix|scale]\\(([\\d,.\\s]+)/);\n if (match && match[1]) {\n const matrix = match[1].split(', ');\n scaleX = parseFloat(matrix[0]);\n }\n }\n\n return scaleX;\n }\n\n /**\n * Whether or not a layer should currently be zooming.\n */\n private isActive(): boolean {\n const { inpoint } = this.params;\n const { outpoint } = this.params;\n return (\n this.scene.pushin.scrollY >= inpoint &&\n this.scene.pushin.scrollY <= outpoint\n );\n }\n\n /**\n * Get the current inpoint for a layer,\n * depending on window breakpoint.\n */\n private getInpoint(inpoints: number[]): number {\n const { breakpoints } = this.scene.options;\n return inpoints[this.scene.getBreakpointIndex(breakpoints)] || inpoints[0];\n }\n\n /**\n * Get the current outpoint for a layer,\n * depending on window breakpoint.\n */\n private getOutpoint(outpoints: number[]): number {\n const { breakpoints } = this.scene.options;\n return (\n outpoints[this.scene.getBreakpointIndex(breakpoints)] || outpoints[0]\n );\n }\n\n /**\n * Get the scaleX value for the layer.\n */\n private getScaleValue(layer: PushInLayer): number {\n const distance = this.scene.pushin.scrollY - layer.params.inpoint;\n const speed = Math.min(layer.params.speed, 100) / 100;\n const delta = (distance * speed) / 100;\n\n return Math.max(layer.originalScale + delta, 0);\n }\n\n /**\n * Set element scale.\n */\n private setScale({ style }: HTMLElement, value: number): void {\n const scaleString = `scale(${value})`;\n style.webkitTransform = scaleString;\n (style as unknown as { mozTransform: string }).mozTransform = scaleString;\n (style as unknown as { msTransform: string }).msTransform = scaleString;\n (style as unknown as { oTransform: string }).oTransform = scaleString;\n style.transform = scaleString;\n }\n\n /**\n * Set CSS styles to control the effect on each layer.\n *\n * This will control the scale and opacity of the layer\n * as the user scrolls.\n */\n setLayerStyle(): void {\n let opacity = 0;\n const isFirst = this.index === 0;\n const isLast = this.index + 1 === this.scene.layers.length;\n const { inpoint } = this.params;\n const { outpoint } = this.params;\n\n if (isFirst && this.scene.pushin.scrollY < inpoint) {\n opacity = 1;\n } else if (isLast && this.scene.pushin.scrollY > outpoint) {\n opacity = 1;\n } else if (this.isActive()) {\n this.setScale(this.element, this.getScaleValue(this));\n\n let inpointDistance =\n Math.max(\n Math.min(\n this.scene.pushin.scrollY - inpoint,\n this.scene.transitionLength\n ),\n 0\n ) / this.scene.transitionLength;\n\n // Set opacity to 1 if its the first layer and it is active (no fading in here)\n if (isFirst) {\n inpointDistance = 1;\n }\n\n let outpointDistance =\n Math.max(\n Math.min(\n outpoint - this.scene.pushin.scrollY,\n this.scene.transitionLength\n ),\n 0\n ) / this.scene.transitionLength;\n\n // Set opacity to 1 if its the last layer and it is active (no fading out)\n if (isLast) {\n outpointDistance = 1;\n }\n\n opacity = Math.min(inpointDistance, outpointDistance);\n }\n\n this.element.style.opacity = opacity.toString();\n }\n}\n","import {\n PUSH_IN_FROM_DATA_ATTRIBUTE,\n PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE,\n PUSH_IN_DEFAULT_BREAKPOINTS,\n} from './constants';\nimport { PushInLayer } from './pushInLayer';\nimport { PushIn } from './pushin';\n\nimport { LayerOptions, SceneOptions } from './types';\n\nexport class PushInScene {\n private container: HTMLElement;\n public layers: PushInLayer[];\n public speedDelta: number;\n public transitionLength: number;\n public layerDepth: number;\n public options: SceneOptions;\n\n constructor(public pushin: PushIn) {\n const container =\n this.pushin.container.querySelector('.pushin-scene');\n\n if (container) {\n this.container = container;\n } else {\n this.container = document.createElement('div');\n this.container.classList.add('pushin-scene');\n\n this.container.innerHTML = this.pushin.container.innerHTML;\n this.pushin.container.innerHTML = '';\n this.pushin.container.appendChild(this.container);\n this.pushin.cleanupFns.push(() => {\n this.pushin.container.innerHTML = this.container.innerHTML;\n });\n }\n\n this.options = pushin.sceneOptions;\n\n this.speedDelta = this.options?.speedDelta || 100;\n this.layerDepth = this.options?.layerDepth || 1000;\n this.transitionLength = this.options?.transitionLength || 200;\n\n this.layers = [];\n\n this.setBreakpoints();\n this.getLayers();\n }\n\n /**\n * Set breakpoints for responsive design settings.\n */\n private setBreakpoints(): void {\n if (this.options?.breakpoints.length === 0) {\n this.options.breakpoints = [...PUSH_IN_DEFAULT_BREAKPOINTS];\n }\n\n if (this.container.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE]) {\n this.options!.breakpoints = this.container.dataset[\n PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE\n ]!.split(',').map(breakpoint => parseInt(breakpoint.trim(), 10));\n }\n\n // Always include break point 0 for anything under first breakpoint\n this.options!.breakpoints.unshift(0);\n }\n\n /**\n * Find all layers on the page and store them with their parameters\n */\n private getLayers(): void {\n const layers = Array.from(\n this.container.getElementsByClassName('pushin-layer')\n );\n\n for (let index = 0; index < layers.length; index++) {\n const element = layers[index];\n let options = {};\n if (this.options?.layers && this.options.layers.length > index) {\n options = this!.options.layers[index];\n }\n\n const layer = new PushInLayer(element, index, this, options);\n this.layers.push(layer);\n\n layer.setZIndex(layers.length);\n }\n }\n\n /**\n * Get the array index of the current window breakpoint.\n */\n getBreakpointIndex(breakpoints: number[]): number {\n const searchIndex = breakpoints\n .reverse()\n .findIndex(bp => bp <= window.innerWidth);\n return searchIndex === -1 ? 0 : breakpoints.length - 1 - searchIndex;\n }\n\n getTop() {\n return this.container.getBoundingClientRect().top;\n }\n\n getInpoints(): number[] {\n let inpoints = [this.getTop()];\n\n if (this.container.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) {\n const pushInFrom = (\n this.container.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]\n );\n inpoints.push(parseInt(pushInFrom, 10));\n } else if (this.options?.inpoints?.length > 0) {\n inpoints = this.options.inpoints;\n }\n\n return inpoints;\n }\n}\n","import { PushInScene } from './pushInScene';\nimport { PushInLayer } from './pushInLayer';\n\nimport { PushInOptions, SceneOptions } from './types';\n\n/**\n * PushIn object\n *\n * Once new object is created, it will initialize itself and\n * bind events to begin interacting with dom.\n */\nexport class PushIn {\n private scene!: PushInScene;\n private pushinDebug?: HTMLElement;\n public sceneOptions: SceneOptions;\n\n public scrollY = 0;\n\n private readonly layers: PushInLayer[] = [];\n private readonly debug: boolean;\n\n private lastAnimationFrameId = -1;\n public cleanupFns: VoidFunction[] = [];\n\n constructor(public container: HTMLElement, options?: PushInOptions) {\n this.debug = options?.debug ?? false;\n\n this.sceneOptions = { breakpoints: [], inpoints: [] };\n if (options?.scene) {\n Object.assign(this.sceneOptions, options.scene);\n }\n if (options?.layers) {\n Object.assign(this.sceneOptions, options.layers);\n }\n }\n\n /**\n * Initialize the object to start everything up.\n */\n start(): void {\n this.scrollY = this.getScrollY();\n\n if (this.debug) {\n this.showDebugger();\n }\n\n if (this.container) {\n this.scene = new PushInScene(this);\n\n this.setScrollLength();\n\n if (typeof window !== 'undefined') {\n this.bindEvents();\n }\n\n // Set layer initial state\n this.toggleLayers();\n } else {\n // eslint-disable-next-line no-console\n console.error(\n 'No container element provided to pushIn.js. Effect will not be applied.'\n );\n }\n }\n\n /**\n * Does all necessary cleanups by removing event listeners.\n */\n destroy(): void {\n cancelAnimationFrame(this.lastAnimationFrameId);\n\n while (this.cleanupFns.length) {\n this.cleanupFns.pop()!();\n }\n }\n\n /**\n * If there is a window object,\n * get the current scroll position.\n *\n * Otherwise default to 0.\n */\n private getScrollY(): number {\n return typeof window !== 'undefined' ? window.scrollY : 0;\n }\n\n /**\n * Bind event listeners to watch for page load and user interaction.\n */\n bindEvents(): void {\n const onScroll = () => {\n this.scrollY = this.getScrollY();\n this.dolly();\n\n if (this.pushinDebug) {\n const content = this.pushinDebug?.querySelector(\n '.pushin-debug__content'\n );\n if (content) {\n content!.textContent = `Scroll position: ${Math.round(\n this.scrollY\n )}px`;\n }\n }\n };\n window.addEventListener('scroll', onScroll);\n this.cleanupFns.push(() => window.removeEventListener('scroll', onScroll));\n\n let resizeTimeout: number;\n const onResize = () => {\n clearTimeout(resizeTimeout);\n\n resizeTimeout = window.setTimeout(() => {\n this.scene.layers.forEach(layer => layer.resetLayerParams());\n this.setScrollLength();\n this.toggleLayers();\n }, 300);\n };\n window.addEventListener('resize', onResize);\n this.cleanupFns.push(() => window.removeEventListener('resize', onResize));\n }\n\n /**\n * Animation effect, mimicking a camera dolly on the webpage.\n */\n private dolly(): void {\n cancelAnimationFrame(this.lastAnimationFrameId);\n\n this.lastAnimationFrameId = requestAnimationFrame(() => {\n this.toggleLayers();\n });\n }\n\n /**\n * Show or hide layers and set their scale, depending on if active.\n */\n private toggleLayers(): void {\n this.scene.layers.forEach(layer => layer.setLayerStyle());\n }\n\n /**\n * Set the default container height based on a few factors:\n * 1. Number of layers present\n * 2. The transition length between layers\n * 3. The length of scrolling time during each layer\n *\n * If this calculation is smaller than the container's current height,\n * the current height will be used instead.\n */\n private setScrollLength(): void {\n const containerHeight = getComputedStyle(this.container).height.replace(\n 'px',\n ''\n );\n\n const transitions = (this.scene.layers.length - 1) * this.scene.speedDelta;\n const scrollLength =\n this.scene.layers.length *\n (this.scene.layerDepth + this.scene.transitionLength);\n\n this.container.style.height = `${Math.max(\n parseFloat(containerHeight),\n scrollLength - transitions\n )}px`;\n }\n\n /**\n * Show a debugging tool appended to the frontend of the page.\n * Can be used to determine best \"pushin-from\" and \"pushin-to\" values.\n */\n private showDebugger(): void {\n this.pushinDebug = document.createElement('div');\n this.pushinDebug.classList.add('pushin-debug');\n\n const scrollTitle = document.createElement('p');\n scrollTitle.innerText = 'Pushin.js Debugger';\n scrollTitle.classList.add('pushin-debug__title');\n\n const debuggerContent = document.createElement('div');\n debuggerContent.classList.add('pushin-debug__content');\n debuggerContent.innerText = `Scroll position: ${this.scrollY}px`;\n\n this.pushinDebug.appendChild(scrollTitle);\n this.pushinDebug.appendChild(debuggerContent);\n\n document.body.appendChild(this.pushinDebug);\n }\n}\n","import { PushIn } from './pushin';\nimport { PushInOptions } from './types';\n\ndeclare global {\n interface Window {\n pushInStart(options?: PushInOptions | string): void;\n }\n}\n\n/**\n * Helper function: Set up and start push-in effect on all elements\n * matching the provided selector.\n */\nconst pushInStart = (options?: PushInOptions): PushIn[] => {\n const pushInOptions = options ?? {};\n\n const elements = document.querySelectorAll('.pushin');\n const instances: PushIn[] = [];\n for (const element of elements) {\n const instance = new PushIn(element, pushInOptions);\n instance.start();\n\n instances.push(instance);\n }\n\n return instances;\n};\n\nif (typeof window !== 'undefined') {\n window.pushInStart = pushInStart;\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/umd/pushin.min.js b/dist/umd/pushin.min.js index 76ee24d..3aea62c 100644 --- a/dist/umd/pushin.min.js +++ b/dist/umd/pushin.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).pushin={})}(this,(function(t){"use strict";class e{constructor(t,e){var s,n,i;this.container=t,this.scrollY=0,this.scrollEnd=null,this.touchStart=null,this.pageHeight=null,this.layers=[],this.speedDelta=100,this.transitionLength=200,this.layerDepth=1e3,this.lastAnimationFrameId=-1,this.cleanupFns=[],this.debug=null!==(s=null==e?void 0:e.debug)&&void 0!==s&&s,this.layerOptions=null!==(n=null==e?void 0:e.layers)&&void 0!==n?n:[],this.sceneOptions=null!==(i=null==e?void 0:e.scene)&&void 0!==i?i:{breakpoints:[],inpoints:[]}}start(){this.container?(this.scrollY=this.getScrollY(),this.debug&&this.showDebugger(),this.addScene(),this.setBreakpoints(),this.getLayers(),this.setScrollLength(),"undefined"!=typeof window&&this.bindEvents(),this.toggleLayers()):console.error("No container element provided to pushIn.js. Effect will not be applied.")}destroy(){for(cancelAnimationFrame(this.lastAnimationFrameId);this.cleanupFns.length;)this.cleanupFns.pop()()}getScrollY(){return"undefined"!=typeof window?window.scrollY:0}addScene(){const t=this.container.querySelector(".pushin-scene");t?this.scene=t:(this.scene=document.createElement("div"),this.scene.classList.add("pushin-scene"),this.scene.innerHTML=this.container.innerHTML,this.container.innerHTML="",this.container.appendChild(this.scene),this.cleanupFns.push((()=>this.container.removeChild(this.scene))))}setBreakpoints(){0===this.sceneOptions.breakpoints.length&&(this.sceneOptions.breakpoints=[768,1440,1920]),this.scene.dataset.pushinBreakpoints&&(this.sceneOptions.breakpoints=this.scene.dataset.pushinBreakpoints.split(",").map((t=>parseInt(t.trim(),10)))),this.sceneOptions.breakpoints.unshift(0)}getLayers(){const t=Array.from(this.container.getElementsByClassName("pushin-layer"));for(let e=0;eparseInt(t.trim(),10)));else if(null===(s=this.layerOptions[e])||void 0===s?void 0:s.inpoints)o=this.layerOptions[e].inpoints;else if(0===e&&this.scene.dataset.pushinFrom)o=this.scene.dataset.pushinFrom.split(",").map((t=>parseInt(t.trim(),10)));else if(0===e&&(null===(n=this.sceneOptions)||void 0===n?void 0:n.inpoints.length)>0)o=this.sceneOptions.inpoints;else if(e>0){const{outpoint:t}=this.layers[e-1].params;o=[t-this.speedDelta]}return o}getOutpoints(t,e,s){var n;let i=[e+this.layerDepth];if(t.dataset.pushinTo){i=t.dataset.pushinTo.split(",").map((t=>parseInt(t.trim(),10)))}else(null===(n=this.layerOptions[s])||void 0===n?void 0:n.outpoints)&&(i=this.layerOptions[s].outpoints);return i}getSpeed(t,e){var s;let n=null;return t.dataset.pushinSpeed?(n=parseInt(t.dataset.pushinSpeed,10),Number.isNaN(n)&&(n=8)):"number"==typeof e&&(null===(s=this.layerOptions[e])||void 0===s?void 0:s.speed)&&(n=this.layerOptions[e].speed),n||8}getBreakpointIndex(){const t="undefined"!=typeof window?window.innerWidth:0,e=this.sceneOptions.breakpoints.reverse().findIndex((e=>e<=t));return-1===e?0:this.sceneOptions.breakpoints.length-1-e}setZIndex(t,e){t.element.style.zIndex=(e-t.index).toString()}bindEvents(){const t=()=>{this.scrollY=this.getScrollY(),this.dolly()};let e;window.addEventListener("scroll",t),this.cleanupFns.push((()=>window.removeEventListener("scroll",t)));const s=()=>{clearTimeout(e),e=window.setTimeout((()=>{this.resetLayerParams(),this.setScrollLength(),this.toggleLayers()}),300)};window.addEventListener("resize",s),this.cleanupFns.push((()=>window.removeEventListener("resize",s))),this.pushinDebug&&window.addEventListener("scroll",(()=>{var t;const e="undefined"!=typeof window?window.scrollY:0,s=null===(t=this.pushinDebug)||void 0===t?void 0:t.querySelector(".pushin-debug__content");s&&(s.textContent=`Scroll position: ${Math.round(e)}px`)}))}resetLayerParams(){this.layers.forEach((t=>{t.params={inpoint:this.getInpoint(t.ref.inpoints),outpoint:this.getOutpoint(t.ref.outpoints),speed:t.ref.speed}}))}getElementScaleX(t){const e=window.getComputedStyle(t).getPropertyValue("transform");let s=1;if(e&&"none"!==e){const t=e.match(/[matrix|scale]\(([\d,.\s]+)/);if(t&&t[1]){const e=t[1].split(", ");s=parseFloat(e[0])}}return s}dolly(){cancelAnimationFrame(this.lastAnimationFrameId),this.lastAnimationFrameId=requestAnimationFrame((()=>{this.toggleLayers()}))}toggleLayers(){this.layers.forEach((t=>this.setLayerStyle(t)))}isActive(t){const{inpoint:e}=t.params,{outpoint:s}=t.params;return this.scrollY>=e&&this.scrollY<=s}getInpoint(t){return t[this.getBreakpointIndex()]||t[0]}getOutpoint(t){return t[this.getBreakpointIndex()]||t[0]}getScaleValue(t){const e=(this.scrollY-t.params.inpoint)*(Math.min(t.params.speed,100)/100)/100;return Math.max(t.originalScale+e,0)}setScale({style:t},e){const s=`scale(${e})`;t.webkitTransform=s,t.mozTransform=s,t.msTransform=s,t.oTransform=s,t.transform=s}setLayerStyle(t){let e=0;const s=0===t.index,n=t.index+1===this.layers.length,{inpoint:i}=t.params,{outpoint:o}=t.params;if(s&&this.scrollYo)e=1;else if(this.isActive(t)){this.setScale(t.element,this.getScaleValue(t));let r=Math.max(Math.min(this.scrollY-i,this.transitionLength),0)/this.transitionLength;s&&(r=1);let a=Math.max(Math.min(o-this.scrollY,this.transitionLength),0)/this.transitionLength;n&&(a=1),e=Math.min(r,a)}t.element.style.opacity=e.toString()}setScrollLength(){const t=getComputedStyle(this.container).height.replace("px",""),e=(this.layers.length-1)*this.speedDelta,s=this.layers.length*(this.layerDepth+this.transitionLength);this.container.style.height=`${Math.max(parseFloat(t),s-e)}px`}showDebugger(){this.pushinDebug=document.createElement("div"),this.pushinDebug.classList.add("pushin-debug");const t=document.createElement("p");t.innerText="Pushin.js Debugger",t.classList.add("pushin-debug__title");const e="undefined"!=typeof window?window.scrollY:0,s=document.createElement("div");s.classList.add("pushin-debug__content"),s.innerText=`Scroll position: ${e}px`,this.pushinDebug.appendChild(t),this.pushinDebug.appendChild(s),document.body.appendChild(this.pushinDebug)}}const s=t=>{const s=null!=t?t:{},n=document.querySelectorAll(".pushin"),i=[];for(const t of n){const n=new e(t,s);n.start(),i.push(n)}return i};"undefined"!=typeof window&&(window.pushInStart=s),t.PushIn=e,Object.defineProperty(t,"__esModule",{value:!0})})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).pushin={})}(this,(function(t){"use strict";const e=[768,1440,1920];class s{constructor(t,e,s,n){this.element=t,this.index=e,this.scene=s,this.options=n;const i=this.getInpoints(this.element,this.index),o=this.getOutpoints(this.element,i[0]),h=this.getSpeed(this.element);this.originalScale=this.getElementScaleX(t),this.ref={inpoints:i,outpoints:o,speed:h},this.params={inpoint:this.getInpoint(i),outpoint:this.getOutpoint(o),speed:h}}getInpoints(t,e){var s;let n=[this.scene.getTop()];if(t.dataset.pushinFrom)n=t.dataset.pushinFrom.split(",").map((t=>parseInt(t.trim(),10)));else if(null===(s=this.options)||void 0===s?void 0:s.inpoints)n=this.options.inpoints;else if(0===e)n=this.scene.getInpoints();else if(e>0){const{outpoint:t}=this.scene.layers[e-1].params;n=[t-this.scene.speedDelta]}return n}getOutpoints(t,e){var s;let n=[e+this.scene.layerDepth];if(t.dataset.pushinTo){n=t.dataset.pushinTo.split(",").map((t=>parseInt(t.trim(),10)))}else(null===(s=this.options)||void 0===s?void 0:s.outpoints)&&(n=this.options.outpoints);return n}getSpeed(t){var e;let s=null;return t.dataset.pushinSpeed?(s=parseInt(t.dataset.pushinSpeed,10),Number.isNaN(s)&&(s=8)):(null===(e=this.options)||void 0===e?void 0:e.speed)&&(s=this.options.speed),s||8}setZIndex(t){this.element.style.zIndex=(t-this.index).toString()}resetLayerParams(){this.params={inpoint:this.getInpoint(this.ref.inpoints),outpoint:this.getOutpoint(this.ref.outpoints),speed:this.ref.speed}}getElementScaleX(t){const e=window.getComputedStyle(t).getPropertyValue("transform");let s=1;if(e&&"none"!==e){const t=e.match(/[matrix|scale]\(([\d,.\s]+)/);if(t&&t[1]){const e=t[1].split(", ");s=parseFloat(e[0])}}return s}isActive(){const{inpoint:t}=this.params,{outpoint:e}=this.params;return this.scene.pushin.scrollY>=t&&this.scene.pushin.scrollY<=e}getInpoint(t){const{breakpoints:e}=this.scene.options;return t[this.scene.getBreakpointIndex(e)]||t[0]}getOutpoint(t){const{breakpoints:e}=this.scene.options;return t[this.scene.getBreakpointIndex(e)]||t[0]}getScaleValue(t){const e=(this.scene.pushin.scrollY-t.params.inpoint)*(Math.min(t.params.speed,100)/100)/100;return Math.max(t.originalScale+e,0)}setScale({style:t},e){const s=`scale(${e})`;t.webkitTransform=s,t.mozTransform=s,t.msTransform=s,t.oTransform=s,t.transform=s}setLayerStyle(){let t=0;const e=0===this.index,s=this.index+1===this.scene.layers.length,{inpoint:n}=this.params,{outpoint:i}=this.params;if(e&&this.scene.pushin.scrollYi)t=1;else if(this.isActive()){this.setScale(this.element,this.getScaleValue(this));let o=Math.max(Math.min(this.scene.pushin.scrollY-n,this.scene.transitionLength),0)/this.scene.transitionLength;e&&(o=1);let h=Math.max(Math.min(i-this.scene.pushin.scrollY,this.scene.transitionLength),0)/this.scene.transitionLength;s&&(h=1),t=Math.min(o,h)}this.element.style.opacity=t.toString()}}class n{constructor(t){var e,s,n;this.pushin=t;const i=this.pushin.container.querySelector(".pushin-scene");i?this.container=i:(this.container=document.createElement("div"),this.container.classList.add("pushin-scene"),this.container.innerHTML=this.pushin.container.innerHTML,this.pushin.container.innerHTML="",this.pushin.container.appendChild(this.container),this.pushin.cleanupFns.push((()=>{this.pushin.container.innerHTML=this.container.innerHTML}))),this.options=t.sceneOptions,this.speedDelta=(null===(e=this.options)||void 0===e?void 0:e.speedDelta)||100,this.layerDepth=(null===(s=this.options)||void 0===s?void 0:s.layerDepth)||1e3,this.transitionLength=(null===(n=this.options)||void 0===n?void 0:n.transitionLength)||200,this.layers=[],this.setBreakpoints(),this.getLayers()}setBreakpoints(){var t;0===(null===(t=this.options)||void 0===t?void 0:t.breakpoints.length)&&(this.options.breakpoints=[...e]),this.container.dataset.pushinBreakpoints&&(this.options.breakpoints=this.container.dataset.pushinBreakpoints.split(",").map((t=>parseInt(t.trim(),10)))),this.options.breakpoints.unshift(0)}getLayers(){var t;const e=Array.from(this.container.getElementsByClassName("pushin-layer"));for(let n=0;nn&&(o=this.options.layers[n]);const h=new s(i,n,this,o);this.layers.push(h),h.setZIndex(e.length)}}getBreakpointIndex(t){const e=t.reverse().findIndex((t=>t<=window.innerWidth));return-1===e?0:t.length-1-e}getTop(){return this.container.getBoundingClientRect().top}getInpoints(){var t,e;let s=[this.getTop()];if(this.container.dataset.pushinFrom){const t=this.container.dataset.pushinFrom;s.push(parseInt(t,10))}else(null===(e=null===(t=this.options)||void 0===t?void 0:t.inpoints)||void 0===e?void 0:e.length)>0&&(s=this.options.inpoints);return s}}class i{constructor(t,e){var s;this.container=t,this.scrollY=0,this.layers=[],this.lastAnimationFrameId=-1,this.cleanupFns=[],this.debug=null!==(s=null==e?void 0:e.debug)&&void 0!==s&&s,this.sceneOptions={breakpoints:[],inpoints:[]},(null==e?void 0:e.scene)&&Object.assign(this.sceneOptions,e.scene),(null==e?void 0:e.layers)&&Object.assign(this.sceneOptions,e.layers)}start(){this.scrollY=this.getScrollY(),this.debug&&this.showDebugger(),this.container?(this.scene=new n(this),this.setScrollLength(),"undefined"!=typeof window&&this.bindEvents(),this.toggleLayers()):console.error("No container element provided to pushIn.js. Effect will not be applied.")}destroy(){for(cancelAnimationFrame(this.lastAnimationFrameId);this.cleanupFns.length;)this.cleanupFns.pop()()}getScrollY(){return"undefined"!=typeof window?window.scrollY:0}bindEvents(){const t=()=>{var t;if(this.scrollY=this.getScrollY(),this.dolly(),this.pushinDebug){const e=null===(t=this.pushinDebug)||void 0===t?void 0:t.querySelector(".pushin-debug__content");e&&(e.textContent=`Scroll position: ${Math.round(this.scrollY)}px`)}};let e;window.addEventListener("scroll",t),this.cleanupFns.push((()=>window.removeEventListener("scroll",t)));const s=()=>{clearTimeout(e),e=window.setTimeout((()=>{this.scene.layers.forEach((t=>t.resetLayerParams())),this.setScrollLength(),this.toggleLayers()}),300)};window.addEventListener("resize",s),this.cleanupFns.push((()=>window.removeEventListener("resize",s)))}dolly(){cancelAnimationFrame(this.lastAnimationFrameId),this.lastAnimationFrameId=requestAnimationFrame((()=>{this.toggleLayers()}))}toggleLayers(){this.scene.layers.forEach((t=>t.setLayerStyle()))}setScrollLength(){const t=getComputedStyle(this.container).height.replace("px",""),e=(this.scene.layers.length-1)*this.scene.speedDelta,s=this.scene.layers.length*(this.scene.layerDepth+this.scene.transitionLength);this.container.style.height=`${Math.max(parseFloat(t),s-e)}px`}showDebugger(){this.pushinDebug=document.createElement("div"),this.pushinDebug.classList.add("pushin-debug");const t=document.createElement("p");t.innerText="Pushin.js Debugger",t.classList.add("pushin-debug__title");const e=document.createElement("div");e.classList.add("pushin-debug__content"),e.innerText=`Scroll position: ${this.scrollY}px`,this.pushinDebug.appendChild(t),this.pushinDebug.appendChild(e),document.body.appendChild(this.pushinDebug)}}const o=t=>{const e=null!=t?t:{},s=document.querySelectorAll(".pushin"),n=[];for(const t of s){const s=new i(t,e);s.start(),n.push(s)}return n};"undefined"!=typeof window&&(window.pushInStart=o),t.PushIn=i,Object.defineProperty(t,"__esModule",{value:!0})})); diff --git a/jest.config.ts b/jest.config.ts index 4f879ed..b5445a9 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -42,7 +42,10 @@ const config: Config.InitialOptions = { * coverage information will be collected for it even if no tests exist for this file and * it's never required in the test suite. */ - collectCoverageFrom: ['test/*.spec.ts'], + collectCoverageFrom: [ + 'src/**/*.ts', + '!src/index.ts|src/constants.ts|src/helpers.ts', + ], /** * A list of reporter names that Jest uses when writing coverage reports. @@ -54,7 +57,7 @@ const config: Config.InitialOptions = { /** * The glob patterns Jest uses to detect test files. */ - testMatch: ['/test/*.spec.ts'], + testMatch: ['/test/**/*.spec.ts'], /** * Indicates whether each individual test should be reported during the run. diff --git a/package-lock.json b/package-lock.json index 0bc8a4e..4c494b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pushin", - "version": "4.0.3", + "version": "4.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "pushin", - "version": "4.0.3", + "version": "4.1.0", "hasInstallScript": true, "license": "MIT", "devDependencies": { @@ -36,7 +36,7 @@ "prettier": "^2.6.1", "pug": "^3.0.2", "pug-loader": "^2.4.0", - "rollup": "2.70.2", + "rollup": "2.72.1", "rollup-plugin-copy": "3.4.0", "rollup-plugin-terser": "^7.0.2", "style-loader": "^3.3.1", @@ -1583,18 +1583,19 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.2.1", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz", + "integrity": "sha512-uGo44hIwoLGNyduRpjdEpovcbMdd+Nv7amtmJxnKmI8xj6yd5LncmSwDa5NgX/41lIFJtkjD6YdVfgEzPfJ5UA==", "dev": true, - "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.1", + "espree": "^9.3.2", "globals": "^13.9.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "engines": { @@ -1602,9 +1603,10 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.13.0", + "version": "13.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.14.0.tgz", + "integrity": "sha512-ERO68sOYwm5UuLvSJTY7w7NP2c8S4UcXs3X1GBX8cwOr+ShOcDBbCY5mH4zxz0jsYCdJ8ve8Mv9n2YGJMB1aeg==", "dev": true, - "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -1617,8 +1619,9 @@ }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2745,9 +2748,9 @@ } }, "node_modules/@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", + "version": "27.5.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.0.tgz", + "integrity": "sha512-9RBFx7r4k+msyj/arpfaa0WOOEcaAZNmN+j80KFbFCoSqCJGHTz7YMAMGQW9Xmqm5w6l5c25vbSjMwlikJi5+g==", "dev": true, "dependencies": { "jest-matcher-utils": "^27.0.0", @@ -3481,9 +3484,10 @@ } }, "node_modules/acorn": { - "version": "8.7.0", + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "dev": true, - "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -3521,8 +3525,9 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -3681,8 +3686,9 @@ }, "node_modules/argparse": { "version": "2.0.1", - "dev": true, - "license": "Python-2.0" + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/array-flatten": { "version": "2.1.2", @@ -5280,11 +5286,12 @@ } }, "node_modules/eslint": { - "version": "8.13.0", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz", + "integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==", "dev": true, - "license": "MIT", "dependencies": { - "@eslint/eslintrc": "^1.2.1", + "@eslint/eslintrc": "^1.2.3", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -5295,7 +5302,7 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", + "espree": "^9.3.2", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5311,7 +5318,7 @@ "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", "regexpp": "^3.2.0", @@ -5612,12 +5619,13 @@ } }, "node_modules/espree": { - "version": "9.3.1", + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -6523,8 +6531,9 @@ }, "node_modules/import-fresh": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, - "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -9035,8 +9044,9 @@ }, "node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -9202,9 +9212,9 @@ "dev": true }, "node_modules/lint-staged": { - "version": "12.3.8", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-12.3.8.tgz", - "integrity": "sha512-0+UpNaqIwKRSGAFOCcpuYNIv/j5QGVC+xUVvmSdxHO+IfIGoHbFLo3XcPmV/LLnsVj5EAncNHVtlITSoY5qWGQ==", + "version": "12.4.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-12.4.1.tgz", + "integrity": "sha512-PTXgzpflrQ+pODQTG116QNB+Q6uUTDg5B5HqGvNhoQSGt8Qy+MA/6zSnR8n38+sxP5TapzeQGTvoKni0KRS8Vg==", "dev": true, "dependencies": { "cli-truncate": "^3.1.0", @@ -10044,8 +10054,9 @@ }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -10833,8 +10844,9 @@ }, "node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -10897,9 +10909,9 @@ } }, "node_modules/rollup": { - "version": "2.70.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.2.tgz", - "integrity": "sha512-EitogNZnfku65I1DD5Mxe8JYRUCy0hkK5X84IlDtUs+O6JRMpRciXTzyCUuX11b5L5pvjH+OmFXiQ3XjabcXgg==", + "version": "2.72.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.72.1.tgz", + "integrity": "sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -11897,9 +11909,10 @@ } }, "node_modules/ts-loader": { - "version": "9.2.8", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.0.tgz", + "integrity": "sha512-2kLLAdAD+FCKijvGKi9sS0OzoqxLCF3CxHpok7rVgCZ5UldRzH0TkbwG9XECKjBzHsAewntC5oDaI/FwKzEUog==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^5.0.0", @@ -13947,22 +13960,26 @@ "dev": true }, "@eslint/eslintrc": { - "version": "1.2.1", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz", + "integrity": "sha512-uGo44hIwoLGNyduRpjdEpovcbMdd+Nv7amtmJxnKmI8xj6yd5LncmSwDa5NgX/41lIFJtkjD6YdVfgEzPfJ5UA==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.1", + "espree": "^9.3.2", "globals": "^13.9.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "dependencies": { "globals": { - "version": "13.13.0", + "version": "13.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.14.0.tgz", + "integrity": "sha512-ERO68sOYwm5UuLvSJTY7w7NP2c8S4UcXs3X1GBX8cwOr+ShOcDBbCY5mH4zxz0jsYCdJ8ve8Mv9n2YGJMB1aeg==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -13970,6 +13987,8 @@ }, "type-fest": { "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true } } @@ -14828,9 +14847,9 @@ } }, "@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", + "version": "27.5.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.0.tgz", + "integrity": "sha512-9RBFx7r4k+msyj/arpfaa0WOOEcaAZNmN+j80KFbFCoSqCJGHTz7YMAMGQW9Xmqm5w6l5c25vbSjMwlikJi5+g==", "dev": true, "requires": { "jest-matcher-utils": "^27.0.0", @@ -15334,7 +15353,9 @@ } }, "acorn": { - "version": "8.7.0", + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "dev": true }, "acorn-globals": { @@ -15358,6 +15379,8 @@ }, "acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "requires": {} }, @@ -15456,6 +15479,8 @@ }, "argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, "array-flatten": { @@ -16532,10 +16557,12 @@ } }, "eslint": { - "version": "8.13.0", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz", + "integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.2.1", + "@eslint/eslintrc": "^1.2.3", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -16546,7 +16573,7 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", + "espree": "^9.3.2", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -16562,7 +16589,7 @@ "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", "regexpp": "^3.2.0", @@ -16747,11 +16774,13 @@ "dev": true }, "espree": { - "version": "9.3.1", + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", "dev": true, "requires": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" } }, @@ -17335,6 +17364,8 @@ }, "import-fresh": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -19111,6 +19142,8 @@ }, "js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" @@ -19225,9 +19258,9 @@ "dev": true }, "lint-staged": { - "version": "12.3.8", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-12.3.8.tgz", - "integrity": "sha512-0+UpNaqIwKRSGAFOCcpuYNIv/j5QGVC+xUVvmSdxHO+IfIGoHbFLo3XcPmV/LLnsVj5EAncNHVtlITSoY5qWGQ==", + "version": "12.4.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-12.4.1.tgz", + "integrity": "sha512-PTXgzpflrQ+pODQTG116QNB+Q6uUTDg5B5HqGvNhoQSGt8Qy+MA/6zSnR8n38+sxP5TapzeQGTvoKni0KRS8Vg==", "dev": true, "requires": { "cli-truncate": "^3.1.0", @@ -19760,6 +19793,8 @@ }, "parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { "callsites": "^3.0.0" @@ -20286,6 +20321,8 @@ }, "resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve.exports": { @@ -20322,9 +20359,9 @@ } }, "rollup": { - "version": "2.70.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.2.tgz", - "integrity": "sha512-EitogNZnfku65I1DD5Mxe8JYRUCy0hkK5X84IlDtUs+O6JRMpRciXTzyCUuX11b5L5pvjH+OmFXiQ3XjabcXgg==", + "version": "2.72.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.72.1.tgz", + "integrity": "sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -20973,7 +21010,9 @@ } }, "ts-loader": { - "version": "9.2.8", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.0.tgz", + "integrity": "sha512-2kLLAdAD+FCKijvGKi9sS0OzoqxLCF3CxHpok7rVgCZ5UldRzH0TkbwG9XECKjBzHsAewntC5oDaI/FwKzEUog==", "dev": true, "requires": { "chalk": "^4.1.0", diff --git a/package.json b/package.json index be9c02b..7b68ed6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pushin", "description": "A javascript plugin to attach a 'dolly' or 'push-in' effect to a div element when user scrolls.", - "version": "4.0.3", + "version": "4.1.0", "sideEffects": true, "module": "dist/esm/pushin.js", "main": "dist/umd/pushin.js", @@ -30,7 +30,7 @@ "docs": "webpack --mode=production", "start": "webpack serve --mode=development", "test:watch": "jest --watch", - "coverage": "jest --coverage", + "coverage": "jest --coverage && open coverage/lcov-report/index.html -a 'Google Chrome'", "test": "jest --run-in-band", "prepack": "clean-package", "postpack": "clean-package restore", @@ -90,7 +90,7 @@ "prettier": "^2.6.1", "pug": "^3.0.2", "pug-loader": "^2.4.0", - "rollup": "2.70.2", + "rollup": "2.72.1", "rollup-plugin-copy": "3.4.0", "rollup-plugin-terser": "^7.0.2", "style-loader": "^3.3.1", diff --git a/src/constants.ts b/src/constants.ts index b6efc02..dabde2c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -10,3 +10,5 @@ export const PUSH_IN_SPEED_DATA_ATTRIBUTE = 'pushinSpeed'; export const PUSH_IN_TO_DATA_ATTRIBUTE = 'pushinTo'; export const PUSH_IN_FROM_DATA_ATTRIBUTE = 'pushinFrom'; + +export const PUSH_IN_DEFAULT_BREAKPOINTS = [768, 1440, 1920]; diff --git a/src/pushInLayer.ts b/src/pushInLayer.ts new file mode 100644 index 0000000..810d63e --- /dev/null +++ b/src/pushInLayer.ts @@ -0,0 +1,241 @@ +import { + DEFAULT_SPEED, + PUSH_IN_TO_DATA_ATTRIBUTE, + PUSH_IN_FROM_DATA_ATTRIBUTE, + PUSH_IN_SPEED_DATA_ATTRIBUTE, +} from './constants'; +import { PushInScene } from './pushInScene'; + +import { LayerOptions, LayerRef, LayerParams } from './types'; + +export class PushInLayer { + private originalScale: number; + private ref: LayerRef; + private params: LayerParams; + + constructor( + private element: HTMLElement, + private index: number, + private scene: PushInScene, + private options: LayerOptions | null + ) { + const inpoints = this.getInpoints(this.element, this.index); + const outpoints = this.getOutpoints(this.element, inpoints[0]); + const speed = this.getSpeed(this.element); + + this.originalScale = this.getElementScaleX(element); + this.ref = { inpoints, outpoints, speed }; + + this.params = { + inpoint: this.getInpoint(inpoints), + outpoint: this.getOutpoint(outpoints), + speed, + }; + } + + /** + * Get all inpoints for the layer. + */ + private getInpoints(element: HTMLElement, index: number): number[] { + let inpoints = [this.scene.getTop()]; + if (element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { + inpoints = element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]!.split(',').map( + inpoint => parseInt(inpoint.trim(), 10) + ); + } else if (this.options?.inpoints) { + inpoints = this.options.inpoints; + } else if (index === 0) { + inpoints = this.scene.getInpoints(); + } else if (index > 0) { + // Set default for middle layers if none provided + const { outpoint } = this.scene.layers[index - 1].params; + inpoints = [outpoint - this.scene.speedDelta]; + } + + return inpoints; + } + + /** + * Get all outpoints for the layer. + */ + private getOutpoints(element: HTMLElement, inpoint: number): number[] { + let outpoints = [inpoint + this.scene.layerDepth]; + + if (element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]) { + const values = element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]!.split(','); + outpoints = values.map(value => parseInt(value.trim(), 10)); + } else if (this.options?.outpoints) { + outpoints = this.options.outpoints; + } + + return outpoints; + } + + /** + * Get the push-in speed for the layer. + */ + private getSpeed(element: HTMLElement): number { + let speed: number | null = null; + + if (element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]) { + speed = parseInt(element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]!, 10); + if (Number.isNaN(speed)) { + speed = DEFAULT_SPEED; + } + } else if (this.options?.speed) { + speed = this.options.speed; + } + + return speed || DEFAULT_SPEED; + } + + /** + * Set the z-index of each layer so they overlap correctly. + */ + setZIndex(total: number): void { + this.element.style.zIndex = (total - this.index).toString(); + } + + /** + * Reset all the layer parameters. + * + * This is used if the window is resized + * and things need to be recalculated. + */ + resetLayerParams(): void { + this.params = { + inpoint: this.getInpoint(this.ref.inpoints), + outpoint: this.getOutpoint(this.ref.outpoints), + speed: this.ref.speed, + }; + } + + /** + * Get the initial scale of the element at time of DOM load. + */ + private getElementScaleX(element: HTMLElement): number { + const transform = window + .getComputedStyle(element) + .getPropertyValue('transform'); + + let scaleX = 1; + if (transform && transform !== 'none') { + const match = transform.match(/[matrix|scale]\(([\d,.\s]+)/); + if (match && match[1]) { + const matrix = match[1].split(', '); + scaleX = parseFloat(matrix[0]); + } + } + + return scaleX; + } + + /** + * Whether or not a layer should currently be zooming. + */ + private isActive(): boolean { + const { inpoint } = this.params; + const { outpoint } = this.params; + return ( + this.scene.pushin.scrollY >= inpoint && + this.scene.pushin.scrollY <= outpoint + ); + } + + /** + * Get the current inpoint for a layer, + * depending on window breakpoint. + */ + private getInpoint(inpoints: number[]): number { + const { breakpoints } = this.scene.options; + return inpoints[this.scene.getBreakpointIndex(breakpoints)] || inpoints[0]; + } + + /** + * Get the current outpoint for a layer, + * depending on window breakpoint. + */ + private getOutpoint(outpoints: number[]): number { + const { breakpoints } = this.scene.options; + return ( + outpoints[this.scene.getBreakpointIndex(breakpoints)] || outpoints[0] + ); + } + + /** + * Get the scaleX value for the layer. + */ + private getScaleValue(layer: PushInLayer): number { + const distance = this.scene.pushin.scrollY - layer.params.inpoint; + const speed = Math.min(layer.params.speed, 100) / 100; + const delta = (distance * speed) / 100; + + return Math.max(layer.originalScale + delta, 0); + } + + /** + * Set element scale. + */ + private setScale({ style }: HTMLElement, value: number): void { + const scaleString = `scale(${value})`; + style.webkitTransform = scaleString; + (style as unknown as { mozTransform: string }).mozTransform = scaleString; + (style as unknown as { msTransform: string }).msTransform = scaleString; + (style as unknown as { oTransform: string }).oTransform = scaleString; + style.transform = scaleString; + } + + /** + * Set CSS styles to control the effect on each layer. + * + * This will control the scale and opacity of the layer + * as the user scrolls. + */ + setLayerStyle(): void { + let opacity = 0; + const isFirst = this.index === 0; + const isLast = this.index + 1 === this.scene.layers.length; + const { inpoint } = this.params; + const { outpoint } = this.params; + + if (isFirst && this.scene.pushin.scrollY < inpoint) { + opacity = 1; + } else if (isLast && this.scene.pushin.scrollY > outpoint) { + opacity = 1; + } else if (this.isActive()) { + this.setScale(this.element, this.getScaleValue(this)); + + let inpointDistance = + Math.max( + Math.min( + this.scene.pushin.scrollY - inpoint, + this.scene.transitionLength + ), + 0 + ) / this.scene.transitionLength; + + // Set opacity to 1 if its the first layer and it is active (no fading in here) + if (isFirst) { + inpointDistance = 1; + } + + let outpointDistance = + Math.max( + Math.min( + outpoint - this.scene.pushin.scrollY, + this.scene.transitionLength + ), + 0 + ) / this.scene.transitionLength; + + // Set opacity to 1 if its the last layer and it is active (no fading out) + if (isLast) { + outpointDistance = 1; + } + + opacity = Math.min(inpointDistance, outpointDistance); + } + + this.element.style.opacity = opacity.toString(); + } +} diff --git a/src/pushInScene.ts b/src/pushInScene.ts new file mode 100644 index 0000000..dc3f54c --- /dev/null +++ b/src/pushInScene.ts @@ -0,0 +1,117 @@ +import { + PUSH_IN_FROM_DATA_ATTRIBUTE, + PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE, + PUSH_IN_DEFAULT_BREAKPOINTS, +} from './constants'; +import { PushInLayer } from './pushInLayer'; +import { PushIn } from './pushin'; + +import { LayerOptions, SceneOptions } from './types'; + +export class PushInScene { + private container: HTMLElement; + public layers: PushInLayer[]; + public speedDelta: number; + public transitionLength: number; + public layerDepth: number; + public options: SceneOptions; + + constructor(public pushin: PushIn) { + const container = + this.pushin.container.querySelector('.pushin-scene'); + + if (container) { + this.container = container; + } else { + this.container = document.createElement('div'); + this.container.classList.add('pushin-scene'); + + this.container.innerHTML = this.pushin.container.innerHTML; + this.pushin.container.innerHTML = ''; + this.pushin.container.appendChild(this.container); + this.pushin.cleanupFns.push(() => { + this.pushin.container.innerHTML = this.container.innerHTML; + }); + } + + this.options = pushin.sceneOptions; + + this.speedDelta = this.options?.speedDelta || 100; + this.layerDepth = this.options?.layerDepth || 1000; + this.transitionLength = this.options?.transitionLength || 200; + + this.layers = []; + + this.setBreakpoints(); + this.getLayers(); + } + + /** + * Set breakpoints for responsive design settings. + */ + private setBreakpoints(): void { + if (this.options?.breakpoints.length === 0) { + this.options.breakpoints = [...PUSH_IN_DEFAULT_BREAKPOINTS]; + } + + if (this.container.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE]) { + this.options!.breakpoints = this.container.dataset[ + PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE + ]!.split(',').map(breakpoint => parseInt(breakpoint.trim(), 10)); + } + + // Always include break point 0 for anything under first breakpoint + this.options!.breakpoints.unshift(0); + } + + /** + * Find all layers on the page and store them with their parameters + */ + private getLayers(): void { + const layers = Array.from( + this.container.getElementsByClassName('pushin-layer') + ); + + for (let index = 0; index < layers.length; index++) { + const element = layers[index]; + let options = {}; + if (this.options?.layers && this.options.layers.length > index) { + options = this!.options.layers[index]; + } + + const layer = new PushInLayer(element, index, this, options); + this.layers.push(layer); + + layer.setZIndex(layers.length); + } + } + + /** + * Get the array index of the current window breakpoint. + */ + getBreakpointIndex(breakpoints: number[]): number { + const searchIndex = breakpoints + .reverse() + .findIndex(bp => bp <= window.innerWidth); + return searchIndex === -1 ? 0 : breakpoints.length - 1 - searchIndex; + } + + getTop() { + return this.container.getBoundingClientRect().top; + } + + getInpoints(): number[] { + let inpoints = [this.getTop()]; + + if (this.container.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { + const pushInFrom = ( + this.container.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE] + ); + inpoints.push(parseInt(pushInFrom, 10)); + } else if (this.options?.inpoints?.length > 0) { + inpoints = this.options.inpoints; + } + + return inpoints; + } +} diff --git a/src/pushin.ts b/src/pushin.ts index 9d48b0b..c8b823b 100644 --- a/src/pushin.ts +++ b/src/pushin.ts @@ -1,16 +1,7 @@ -import { - DEFAULT_SPEED, - PUSH_IN_TO_DATA_ATTRIBUTE, - PUSH_IN_FROM_DATA_ATTRIBUTE, - PUSH_IN_SPEED_DATA_ATTRIBUTE, - PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE, -} from './constants'; -import { - PushInLayer, - PushInOptions, - LayerOptions, - SceneOptions, -} from './types'; +import { PushInScene } from './pushInScene'; +import { PushInLayer } from './pushInLayer'; + +import { PushInOptions, SceneOptions } from './types'; /** * PushIn object @@ -19,46 +10,43 @@ import { * bind events to begin interacting with dom. */ export class PushIn { - private scene!: HTMLElement; + private scene!: PushInScene; private pushinDebug?: HTMLElement; - private layerOptions: LayerOptions[]; - private sceneOptions: SceneOptions; + public sceneOptions: SceneOptions; - private scrollY = 0; - private scrollEnd: number | null = null; - private touchStart: number | null = null; - private pageHeight: number | null = null; + public scrollY = 0; private readonly layers: PushInLayer[] = []; private readonly debug: boolean; - private speedDelta = 100; - private transitionLength = 200; - private layerDepth = 1000; - private lastAnimationFrameId = -1; - private readonly cleanupFns: VoidFunction[] = []; + public cleanupFns: VoidFunction[] = []; - constructor(private container: HTMLElement, options?: PushInOptions) { + constructor(public container: HTMLElement, options?: PushInOptions) { this.debug = options?.debug ?? false; - this.layerOptions = options?.layers ?? []; - this.sceneOptions = options?.scene ?? { breakpoints: [], inpoints: [] }; + + this.sceneOptions = { breakpoints: [], inpoints: [] }; + if (options?.scene) { + Object.assign(this.sceneOptions, options.scene); + } + if (options?.layers) { + Object.assign(this.sceneOptions, options.layers); + } } /** * Initialize the object to start everything up. */ start(): void { - if (this.container) { - this.scrollY = this.getScrollY(); + this.scrollY = this.getScrollY(); - if (this.debug) { - this.showDebugger(); - } + if (this.debug) { + this.showDebugger(); + } + + if (this.container) { + this.scene = new PushInScene(this); - this.addScene(); - this.setBreakpoints(); - this.getLayers(); this.setScrollLength(); if (typeof window !== 'undefined') { @@ -96,163 +84,6 @@ export class PushIn { return typeof window !== 'undefined' ? window.scrollY : 0; } - /** - * Get the "scene" element from the DOM. - * If it doesn't exist, make one. - */ - private addScene(): void { - const scene = this.container.querySelector('.pushin-scene'); - - if (scene) { - this.scene = scene; - } else { - this.scene = document.createElement('div'); - this.scene.classList.add('pushin-scene'); - - this.scene.innerHTML = this.container.innerHTML; - this.container.innerHTML = ''; - this.container.appendChild(this.scene); - // We register the cleanup function only for the manually created scene. - this.cleanupFns.push(() => this.container.removeChild(this.scene)); - } - } - - /** - * Set breakpoints for responsive design settings. - */ - private setBreakpoints(): void { - if (this.sceneOptions.breakpoints.length === 0) { - this.sceneOptions.breakpoints = [768, 1440, 1920]; - } - - if (this.scene.dataset[PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE]) { - this.sceneOptions.breakpoints = this.scene.dataset[ - PUSH_IN_BREAKPOINTS_DATA_ATTRIBUTE - ]!.split(',').map(breakpoint => parseInt(breakpoint.trim(), 10)); - } - - // Always include break point 0 for anything under first breakpoint - this.sceneOptions.breakpoints.unshift(0); - } - - /** - * Find all layers on the page and store them with their parameters - */ - private getLayers(): void { - const layers = Array.from( - this.container.getElementsByClassName('pushin-layer') - ); - - for (let index = 0; index < layers.length; index++) { - const element = layers[index]; - const inpoints = this.getInpoints(element, index); - const outpoints = this.getOutpoints(element, inpoints[0], index); - const speed = this.getSpeed(element, index); - - const layer: PushInLayer = { - element, - index, - originalScale: this.getElementScaleX(element), - ref: { inpoints, outpoints, speed }, - params: { - inpoint: this.getInpoint(inpoints), - outpoint: this.getOutpoint(outpoints), - speed, - }, - }; - - this.layers.push(layer); - this.setZIndex(layer, layers.length); - } - } - - /** - * Get all inpoints for the layer. - */ - private getInpoints(element: HTMLElement, index: number): number[] { - const { top } = this.scene.getBoundingClientRect(); - - let inpoints = [top]; - if (element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { - inpoints = element.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]!.split(',').map( - inpoint => parseInt(inpoint.trim(), 10) - ); - } else if (this.layerOptions[index]?.inpoints) { - inpoints = this.layerOptions[index].inpoints; - } else if (index === 0 && this.scene.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]) { - // Custom inpoint - inpoints = this.scene.dataset[PUSH_IN_FROM_DATA_ATTRIBUTE]!.split( - ',' - ).map(inpoint => parseInt(inpoint.trim(), 10)); - } else if (index === 0 && this.sceneOptions?.inpoints.length > 0) { - inpoints = this.sceneOptions.inpoints; - } else if (index > 0) { - // Set default for middle layers if none provided - const { outpoint } = this.layers[index - 1].params; - inpoints = [outpoint - this.speedDelta]; - } - - return inpoints; - } - - /** - * Get all outpoints for the layer. - */ - private getOutpoints( - element: HTMLElement, - inpoint: number, - index: number - ): number[] { - let outpoints = [inpoint + this.layerDepth]; - - if (element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]) { - const values = element.dataset[PUSH_IN_TO_DATA_ATTRIBUTE]!.split(','); - outpoints = values.map(value => parseInt(value.trim(), 10)); - } else if (this.layerOptions[index]?.outpoints) { - outpoints = this.layerOptions[index].outpoints; - } - - return outpoints; - } - - /** - * Get the push-in speed for the layer. - */ - private getSpeed(element: HTMLElement, index?: number): number { - let speed: number | null = null; - - if (element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]) { - speed = parseInt(element.dataset[PUSH_IN_SPEED_DATA_ATTRIBUTE]!, 10); - if (Number.isNaN(speed)) { - speed = DEFAULT_SPEED; - } - } else if (typeof index === 'number' && this.layerOptions[index]?.speed) { - speed = this.layerOptions[index].speed; - } - - return speed || DEFAULT_SPEED; - } - - /** - * Get the array index of the current window breakpoint. - */ - private getBreakpointIndex(): number { - const windowWidth = typeof window !== 'undefined' ? window.innerWidth : 0; - const searchIndex = this.sceneOptions.breakpoints - .reverse() - .findIndex(bp => bp <= windowWidth); - return searchIndex === -1 - ? 0 - : this.sceneOptions.breakpoints.length - 1 - searchIndex; - } - - /** - * Set the z-index of each layer so they overlap correctly. - */ - private setZIndex(layer: PushInLayer, total: number): void { - layer.element.style.zIndex = (total - layer.index).toString(); - } - /** * Bind event listeners to watch for page load and user interaction. */ @@ -260,6 +91,17 @@ export class PushIn { const onScroll = () => { this.scrollY = this.getScrollY(); this.dolly(); + + if (this.pushinDebug) { + const content = this.pushinDebug?.querySelector( + '.pushin-debug__content' + ); + if (content) { + content!.textContent = `Scroll position: ${Math.round( + this.scrollY + )}px`; + } + } }; window.addEventListener('scroll', onScroll); this.cleanupFns.push(() => window.removeEventListener('scroll', onScroll)); @@ -269,61 +111,13 @@ export class PushIn { clearTimeout(resizeTimeout); resizeTimeout = window.setTimeout(() => { - this.resetLayerParams(); + this.scene.layers.forEach(layer => layer.resetLayerParams()); this.setScrollLength(); this.toggleLayers(); }, 300); }; window.addEventListener('resize', onResize); this.cleanupFns.push(() => window.removeEventListener('resize', onResize)); - - if (this.pushinDebug) { - window.addEventListener('scroll', () => { - const scrollY = typeof window !== 'undefined' ? window.scrollY : 0; - const content = this.pushinDebug?.querySelector( - '.pushin-debug__content' - ); - if (content) { - content!.textContent = `Scroll position: ${Math.round(scrollY)}px`; - } - }); - } - } - - /** - * Reset all the layer parameters. - * - * This is used if the window is resized - * and things need to be recalculated. - */ - private resetLayerParams(): void { - this.layers.forEach(layer => { - layer.params = { - inpoint: this.getInpoint(layer.ref.inpoints), - outpoint: this.getOutpoint(layer.ref.outpoints), - speed: layer.ref.speed, - }; - }); - } - - /** - * Get the initial scale of the element at time of DOM load. - */ - private getElementScaleX(element: HTMLElement): number { - const transform = window - .getComputedStyle(element) - .getPropertyValue('transform'); - - let scaleX = 1; - if (transform && transform !== 'none') { - const match = transform.match(/[matrix|scale]\(([\d,.\s]+)/); - if (match && match[1]) { - const matrix = match[1].split(', '); - scaleX = parseFloat(matrix[0]); - } - } - - return scaleX; } /** @@ -341,99 +135,7 @@ export class PushIn { * Show or hide layers and set their scale, depending on if active. */ private toggleLayers(): void { - this.layers.forEach(layer => this.setLayerStyle(layer)); - } - - /** - * Whether or not a layer should currently be zooming. - */ - private isActive(layer: PushInLayer): boolean { - const { inpoint } = layer.params; - const { outpoint } = layer.params; - return this.scrollY >= inpoint && this.scrollY <= outpoint; - } - - /** - * Get the current inpoint for a layer, - * depending on window breakpoint. - */ - private getInpoint(inpoints: number[]): number { - return inpoints[this.getBreakpointIndex()] || inpoints[0]; - } - - /** - * Get the current outpoint for a layer, - * depending on window breakpoint. - */ - private getOutpoint(outpoints: number[]): number { - return outpoints[this.getBreakpointIndex()] || outpoints[0]; - } - - /** - * Get the scaleX value for the layer. - */ - private getScaleValue(layer: PushInLayer): number { - const distance = this.scrollY - layer.params.inpoint; - const speed = Math.min(layer.params.speed, 100) / 100; - const delta = (distance * speed) / 100; - - return Math.max(layer.originalScale + delta, 0); - } - - /** - * Set element scale. - */ - private setScale({ style }: HTMLElement, value: number): void { - const scaleString = `scale(${value})`; - style.webkitTransform = scaleString; - (style as unknown as { mozTransform: string }).mozTransform = scaleString; - (style as unknown as { msTransform: string }).msTransform = scaleString; - (style as unknown as { oTransform: string }).oTransform = scaleString; - style.transform = scaleString; - } - - /** - * Set CSS styles to control the effect on each layer. - * - * This will control the scale and opacity of the layer - * as the user scrolls. - */ - private setLayerStyle(layer: PushInLayer): void { - let opacity = 0; - const isFirst = layer.index === 0; - const isLast = layer.index + 1 === this.layers.length; - const { inpoint } = layer.params; - const { outpoint } = layer.params; - - if (isFirst && this.scrollY < inpoint) { - opacity = 1; - } else if (isLast && this.scrollY > outpoint) { - opacity = 1; - } else if (this.isActive(layer)) { - this.setScale(layer.element, this.getScaleValue(layer)); - - let inpointDistance = - Math.max(Math.min(this.scrollY - inpoint, this.transitionLength), 0) / - this.transitionLength; - - // Set opacity to 1 if its the first layer and it is active (no fading in here) - if (isFirst) { - inpointDistance = 1; - } - - let outpointDistance = - Math.max(Math.min(outpoint - this.scrollY, this.transitionLength), 0) / - this.transitionLength; - - // Set opacity to 1 if its the last layer and it is active (no fading out) - if (isLast) { - outpointDistance = 1; - } - - opacity = Math.min(inpointDistance, outpointDistance); - } - - layer.element.style.opacity = opacity.toString(); + this.scene.layers.forEach(layer => layer.setLayerStyle()); } /** @@ -451,9 +153,10 @@ export class PushIn { '' ); - const transitions = (this.layers.length - 1) * this.speedDelta; + const transitions = (this.scene.layers.length - 1) * this.scene.speedDelta; const scrollLength = - this.layers.length * (this.layerDepth + this.transitionLength); + this.scene.layers.length * + (this.scene.layerDepth + this.scene.transitionLength); this.container.style.height = `${Math.max( parseFloat(containerHeight), @@ -473,11 +176,9 @@ export class PushIn { scrollTitle.innerText = 'Pushin.js Debugger'; scrollTitle.classList.add('pushin-debug__title'); - const scrollY = typeof window !== 'undefined' ? window.scrollY : 0; - const debuggerContent = document.createElement('div'); debuggerContent.classList.add('pushin-debug__content'); - debuggerContent.innerText = `Scroll position: ${scrollY}px`; + debuggerContent.innerText = `Scroll position: ${this.scrollY}px`; this.pushinDebug.appendChild(scrollTitle); this.pushinDebug.appendChild(debuggerContent); diff --git a/src/types.ts b/src/types.ts index 87b95ca..6377c4d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,8 +5,12 @@ export interface LayerOptions { } export interface SceneOptions { + speedDelta?: number; + layerDepth?: number; + transitionLength?: number; breakpoints: number[]; inpoints: number[]; + layers?: LayerOptions[]; } export interface PushInOptions { @@ -19,14 +23,16 @@ export interface PushInLayer { element: HTMLElement; index: number; originalScale: number; - ref: { - inpoints: number[]; - outpoints: number[]; - speed: number; - }; - params: { - inpoint: number; - outpoint: number; - speed: number; - }; +} + +export interface LayerRef { + inpoints: number[]; + outpoints: number[]; + speed: number; +} + +export interface LayerParams { + inpoint: number; + outpoint: number; + speed: number; } diff --git a/test/__mocks__/layerOptions.ts b/test/__mocks__/layerOptions.ts new file mode 100644 index 0000000..ea26647 --- /dev/null +++ b/test/__mocks__/layerOptions.ts @@ -0,0 +1,5 @@ +export default { + inpoints: [100, 200], + outpoints: [150, 250], + speed: 50, +} diff --git a/test/addScene.spec.ts b/test/addScene.spec.ts deleted file mode 100644 index 9874334..0000000 --- a/test/addScene.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; - -describe('addScene', () => { - let textContent: string; - let pushIn: PushIn; - - beforeEach(() => { - textContent = 'FooBar'; - setupJSDOM(` - - -
-
${textContent}
-
- - `); - - const container = document.querySelector('.pushin'); - pushIn = new PushIn(container); - }); - - afterEach(() => pushIn.destroy()); - - it('Should assign existing .pushin-scene element to the scene property', () => { - pushIn['addScene'](); - const result = pushIn['scene'].textContent; - expect(result).toEqual(textContent); - }); - - it("Should create new .pushin-scene element if it doesn't yet exist", () => { - document.querySelector('.pushin-scene').remove(); - pushIn['addScene'](); - const result = pushIn['scene'].classList.contains('pushin-scene'); - expect(result).toEqual(true); - }); - - it('Should move any inner HTML into the new scene element as children', () => { - const innerHTML = 'FooBar'; - document.querySelector('.pushin-scene').remove(); - document.querySelector('.pushin').innerHTML = innerHTML; - pushIn['addScene'](); - const result = pushIn['scene'].innerHTML; - expect(result).toEqual(innerHTML); - }); -}); diff --git a/test/getElementScaleX.spec.ts b/test/getElementScaleX.spec.ts deleted file mode 100644 index 988fa13..0000000 --- a/test/getElementScaleX.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; - -describe('getElementScaleX', () => { - let pushIn: PushIn; - - beforeEach(() => { - setupJSDOM(` - - -
Hello World!
- - `); - - pushIn = new PushIn(null); - }); - - afterEach(() => pushIn.destroy()); - - it('Should return default element scale if never altered', () => { - const element = document.querySelector('.foo'); - const result = pushIn['getElementScaleX'](element); - - expect(result).toEqual(1); - }); - - it('Should return element scale if it was previously set', () => { - const element = document.querySelector('.foo'); - - element.style.transform = 'scale(5)'; - - const result = pushIn['getElementScaleX'](element); - - expect(result).toEqual(5); - }); -}); diff --git a/test/getLayers.spec.ts b/test/getLayers.spec.ts deleted file mode 100644 index 344874a..0000000 --- a/test/getLayers.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; - -describe('getLayers', () => { - let pushIn: PushIn; - let layers: HTMLElement[]; - - beforeEach(() => { - setupJSDOM(` - - -
-
-
Layer 0
-
Layer 1
-
Layer 2
-
Layer 3
-
-
- - `); - - const container = document.querySelector('.pushin'); - pushIn = new PushIn(container); - const scene = document.querySelector('.pushin-scene'); - pushIn['scene'] = scene; - - layers = [...document.querySelectorAll('.pushin-layer')]; - - // Mock some methods - Object.assign(pushIn, { - getInpoints: () => [1, 2], - getInpoint: () => 1, - getOutpoints: () => [3, 4], - getOutpoint: () => 3, - getElementScaleX: () => 123, - getSpeed: () => 5, - setZIndex: () => {}, - }); - }); - - afterEach(() => pushIn.destroy()); - - it('Should set the layers property to contain all .pushin-layer elements', () => { - pushIn['getLayers'](); - expect(pushIn['layers'].length).toEqual(layers.length); - }); - - it('Should include the element for each layer', () => { - pushIn['getLayers'](); - const result = pushIn['layers'][0].element.id; - expect(result).toEqual('layer-0'); - }); - - it('Should include the index of each layer', () => { - pushIn['getLayers'](); - const result = pushIn['layers'][0].index; - expect(result).toEqual(0); - }); - - it('Should include the original scale of each layer', () => { - pushIn['getLayers'](); - const result = pushIn['layers'][1].originalScale; - expect(result).toEqual(123); - }); - - it('Should include reference inpoints array', () => { - pushIn['getLayers'](); - const result = pushIn['layers'][2].ref.inpoints; - expect(result).toEqual([1, 2]); - }); - - it('Should include reference outpoints array', () => { - pushIn['getLayers'](); - const result = pushIn['layers'][0].ref.outpoints; - expect(result).toEqual([3, 4]); - }); - - it('Should include the inpoint param', () => { - pushIn['getLayers'](); - const result = pushIn['layers'][0].params.inpoint; - expect(result).toEqual(1); - }); - - it('Should include the outpoint param', () => { - pushIn['getLayers'](); - const result = pushIn['layers'][0].params.outpoint; - expect(result).toEqual(3); - }); - - it('Should include the speed param', () => { - pushIn['getLayers'](); - const result = pushIn['layers'][0].params.speed; - expect(result).toEqual(5); - }); -}); diff --git a/test/getOutpoints.spec.ts b/test/getOutpoints.spec.ts deleted file mode 100644 index 4dceb8b..0000000 --- a/test/getOutpoints.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; - -describe('getInpoints', () => { - let pushIn: PushIn; - - beforeEach(() => { - setupJSDOM(` - - -
-
-
Layer 0
-
Layer 1
-
Layer 2
-
Layer 3
-
-
- - `); - - pushIn = new PushIn(null); - }); - - afterEach(() => pushIn.destroy()); - - it('Should return inpoint + layerDepth by default for first layer', () => { - pushIn['layerDepth'] = 300; - - const inpoint = 100; - - const elem = document.querySelector('#layer-0'); - const result = pushIn['getOutpoints'](elem, inpoint, 0); - - expect(result).toEqual([400]); - }); - - it('Should return data-attribute value if set', () => { - pushIn['layerDepth'] = 300; - - const inpoint = 100; - - const elem = document.querySelector('#layer-1'); - const result = pushIn['getOutpoints'](elem, inpoint, 1); - - expect(result).toEqual([300]); - }); - - it('Should return array of data from data-attribute if set', () => { - pushIn['layerDepth'] = 300; - - const inpoint = 100; - - const elem = document.querySelector('#layer-2'); - const result = pushIn['getOutpoints'](elem, inpoint, 2); - - expect(result).toEqual([300, 500]); - }); - - it('Should generate value based on previous inpoint', () => { - pushIn['layerDepth'] = 300; - - const inpoint = 500; - - const elem = document.querySelector('#layer-3'); - const result = pushIn['getOutpoints'](elem, inpoint, 3); - - expect(result).toEqual([800]); - }); -}); diff --git a/test/getScaleValue.spec.ts b/test/getScaleValue.spec.ts deleted file mode 100644 index 9c31aa6..0000000 --- a/test/getScaleValue.spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; -import { PushInLayer } from '../src/types'; - -describe('getScaleValue', () => { - let pushIn: PushIn; - const layerMock = { - originalScale: 2, - params: { - inpoint: 10, - speed: 2, - }, - } as PushInLayer; - - const layerMock2 = { - originalScale: 1, - params: { - inpoint: 150, - speed: 100, - }, - } as PushInLayer; - - beforeEach(() => { - setupJSDOM(``); - pushIn = new PushIn(null); - }); - - afterEach(() => pushIn.destroy()); - - it('should return original scale if scroll position and inpoint are the same', () => { - pushIn['scrollY'] = 10; - const result = pushIn['getScaleValue'](layerMock); - - expect(result).toEqual(2); - }); - - it('should reduce scale if scrollY is less than inpoint', () => { - pushIn['scrollY'] = 6; - const result = pushIn['getScaleValue'](layerMock); - - expect(result).toEqual(1.9992); - }); - - it('should increase scale if scrollY is greater than inpoint', () => { - pushIn['scrollY'] = 20; - const result = pushIn['getScaleValue'](layerMock); - - expect(result).toEqual(2.002); - }); - - it('should not return a negative number', () => { - pushIn['scrollY'] = 1; - const result = pushIn['getScaleValue'](layerMock2); - - expect(result).toEqual(0); - }); -}); diff --git a/test/getSpeed.spec.ts b/test/getSpeed.spec.ts deleted file mode 100644 index 6850b42..0000000 --- a/test/getSpeed.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; -import { DEFAULT_SPEED } from '../src/constants'; - -describe('getSpeed', () => { - let pushIn: PushIn; - - beforeEach(() => { - setupJSDOM(` - - -
-
-
Layer 0
-
Layer 1
-
Layer 2
-
-
- - `); - - const container = document.querySelector('.pushin'); - pushIn = new PushIn(container); - }); - - afterEach(() => pushIn.destroy()); - - it('Should return 8 by default', () => { - const elem = document.querySelector('#layer-0'); - const result = pushIn['getSpeed'](elem); - expect(result).toEqual(DEFAULT_SPEED); - }); - - it('Should return integer value from data-pushin-speed attribute', () => { - const elem = document.querySelector('#layer-1'); - const result = pushIn['getSpeed'](elem); - expect(result).toEqual(50); - }); - - it('Should return default if NaN', () => { - const elem = document.querySelector('#layer-2'); - const result = pushIn['getSpeed'](elem); - expect(result).toEqual(DEFAULT_SPEED); - }); -}); diff --git a/test/isActive.spec.ts b/test/isActive.spec.ts deleted file mode 100644 index e7216ee..0000000 --- a/test/isActive.spec.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; -import { PushInLayer } from '../src/types'; - -describe('isActive', () => { - let pushIn: PushIn; - - const layer = { - params: { - inpoint: 10, - outpoint: 20, - }, - } as PushInLayer; - - beforeEach(() => { - setupJSDOM(``); - pushIn = new PushIn(null); - }); - - afterEach(() => pushIn.destroy()); - - it('should be true if screen top is greater than inpoint and less than outpoint', () => { - pushIn['scrollY'] = 15; - const result = pushIn['isActive'](layer); - - expect(result).toEqual(true); - }); - - it('should be true if screen top is equal to inpoint', () => { - pushIn['scrollY'] = 10; - const result = pushIn['isActive'](layer); - - expect(result).toEqual(true); - }); - - it('should be true if screen top is equal to outpoint', () => { - pushIn['scrollY'] = 20; - const result = pushIn['isActive'](layer); - - expect(result).toEqual(true); - }); - - it('should be false if screen top is less than inpoint', () => { - pushIn['scrollY'] = 5; - const result = pushIn['isActive'](layer); - - expect(result).toEqual(false); - }); - - it('should be false if screen top is greater than outpoint', () => { - pushIn['scrollY'] = 25; - const result = pushIn['isActive'](layer); - - expect(result).toEqual(false); - }); -}); diff --git a/test/destroy.spec.ts b/test/pushIn/destroy.spec.ts similarity index 89% rename from test/destroy.spec.ts rename to test/pushIn/destroy.spec.ts index d941d16..a969fb8 100644 --- a/test/destroy.spec.ts +++ b/test/pushIn/destroy.spec.ts @@ -1,5 +1,5 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; +import { setupJSDOM } from '../setup'; +import { PushIn } from '../../src/pushin'; describe('destroy', () => { let textContent: string; diff --git a/test/pushIn/setScrollLength.spec.ts b/test/pushIn/setScrollLength.spec.ts new file mode 100644 index 0000000..72c39d6 --- /dev/null +++ b/test/pushIn/setScrollLength.spec.ts @@ -0,0 +1,70 @@ +import { setupJSDOM } from '../setup'; +import { PushIn } from '../../src/pushin'; +import { PushInLayer } from '../../src/pushInLayer'; +import { PushInScene } from '../../src/pushInScene'; + +describe('setScrollLength', () => { + let mockPushIn: PushIn; + let container: HTMLElement; + + beforeEach(() => { + setupJSDOM(` + + +
+ + `); + + container = document.querySelector('.pushin'); + + const mockScene = Object.create(PushInScene.prototype); + Object.assign( + mockScene, + { + speedDelta: 100, + layerDepth: 100, + transitionLength: 100, + layers: [ + Object.create(PushInLayer.prototype), + Object.create(PushInLayer.prototype), + Object.create(PushInLayer.prototype), + ] + } + ); + + mockPushIn = Object.create(PushIn.prototype); + Object.assign( + mockPushIn, + { + container, + scene: mockScene + } + ); + }); + + it('Should set the container height to its original value if it is higher than calculated value', () => { + mockPushIn['setScrollLength'](); + const result = container.style.height; + expect(result).toEqual('500px'); + }); + + it('Should calculate container height based on layerDepth and transitionLength properties', () => { + mockPushIn['scene']['speedDelta'] = 0; + mockPushIn['scene']['layerDepth'] = 200; + mockPushIn['scene']['transitionLength'] = 200; + + mockPushIn['setScrollLength'](); + const result = container.style.height; + expect(result).toEqual('1200px'); + }); + + it('Should reduce container height to account for overlapping transition length', () => { + mockPushIn['scene']['speedDelta'] = 100; + mockPushIn['scene']['layerDepth'] = 200; + mockPushIn['scene']['transitionLength'] = 200; + + mockPushIn['setScrollLength'](); + const result = container.style.height; + expect(result).toEqual('1000px'); + }); +}); diff --git a/test/pushInLayer/getElementScaleX.spec.ts b/test/pushInLayer/getElementScaleX.spec.ts new file mode 100644 index 0000000..61844c0 --- /dev/null +++ b/test/pushInLayer/getElementScaleX.spec.ts @@ -0,0 +1,32 @@ +import { setupJSDOM } from '../setup'; +import { PushInLayer } from '../../src/pushInLayer'; + +describe('getElementScaleX', () => { + let element: HTMLElement; + let mockPushInLayer: PushInLayer; + jest.mock('../../src/pushInLayer', () => jest.fn()); + + beforeEach(() => { + setupJSDOM(` + + +
Hello World!
+ + `); + + element = document.querySelector('.foo'); + mockPushInLayer = Object.create(PushInLayer.prototype); + mockPushInLayer['element'] = element; + }); + + it('Should return default element scale if never altered', () => { + const result = mockPushInLayer['getElementScaleX'](element); + expect(result).toEqual(1); + }); + + it('Should return element scale if it was previously set', () => { + element.style.transform = 'scale(5)'; + const result = mockPushInLayer['getElementScaleX'](element); + expect(result).toEqual(5); + }); +}); diff --git a/test/getInpoints.spec.ts b/test/pushInLayer/getInpoints.spec.ts similarity index 57% rename from test/getInpoints.spec.ts rename to test/pushInLayer/getInpoints.spec.ts index 88bd332..1e257f8 100644 --- a/test/getInpoints.spec.ts +++ b/test/pushInLayer/getInpoints.spec.ts @@ -1,8 +1,10 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; +import { setupJSDOM } from '../setup'; +import { PushInLayer } from '../../src/pushInLayer'; +import { PushInScene } from '../../src/pushInScene'; describe('getInpoints', () => { - let pushIn: PushIn; + let mockPushInLayer: PushInLayer; + let mockPushInScene: PushInScene; beforeEach(() => { setupJSDOM(` @@ -19,56 +21,46 @@ describe('getInpoints', () => { `); - pushIn = new PushIn(null); - pushIn['scene'] = document.querySelector('.pushin-scene'); - pushIn['scene'].getBoundingClientRect = () => { - return { top: 10 } as unknown as DOMRect; + const mockLayer1 = Object.create(PushInLayer.prototype); + mockLayer1['params'] = { + outpoint: 1000, }; - pushIn['speedDelta'] = 100; - (pushIn as any).layers = [ + mockPushInScene = Object.create(PushInScene.prototype); + mockPushInScene['getTop'] = () => 0; + mockPushInScene['getInpoints'] = () => [10]; + mockPushInScene['layers'] = [ null, null, - { - params: { - outpoint: 1000, - }, - }, + mockLayer1 ]; - }); - - afterEach(() => pushIn.destroy()); + mockPushInScene['speedDelta'] = 100; - it('Should return scene[pushinFrom] value, if available for first layer', () => { - // const scene = document.querySelector( '.pushin-scene' ); - pushIn['scene'].setAttribute('data-pushin-from', '30'); - - const elem = document.querySelector('#layer-0'); - const result = pushIn['getInpoints'](elem, 0); - expect(result).toEqual([30]); + mockPushInLayer = Object.create(PushInLayer.prototype); + mockPushInLayer['scene'] = mockPushInScene; }); it('Should return scene top value as the default for first layer', () => { const elem = document.querySelector('#layer-0'); - const result = pushIn['getInpoints'](elem, 0); + const result = mockPushInLayer['getInpoints'](elem, 0); expect(result).toEqual([10]); }); it('Should return value provided by data attribute', () => { const elem = document.querySelector('#layer-1'); - const result = pushIn['getInpoints'](elem, 1); + const result = mockPushInLayer['getInpoints'](elem, 1); expect(result).toEqual([300]); }); it('Should return array of values provided by data attribute', () => { const elem = document.querySelector('#layer-2'); - const result = pushIn['getInpoints'](elem, 2); + const result = mockPushInLayer['getInpoints'](elem, 2); expect(result).toEqual([300, 500]); }); it('Should return generated value based on previous layer outpoint', () => { const elem = document.querySelector('#layer-3'); - const result = pushIn['getInpoints'](elem, 3); + const result = mockPushInLayer['getInpoints'](elem, 3); expect(result).toEqual([900]); }); }); diff --git a/test/pushInLayer/getOutpoints.spec.ts b/test/pushInLayer/getOutpoints.spec.ts new file mode 100644 index 0000000..5a4a5a8 --- /dev/null +++ b/test/pushInLayer/getOutpoints.spec.ts @@ -0,0 +1,70 @@ +import { setupJSDOM } from '../setup'; +import { PushInScene } from '../../src/pushInScene'; +import { PushInLayer } from '../../src/pushInLayer'; + +describe('getInpoints', () => { + let mockPushInLayer: PushInLayer; + + beforeEach(() => { + setupJSDOM(` + + +
+
+
Layer 0
+
Layer 1
+
Layer 2
+
Layer 3
+
+
+ + `); + + mockPushInLayer = Object.create(PushInLayer.prototype); + mockPushInLayer['scene'] = {}; + }); + + it('Should return inpoint + layerDepth by default for first layer', () => { + mockPushInLayer['scene']['layerDepth'] = 300; + + const inpoint = 100; + + const elem = document.querySelector('#layer-0'); + const result = mockPushInLayer['getOutpoints'](elem, inpoint); + + expect(result).toEqual([400]); + }); + + it('Should return data-attribute value if set', () => { + mockPushInLayer['scene']['layerDepth'] = 300; + + const inpoint = 100; + + const elem = document.querySelector('#layer-1'); + const result = mockPushInLayer['getOutpoints'](elem, inpoint); + + expect(result).toEqual([300]); + }); + + it('Should return array of data from data-attribute if set', () => { + mockPushInLayer['scene']['layerDepth'] = 300; + + const inpoint = 100; + + const elem = document.querySelector('#layer-2'); + const result = mockPushInLayer['getOutpoints'](elem, inpoint); + + expect(result).toEqual([300, 500]); + }); + + it('Should generate value based on previous inpoint', () => { + mockPushInLayer['scene']['layerDepth'] = 300; + + const inpoint = 500; + + const elem = document.querySelector('#layer-3'); + const result = mockPushInLayer['getOutpoints'](elem, inpoint); + + expect(result).toEqual([800]); + }); +}); diff --git a/test/pushInLayer/getScaleValue.spec.ts b/test/pushInLayer/getScaleValue.spec.ts new file mode 100644 index 0000000..217abc1 --- /dev/null +++ b/test/pushInLayer/getScaleValue.spec.ts @@ -0,0 +1,60 @@ +import { setupJSDOM } from '../setup'; +import { PushInLayer } from '../../src/pushInLayer'; +import { PushInScene } from '../../src/pushInScene'; +import { PushIn } from '../../src/pushin'; +import { LayerParams } from '../../src/types'; + +describe('getScaleValue', () => { + let layerMock: PushInLayer; + let layerMock2: PushInLayer; + let mockPushInLayer: PushInLayer; + + beforeEach(() => { + setupJSDOM(``); + layerMock = Object.create(PushInLayer.prototype); + layerMock['originalScale'] = 2; + layerMock['params'] = { + inpoint: 10, + speed: 2, + }; + + layerMock2 = Object.create(PushInLayer.prototype); + layerMock2['originalScale'] = 1; + layerMock2['params'] = { + inpoint: 150, + speed: 100, + }; + + mockPushInLayer = Object.create(PushInLayer.prototype); + mockPushInLayer['scene'] = Object.create(PushInScene.prototype); + mockPushInLayer['scene']['pushin'] = {scrollY:0}; + }); + + it('should return original scale if scroll position and inpoint are the same', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 10; + const result = mockPushInLayer['getScaleValue'](layerMock); + + expect(result).toEqual(2); + }); + + it('should reduce scale if scrollY is less than inpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 6; + const result = mockPushInLayer['getScaleValue'](layerMock); + + expect(result).toEqual(1.9992); + }); + + it('should increase scale if scrollY is greater than inpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 20; + const result = mockPushInLayer['getScaleValue'](layerMock); + + expect(result).toEqual(2.002); + }); + + it('should not return a negative number', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 1; + const result = mockPushInLayer['getScaleValue'](layerMock2); + + expect(result).toEqual(0); + }); +}); diff --git a/test/pushInLayer/getSpeed.spec.ts b/test/pushInLayer/getSpeed.spec.ts new file mode 100644 index 0000000..397503b --- /dev/null +++ b/test/pushInLayer/getSpeed.spec.ts @@ -0,0 +1,42 @@ +import { setupJSDOM } from '../setup'; +import { PushInLayer } from '../../src/pushInLayer'; +import { DEFAULT_SPEED } from '../../src/constants'; + +describe('getSpeed', () => { + let mockPushInLayer: PushInLayer; + + beforeEach(() => { + setupJSDOM(` + + +
+
+
Layer 0
+
Layer 1
+
Layer 2
+
+
+ + `); + + mockPushInLayer = Object.create(PushInLayer.prototype); + }); + + it('Should return 8 by default', () => { + const elem = document.querySelector('#layer-0'); + const result = mockPushInLayer['getSpeed'](elem); + expect(result).toEqual(DEFAULT_SPEED); + }); + + it('Should return integer value from data-pushin-speed attribute', () => { + const elem = document.querySelector('#layer-1'); + const result = mockPushInLayer['getSpeed'](elem); + expect(result).toEqual(50); + }); + + it('Should return default if NaN', () => { + const elem = document.querySelector('#layer-2'); + const result = mockPushInLayer['getSpeed'](elem); + expect(result).toEqual(DEFAULT_SPEED); + }); +}); diff --git a/test/pushInLayer/isActive.spec.ts b/test/pushInLayer/isActive.spec.ts new file mode 100644 index 0000000..db92cc7 --- /dev/null +++ b/test/pushInLayer/isActive.spec.ts @@ -0,0 +1,61 @@ +import { setupJSDOM } from '../setup'; +import { PushIn } from '../../src/pushin'; +import { PushInLayer } from '../../src/pushInLayer'; +import { PushInScene } from '../../src/pushInScene'; +import { LayerParams } from '../../src/types'; + +describe('isActive', () => { + let mockPushInLayer: PushInLayer; + + beforeEach(() => { + setupJSDOM(``); + mockPushInLayer = Object.create(PushInLayer.prototype); + + Object.assign( + mockPushInLayer, + { + 'params': { + inpoint: 10, + outpoint: 20 + }, + 'scene': Object.create(PushInScene.prototype), + }); + + mockPushInLayer['scene']['pushin'] = Object.create(PushIn.prototype); + }); + + it('should be true if screen top is greater than inpoint and less than outpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 15; + const result = mockPushInLayer['isActive'](); + + expect(result).toEqual(true); + }); + + it('should be true if screen top is equal to inpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 10; + const result = mockPushInLayer['isActive'](); + + expect(result).toEqual(true); + }); + + it('should be true if screen top is equal to outpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 20; + const result = mockPushInLayer['isActive'](); + + expect(result).toEqual(true); + }); + + it('should be false if screen top is less than inpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 5; + const result = mockPushInLayer['isActive'](); + + expect(result).toEqual(false); + }); + + it('should be false if screen top is greater than outpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 25; + const result = mockPushInLayer['isActive'](); + + expect(result).toEqual(false); + }); +}); diff --git a/test/pushInLayer/setLayerStyle.spec.ts b/test/pushInLayer/setLayerStyle.spec.ts new file mode 100644 index 0000000..d43dc2a --- /dev/null +++ b/test/pushInLayer/setLayerStyle.spec.ts @@ -0,0 +1,150 @@ +import { setupJSDOM } from '../setup'; +import { PushInLayer } from '../../src/pushInLayer'; +import { PushIn } from '../../src/pushin'; +import { PushInScene } from '../../src/pushInScene'; +import { LayerParams } from '../../src/types'; + +describe('setLayerStyle', () => { + let mockPushInLayer: PushInLayer; + let element: HTMLElement; + + beforeEach(() => { + setupJSDOM(` + + +
+ Lorem Ipsum +
+ + `); + + element = document.querySelector('.pushin-layer'); + + const mockScene = Object.create(PushInScene.prototype); + Object.assign( + mockScene, + { + transitionLength: 200, + } + ); + + mockPushInLayer = Object.create(PushInLayer.prototype); + Object.assign( + mockPushInLayer, + { + element: document.querySelector('.pushin-layer'), + index: 0, + 'params': { + inpoint: 200, + outpoint: 500, + }, + 'scene': mockScene, + }); + + const mockPushIn = Object.create(PushIn.prototype); + Object.assign( + mockPushIn, + { + scrollY: 0, + } + ); + + Object.assign( + mockPushInLayer['scene'], + { + pushin: mockPushIn, + layers: [ + Object.create(PushInLayer.prototype), + Object.create(PushInLayer.prototype), + Object.create(PushInLayer.prototype) + ], + } + ); + + // stub methods + Object.assign( + mockPushInLayer, + { + isActive: () => true, + setScale: () => null, + getScaleValue: () => null, + } + ); + }); + + it('should set opacity to 1 if its the first layer and the scroll position is before its inpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 10; + mockPushInLayer['setLayerStyle'](); + const result = element.style.opacity; + + expect(result).toEqual('1'); + }); + + it('should set opacity to 1 if its the first layer and it is active', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 205; + mockPushInLayer['setLayerStyle'](); + const result = element.style.opacity; + + expect(result).toEqual('1'); + }); + + it('should set opacity to 1 if its the last layer and the scroll position is after its outpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 600; + mockPushInLayer['index'] = 2; + mockPushInLayer['setLayerStyle'](); + + const result = element.style.opacity; + + expect(result).toEqual('1'); + }); + + it('should set opacity to 1 if its the last layer and it is active', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 450; + mockPushInLayer['index'] = 2; + mockPushInLayer['setLayerStyle'](); + + const result = element.style.opacity; + + expect(result).toEqual('1'); + }); + + it('should set opacity to 0 if its a middle layer and scroll position is exactly equal to its inpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 200; + mockPushInLayer['index'] = 1; + mockPushInLayer['setLayerStyle'](); + + const result = element.style.opacity; + + expect(result).toEqual('0'); + }); + + it('should set opacity to 0.5 if its a middle layer and scroll position is 100px from its inpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 300; + mockPushInLayer['index'] = 1; + mockPushInLayer['setLayerStyle'](); + + const result = element.style.opacity; + + expect(result).toEqual('0.5'); + }); + + it('should set opacity to 0 if its a middle layer and scroll position is exactly equal to its outpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 500; + mockPushInLayer['index'] = 1; + mockPushInLayer['setLayerStyle'](); + + const result = element.style.opacity; + + expect(result).toEqual('0'); + }); + + it('should set opacity to 0.5 if its a middle layer and scroll position is 100px from its outpoint', () => { + mockPushInLayer['scene']['pushin']['scrollY'] = 400; + mockPushInLayer['index'] = 1; + mockPushInLayer['setLayerStyle'](); + + const result = element.style.opacity; + + expect(result).toEqual('0.5'); + }); +}); diff --git a/test/setScale.spec.ts b/test/pushInLayer/setScale.spec.ts similarity index 58% rename from test/setScale.spec.ts rename to test/pushInLayer/setScale.spec.ts index 4890bad..2f49250 100644 --- a/test/setScale.spec.ts +++ b/test/pushInLayer/setScale.spec.ts @@ -1,5 +1,5 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; +import { setupJSDOM } from '../setup'; +import { PushInLayer } from '../../src/pushInLayer'; describe('setScale', () => { beforeEach(() => { @@ -12,18 +12,10 @@ describe('setScale', () => { }); it('should set element scale value', () => { - const instance = new PushIn(null); - + const mockPushInLayer = Object.create(PushInLayer.prototype); const element = document.querySelector('.foo'); - - instance['setScale'](element, 10); - + mockPushInLayer['setScale'](element, 10); const result = element.style.transform; - - try { - expect(result).toEqual('scale(10)'); - } finally { - instance.destroy(); - } + expect(result).toEqual('scale(10)'); }); }); diff --git a/test/setZIndex.spec.ts b/test/pushInLayer/setZIndex.spec.ts similarity index 58% rename from test/setZIndex.spec.ts rename to test/pushInLayer/setZIndex.spec.ts index a48c86d..6ed960e 100644 --- a/test/setZIndex.spec.ts +++ b/test/pushInLayer/setZIndex.spec.ts @@ -1,8 +1,8 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; +import { setupJSDOM } from '../setup'; +import { PushInLayer } from '../../src/pushInLayer'; describe('setZIndex', () => { - let pushIn: PushIn; + let mockPushInLayer: PushInLayer; beforeEach(() => { setupJSDOM(` @@ -18,24 +18,14 @@ describe('setZIndex', () => { `); - const container = document.querySelector('.pushin'); - pushIn = new PushIn(container); + mockPushInLayer = Object.create(PushInLayer.prototype); + mockPushInLayer['element'] = document.querySelector('#layer-1'); + mockPushInLayer['index'] = 1; }); - afterEach(() => pushIn.destroy()); - it('Should return the difference between the total number of layers and the current layer index', () => { - const mockLayer: any = { - element: { - style: { - zIndex: null, - }, - }, - index: 1, - }; - - pushIn['setZIndex'](mockLayer, 10); - const result = mockLayer.element.style.zIndex; - expect(result).toEqual('9'); + mockPushInLayer['setZIndex'](3); + const result = mockPushInLayer['element'].style.zIndex; + expect(result).toEqual('2'); }); }); diff --git a/test/getBreakpointIndex.spec.ts b/test/pushInScene/getBreakpointIndex.spec.ts similarity index 61% rename from test/getBreakpointIndex.spec.ts rename to test/pushInScene/getBreakpointIndex.spec.ts index b61da68..d137db4 100644 --- a/test/getBreakpointIndex.spec.ts +++ b/test/pushInScene/getBreakpointIndex.spec.ts @@ -1,9 +1,7 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; +import { setupJSDOM } from '../setup'; +import { PushInScene } from '../../src/pushInScene'; describe('getBreakpointIndex', () => { - let pushIn: PushIn; - beforeEach(() => { setupJSDOM(` @@ -13,23 +11,17 @@ describe('getBreakpointIndex', () => { `); - const container = document.querySelector('.pushin'); - pushIn = new PushIn(container); - pushIn['sceneOptions'].breakpoints = [0, 768, 1440, 1920]; }); - afterEach(() => pushIn.destroy()); - it('Should return 0 by default', () => { - pushIn['sceneOptions'].breakpoints = []; - const result = pushIn['getBreakpointIndex'](); + const result = PushInScene.prototype.getBreakpointIndex([]); expect(result).toEqual(0); }); it('Should return the index of the nearest breakpoint that is less than current window width', () => { window.innerWidth = 800; - const result = pushIn['getBreakpointIndex'](); + const result = PushInScene.prototype.getBreakpointIndex([0, 768, 1440, 1920]); expect(result).toEqual(1); }); }); diff --git a/test/pushInScene/getLayers.spec.ts b/test/pushInScene/getLayers.spec.ts new file mode 100644 index 0000000..485ce45 --- /dev/null +++ b/test/pushInScene/getLayers.spec.ts @@ -0,0 +1,42 @@ +import { setupJSDOM } from '../setup'; +import { PushInScene } from '../../src/pushInScene'; +import { PushInLayer } from '../../src/pushInLayer'; +jest.mock('../../src/pushInLayer'); + +describe('getLayers', () => { + let mockPushInScene: PushInScene; + let layers: HTMLElement[]; + + beforeEach(() => { + (PushInLayer as jest.Mock).mockClear(); + setupJSDOM(` + + +
+
+
Layer 0
+
Layer 1
+
Layer 2
+
Layer 3
+
+
+ + `); + + mockPushInScene = Object.create(PushInScene.prototype); + mockPushInScene['container'] = document.querySelector('.pushin-scene'); + mockPushInScene['layers'] = []; + + layers = [ ...document.querySelectorAll('.pushin-layer')]; + }); + + it('Should set the layers property to contain all .pushin-layer elements', () => { + mockPushInScene['getLayers'](); + expect(mockPushInScene['layers'].length).toEqual(layers.length); + }); + + it('Should create pushInLayer with correct arguments', () => { + mockPushInScene['getLayers'](); + expect(PushInLayer).toHaveBeenCalledWith(layers[1], 1, mockPushInScene, {}); + }); +}); diff --git a/test/pushInScene/setBreakpoints.spec.ts b/test/pushInScene/setBreakpoints.spec.ts new file mode 100644 index 0000000..0229a57 --- /dev/null +++ b/test/pushInScene/setBreakpoints.spec.ts @@ -0,0 +1,41 @@ +import { setupJSDOM } from '../setup'; +import { PushInScene } from '../../src/pushInScene'; +import { SceneOptions } from '../../src/types'; +import { PUSH_IN_DEFAULT_BREAKPOINTS } from '../../src/constants'; + +describe('setBreakpoints', () => { + let mockPushInScene: PushInScene; + + beforeEach(() => { + setupJSDOM(` + + +
+
+
+ + `); + + mockPushInScene = Object.create(PushInScene.prototype); + mockPushInScene['container'] = document.querySelector('.pushin-scene'); + mockPushInScene['options'] = { + breakpoints: [], + }; + }); + + it('Should set the default breakpoints', () => { + mockPushInScene['setBreakpoints'](); + const result = mockPushInScene['options'].breakpoints; + console.log(PUSH_IN_DEFAULT_BREAKPOINTS); + const expected = [0, ...PUSH_IN_DEFAULT_BREAKPOINTS]; + expect(result).toEqual(expected); + }); + + it('Should set the breakpoints provided by data-attributes', () => { + mockPushInScene['container'].setAttribute('data-pushin-breakpoints', '1,2,3'); + mockPushInScene['setBreakpoints'](); + const result = mockPushInScene['options'].breakpoints; + const expected = [0, 1, 2, 3]; + expect(result).toEqual(expected); + }); +}); diff --git a/test/setBreakpoints.spec.ts b/test/setBreakpoints.spec.ts deleted file mode 100644 index ff9d9c0..0000000 --- a/test/setBreakpoints.spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; - -describe('setBreakpoints', () => { - let pushIn: PushIn; - - beforeEach(() => { - setupJSDOM(` - - -
-
-
- - `); - - const container = document.querySelector('.pushin'); - pushIn = new PushIn(container); - const scene = document.querySelector('.pushin-scene'); - pushIn['scene'] = scene; - }); - - afterEach(() => pushIn.destroy()); - - it('Should set the default breakpoints', () => { - pushIn['setBreakpoints'](); - const result = pushIn['sceneOptions'].breakpoints; - const expected = [0, 768, 1440, 1920]; - expect(result).toEqual(expected); - }); - - it('Should set the breakpoints provided by data-attributes', () => { - pushIn['scene'].setAttribute('data-pushin-breakpoints', '1,2,3'); - pushIn['setBreakpoints'](); - const result = pushIn['sceneOptions'].breakpoints; - const expected = [0, 1, 2, 3]; - expect(result).toEqual(expected); - }); -}); diff --git a/test/setLayerStyle.spec.ts b/test/setLayerStyle.spec.ts deleted file mode 100644 index 8927c23..0000000 --- a/test/setLayerStyle.spec.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; - -describe('setLayerStyle', () => { - let pushIn: PushIn; - - beforeEach(() => { - setupJSDOM(` - - -
- Lorem Ipsum -
-
- Dolor sit amet -
-
- Hello World -
- - `); - - const layers = [ - { - element: document.querySelector('.demo-layer-1'), - index: 0, - originalScale: 1, - params: { - inpoint: 200, - outpoint: 500, - speed: 8, - }, - }, - { - element: document.querySelector('.demo-layer-2'), - index: 1, - originalScale: 1, - params: { - inpoint: 500, - outpoint: 800, - speed: 8, - }, - }, - { - element: document.querySelector('.demo-layer-3'), - index: 2, - originalScale: 1, - params: { - inpoint: 800, - outpoint: 1200, - speed: 8, - }, - }, - ]; - - pushIn = new PushIn(null); - Object.assign(pushIn, { - isActive: () => true, - layers, - transitionLength: 200, - }); - }); - - afterEach(() => pushIn.destroy()); - - it('should set opacity to 1 if its the first layer and the scroll position is before its inpoint', () => { - pushIn['scrollY'] = 10; - const element = document.querySelector('.demo-layer-1'); - pushIn['setLayerStyle'](pushIn['layers'][0]); - const result = element.style.opacity; - - expect(result).toEqual('1'); - }); - - it('should set opacity to 1 if its the first layer and it is active', () => { - pushIn['scrollY'] = 205; - const element = document.querySelector('.demo-layer-1'); - pushIn['setLayerStyle'](pushIn['layers'][0]); - const result = element.style.opacity; - - expect(result).toEqual('1'); - }); - - it('should set opacity to 1 if its the last layer and the scroll position is after its outpoint', () => { - pushIn['scrollY'] = 1300; - const element = document.querySelector('.demo-layer-3'); - pushIn['setLayerStyle'](pushIn['layers'][2]); - - const result = element.style.opacity; - - expect(result).toEqual('1'); - }); - - it('should set opacity to 1 if its the last layer and it is active', () => { - pushIn['scrollY'] = 1195; - const element = document.querySelector('.demo-layer-3'); - pushIn['setLayerStyle'](pushIn['layers'][2]); - - const result = element.style.opacity; - - expect(result).toEqual('1'); - }); - - it('should set opacity to 0 if its a middle layer and scroll position is exactly equal to its inpoint', () => { - pushIn['scrollY'] = 500; - const element = document.querySelector('.demo-layer-2'); - - pushIn['setLayerStyle'](pushIn['layers'][1]); - - const result = element.style.opacity; - - expect(result).toEqual('0'); - }); - - it('should set opacity to 0.5 if its a middle layer and scroll position is 100px from its inpoint', () => { - pushIn['scrollY'] = 600; - const element = document.querySelector('.demo-layer-2'); - - pushIn['setLayerStyle'](pushIn['layers'][1]); - - const result = element.style.opacity; - - expect(result).toEqual('0.5'); - }); - - it('should set opacity to 0 if its a middle layer and scroll position is exactly equal to its outpoint', () => { - pushIn['scrollY'] = 800; - const element = document.querySelector('.demo-layer-2'); - - pushIn['setLayerStyle'](pushIn['layers'][1]); - - const result = element.style.opacity; - - expect(result).toEqual('0'); - }); - - it('should set opacity to 0.5 if its a middle layer and scroll position is 100px from its outpoint', () => { - pushIn['scrollY'] = 700; - const element = document.querySelector('.demo-layer-2'); - - pushIn['setLayerStyle'](pushIn['layers'][1]); - - const result = element.style.opacity; - - expect(result).toEqual('0.5'); - }); -}); diff --git a/test/setScrollLength.spec.ts b/test/setScrollLength.spec.ts deleted file mode 100644 index 55d7756..0000000 --- a/test/setScrollLength.spec.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { setupJSDOM } from './setup'; -import { PushIn } from '../src/pushin'; - -describe('setScrollLength', () => { - let pushIn: PushIn; - - beforeEach(() => { - setupJSDOM(` - - -
- - `); - - const container = document.querySelector('.pushin'); - pushIn = new PushIn(container); - - (pushIn as any).layers = [1, 2, 3]; - pushIn['speedDelta'] = 100; - pushIn['layerDepth'] = 100; - pushIn['transitionLength'] = 100; - }); - - afterEach(() => pushIn.destroy()); - - it('Should set the container height to its original value if it is higher than calculated value', () => { - pushIn['setScrollLength'](); - const result = pushIn['container'].style.height; - expect(result).toEqual('500px'); - }); - - it('Should calculate container height based on layerDepth and transitionLength properties', () => { - pushIn['speedDelta'] = 0; - pushIn['layerDepth'] = 200; - pushIn['transitionLength'] = 200; - - pushIn['setScrollLength'](); - const result = pushIn['container'].style.height; - expect(result).toEqual('1200px'); - }); - - it('Should reduce container height to account for overlapping transition length', () => { - pushIn['speedDelta'] = 100; - pushIn['layerDepth'] = 200; - pushIn['transitionLength'] = 200; - - pushIn['setScrollLength'](); - const result = pushIn['container'].style.height; - expect(result).toEqual('1000px'); - }); -});