continue re-design
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
import classNames from "classnames";
|
||||
|
||||
export function cn(...classes: classNames.ArgumentArray) {
|
||||
return classNames(...classes);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { debounce } from "lodash-es";
|
||||
|
||||
export default (canvas: HTMLCanvasElement) => {
|
||||
const { width, height } = canvas.getBoundingClientRect();
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
|
||||
canvas.style.width = `${width}px`;
|
||||
canvas.style.height = `${height}px`;
|
||||
|
||||
const upscaleCanvas = () => {
|
||||
const scale = window.visualViewport?.scale || 1;
|
||||
const dpr = (window.devicePixelRatio || 1) * scale;
|
||||
|
||||
canvas.width = width * dpr;
|
||||
canvas.height = height * dpr;
|
||||
|
||||
ctx.scale(dpr, dpr);
|
||||
|
||||
canvas.dispatchEvent(new Event("resize"));
|
||||
};
|
||||
|
||||
upscaleCanvas();
|
||||
|
||||
const handleResize = debounce(upscaleCanvas, 500);
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
window.visualViewport?.addEventListener("resize", handleResize);
|
||||
|
||||
return ctx;
|
||||
};
|
||||
@@ -0,0 +1,130 @@
|
||||
export function setTimeoutOnVisible({
|
||||
element,
|
||||
callback,
|
||||
timeout,
|
||||
threshold = 0.01,
|
||||
}: {
|
||||
element?: HTMLElement;
|
||||
callback: () => void;
|
||||
timeout: number;
|
||||
threshold?: number;
|
||||
}) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
let timeoutId: NodeJS.Timeout | null = null;
|
||||
let finished = false;
|
||||
|
||||
// Check if element is already visible at the beginning
|
||||
const rect = element.getBoundingClientRect();
|
||||
const isVisible = rect.top < window.innerHeight && rect.bottom > 0;
|
||||
|
||||
const setupTimeout = () => {
|
||||
if (finished) return;
|
||||
|
||||
timeoutId = setTimeout(() => {
|
||||
if (finished) return;
|
||||
|
||||
callback();
|
||||
timeoutId = null;
|
||||
finished = true;
|
||||
}, timeout);
|
||||
};
|
||||
|
||||
if (isVisible && !timeoutId) setupTimeout();
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
// Element is visible, start the timeout
|
||||
if (!timeoutId) {
|
||||
setupTimeout();
|
||||
observer.disconnect();
|
||||
}
|
||||
} else {
|
||||
// Element is no longer visible, clear the timeout
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold },
|
||||
);
|
||||
|
||||
observer.observe(element);
|
||||
|
||||
// Return a cleanup function
|
||||
return () => {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
||||
observer.disconnect();
|
||||
};
|
||||
}
|
||||
|
||||
export function setIntervalOnVisible({
|
||||
element,
|
||||
callback,
|
||||
interval,
|
||||
threshold = 0.01,
|
||||
}: {
|
||||
element?: HTMLElement | null;
|
||||
callback: () => void;
|
||||
interval: number;
|
||||
threshold?: number;
|
||||
}) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
let intervalId: NodeJS.Timeout | null = null;
|
||||
|
||||
// Check if element is already visible at the beginning
|
||||
const rect = element.getBoundingClientRect();
|
||||
const isVisible = rect.top < window.innerHeight && rect.bottom > 0;
|
||||
|
||||
const setupInterval = () => {
|
||||
if (!intervalId) {
|
||||
intervalId = setInterval(callback, interval);
|
||||
}
|
||||
};
|
||||
|
||||
const clearIntervalIfExists = () => {
|
||||
if (intervalId) {
|
||||
clearInterval(intervalId);
|
||||
intervalId = null;
|
||||
}
|
||||
};
|
||||
|
||||
if (isVisible) setupInterval();
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
// Element is visible, start the interval
|
||||
setupInterval();
|
||||
} else {
|
||||
// Element is no longer visible, clear the interval
|
||||
clearIntervalIfExists();
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold },
|
||||
);
|
||||
|
||||
observer.observe(element);
|
||||
|
||||
// Return a cleanup function
|
||||
return () => {
|
||||
clearIntervalIfExists();
|
||||
observer.disconnect();
|
||||
};
|
||||
}
|
||||
|
||||
export default setTimeoutOnVisible;
|
||||
@@ -0,0 +1,2 @@
|
||||
export const sleep = (ms: number) =>
|
||||
new Promise((resolve) => setTimeout(resolve, ms));
|
||||
Reference in New Issue
Block a user