UNPKG

@naturalcycles/js-lib

Version:

Standard library for universal (browser + Node.js) javascript

136 lines (135 loc) 4.09 kB
// Modified version of topbar: // http://buunguyen.github.io/topbar // oxlint-disable const browser = typeof window !== 'undefined'; let canvas; let progressTimerId; let fadeTimerId; let currentProgress; let showing; const addEvent = (elem, type, handler) => { if (elem.addEventListener) elem.addEventListener(type, handler, false); else if (elem.attachEvent) elem.attachEvent('on' + type, handler); else elem['on' + type] = handler; }; const options = { autoRun: true, barThickness: 5, barColors: { '0': 'rgba(26, 188, 156, .9)', '.25': 'rgba(52, 152, 219, .9)', '.50': 'rgba(241, 196, 15, .9)', '.75': 'rgba(230, 126, 34, .9)', '1.0': 'rgba(211, 84, 0, .9)', }, shadowBlur: 10, shadowColor: 'rgba(0, 0, 0, .6)', }; const repaint = () => { canvas.width = window.innerWidth; canvas.height = options.barThickness * 5; // need space for shadow const ctx = canvas.getContext('2d'); ctx.shadowBlur = options.shadowBlur; ctx.shadowColor = options.shadowColor; const lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0); for (const stop in options.barColors) { // @ts-expect-error lineGradient.addColorStop(stop, options.barColors[stop]); } ctx.lineWidth = options.barThickness; ctx.beginPath(); ctx.moveTo(0, options.barThickness / 2); ctx.lineTo(Math.ceil(currentProgress * canvas.width), options.barThickness / 2); ctx.strokeStyle = lineGradient; ctx.stroke(); }; const createCanvas = () => { canvas = document.createElement('canvas'); canvas.ariaHidden = 'true'; const style = canvas.style; style.position = 'fixed'; style.top = style.left = style.right = style.margin = style.padding = 0; style.zIndex = 100001; style.display = 'none'; document.body.appendChild(canvas); addEvent(window, 'resize', repaint); }; export const topbar = { config(opts) { for (const key in opts) { if (options.hasOwnProperty(key)) { // @ts-expect-error options[key] = opts[key]; } } }, set(show, opts) { if (show) { topbar.show(opts); } else { topbar.hide(); } }, show(opts) { if (!browser) return; // ssr protection if (opts) topbar.config(opts); if (showing) return; showing = true; if (fadeTimerId !== null) { window.cancelAnimationFrame(fadeTimerId); } if (!canvas) createCanvas(); canvas.style.opacity = 1; canvas.style.display = 'block'; topbar.progress(0); if (options.autoRun) { ; (function loop() { progressTimerId = window.requestAnimationFrame(loop); topbar.progress('+' + 0.05 * (1 - Math.sqrt(currentProgress)) ** 2); })(); } }, progress(to) { if (!browser) return; // ssr protection if (typeof to === 'undefined') { return currentProgress; } if (typeof to === 'string') { to = (to.includes('+') || to.includes('-') ? currentProgress : 0) + parseFloat(to); } currentProgress = to > 1 ? 1 : to; repaint(); return currentProgress; }, hide() { if (!showing || !browser) return; showing = false; if (progressTimerId != null) { window.cancelAnimationFrame(progressTimerId); progressTimerId = null; } ; (function loop() { if (topbar.progress('+.1') >= 1) { canvas.style.opacity -= 0.05; if (canvas.style.opacity <= 0.05) { canvas.style.display = 'none'; fadeTimerId = null; return; } } fadeTimerId = window.requestAnimationFrame(loop); })(); }, };