UNPKG

@arwes/bgs

Version:

Futuristic Sci-Fi UI Web Framework

172 lines (171 loc) 6.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createBackgroundDots = void 0; const animated_1 = require("@arwes/animated"); const getDistanceFromOriginToCornerProgress_js_1 = require("./getDistanceFromOriginToCornerProgress.js"); const defaultProps = { color: '#777', type: 'box', distance: 30, size: 4, crossSize: 1, origin: 'center', originInverted: false, easing: animated_1.easing.inSine }; const createBackgroundDots = (props) => { const { canvas, animator } = props; const ctx = canvas.getContext('2d'); if (!ctx) { return { cancel: () => { } }; } const dpr = Math.min(window.devicePixelRatio || 2, 2); let transitionControl; let resizeObserver; let unsubscribe; const getSettings = () => ({ ...defaultProps, ...props.settingsRef.current }); const resize = () => { const { width, height } = canvas.getBoundingClientRect(); if (canvas.width !== width * dpr || canvas.height !== height * dpr) { canvas.width = width * dpr; canvas.height = height * dpr; } ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.scale(dpr, dpr); }; const draw = (isEntering, progress) => { if (!ctx) { return; } const { color, type, distance, size, crossSize, origin, originInverted } = getSettings(); const { width, height } = canvas; const xLength = 1 + Math.floor(width / distance); const yLength = 1 + Math.floor(height / distance); const xMargin = width % distance; const yMargin = height % distance; ctx.clearRect(0, 0, width, height); for (let xIndex = 0; xIndex < xLength; xIndex++) { const x = xMargin / 2 + xIndex * distance; for (let yIndex = 0; yIndex < yLength; yIndex++) { const y = yMargin / 2 + yIndex * distance; const distanceFromOriginProgress = (0, getDistanceFromOriginToCornerProgress_js_1.getDistanceFromOriginToCornerProgress)(width / dpr, height / dpr, x, y, origin); const distancePercentage = (isEntering && originInverted) || (!isEntering && !originInverted) ? 1 - distanceFromOriginProgress : distanceFromOriginProgress; const alphaProgress = progress / distancePercentage; const alpha = Math.max(0, Math.min(1, alphaProgress)); ctx.beginPath(); ctx.globalAlpha = isEntering ? alpha : 1 - alpha; if (type === 'circle') { ctx.arc(x, y, size, 0, 2 * Math.PI); } else if (type === 'cross') { const l = size / 2; const b = crossSize / 2; ctx.moveTo(x - l, y + b); ctx.lineTo(x - l, y - b); ctx.lineTo(x - b, y - b); ctx.lineTo(x - b, y - l); ctx.lineTo(x + b, y - l); ctx.lineTo(x + b, y - b); ctx.lineTo(x + l, y - b); ctx.lineTo(x + l, y + b); ctx.lineTo(x + b, y + b); ctx.lineTo(x + b, y + l); ctx.lineTo(x - b, y + l); ctx.lineTo(x - b, y + b); } else { ctx.rect(x - size / 2, y - size / 2, size, size); } ctx.fillStyle = color; ctx.fill(); ctx.closePath(); } } }; const setup = () => { canvas.style.opacity = '1'; if (typeof window !== 'undefined' && !resizeObserver) { resizeObserver = new window.ResizeObserver(() => { resize(); if (animator) { switch (animator.state) { case 'entered': { draw(true, 1); break; } } } else { draw(true, 1); } }); resizeObserver.observe(canvas); resize(); } }; const stop = () => { canvas.style.opacity = '0'; resizeObserver?.disconnect(); resizeObserver = undefined; transitionControl?.cancel(); transitionControl = undefined; }; const start = () => { if (!animator) { setup(); draw(true, 1); return; } unsubscribe = animator.subscribe((node) => { const settings = getSettings(); switch (node.state) { case 'entering': { setup(); transitionControl?.cancel(); transitionControl = (0, animated_1.createAnimation)({ duration: node.settings.duration.enter, easing: settings.easing, onUpdate(progress) { draw(true, progress); } }); break; } case 'entered': { setup(); transitionControl?.cancel(); draw(true, 1); break; } case 'exiting': { setup(); transitionControl?.cancel(); transitionControl = (0, animated_1.createAnimation)({ duration: node.settings.duration.exit, easing: settings.easing, onUpdate(progress) { draw(false, progress); } }); break; } case 'exited': { stop(); break; } } }); }; const cancel = () => { unsubscribe?.(); stop(); }; start(); return Object.freeze({ cancel }); }; exports.createBackgroundDots = createBackgroundDots;