too many changes, forgot to commit smh

This commit is contained in:
2025-06-29 19:35:32 +02:00
parent 96a8604d4b
commit 60e3102257
17 changed files with 633 additions and 279 deletions

View File

@@ -0,0 +1,176 @@
<script lang="ts">
import cursor_default from '$assets/cursor.png';
import cursor_additive from '$assets/cursor-additive.png';
import { animate } from 'animejs';
import { onMount } from 'svelte';
let mouseX = $state(0);
let mouseY = $state(0);
let rotation = $state(0);
let isMouseDown = $state(false);
let isHoveringInteractive = $state(false);
let dragStartX = $state(0);
let dragStartY = $state(0);
let degrees = $state(0);
let applyRotation = $state(false);
function isInteractive(el: Element | null): boolean {
while (el) {
const tag = el.tagName.toLowerCase();
const role = el.getAttribute('role');
const computed = getComputedStyle(el);
if (
['button', 'a', 'input', 'select', 'textarea', 'label', 'option'].includes(tag) ||
(role && ['button', 'link', 'checkbox', 'combobox'].includes(role)) ||
computed.cursor === 'pointer'
) {
return true;
}
el = el.parentElement;
}
return false;
}
const handleMouseMove = (e: MouseEvent) => {
mouseX = e.clientX;
mouseY = e.clientY;
const deltaX = e.pageX - window.pageXOffset - dragStartX;
const deltaY = e.pageY - window.pageYOffset - dragStartY;
if (!applyRotation && isMouseDown && deltaX * deltaX + deltaY * deltaY > 30 * 100) {
applyRotation = true;
}
let newDegrees = (Math.atan2(-deltaX, deltaY) * 180) / Math.PI + 24.3;
let diff = (newDegrees - degrees) % 360;
if (diff < -180) diff += 360;
if (diff > 180) diff -= 360;
if (isMouseDown && applyRotation) {
degrees += diff;
} else {
degrees = 0;
}
const el = document.elementFromPoint(mouseX, mouseY);
isHoveringInteractive = isInteractive(el);
if (!isMouseDown) {
if (isHoveringInteractive) {
animate(cursorAdditive, {
opacity: 1,
duration: 800,
ease: (t: number) => (t - 1) ** 5 + 1,
});
} else {
animate(cursorAdditive, {
opacity: 0,
duration: 800,
ease: (t: number) => (t - 1) ** 5 + 1,
});
}
}
animate(cursor, {
duration: 180,
translateX: mouseX,
translateY: mouseY - 50,
ease: (t: number) => (t - 1) ** 3 + 1,
});
animate(cursor, {
duration: 1500,
rotate: degrees,
transformOrigin: '0px 0px 0',
ease: (t: number) => Math.pow(2, -10 * t) * Math.sin((t - 0.075) * 20.94) + 1 - 0.0005 * t,
});
};
const handleMouseDown = (event: MouseEvent) => {
dragStartX = event.clientX;
dragStartY = event.clientY;
isMouseDown = true;
animate(cursorInner, {
scale: 0.9,
duration: 800,
ease: (t: number) => (t - 1) ** 3 + 1,
});
animate(cursorAdditive, {
opacity: 1,
scale: 0.9,
duration: 800,
ease: (t: number) => (t - 1) ** 5 + 1,
});
};
const handleMouseUp = () => {
rotation = 0;
isMouseDown = false;
applyRotation = false;
animate(cursorInner, {
scale: 1,
duration: 500,
ease: (t: number) => Math.pow(2, -10 * t) * Math.sin((t - 0.075) * 20.94) + 1 - 0.0005 * t,
});
animate(cursorAdditive, {
opacity: 0,
duration: 500,
scale: 1,
ease: (t: number) => (t - 1) ** 5 + 1,
});
};
let cursor: HTMLElement;
let cursorInner: HTMLDivElement;
let cursorAdditive: HTMLImageElement;
/* onMount(() => {
const processMouseMove = (e: MouseEvent) =>
handleMouseMove(e.clientX, e.clientY, e.pageX, e.pageY);
document.addEventListener('pointermove', processMouseMove);
document.addEventListener('pointerdown', handleMouseDown);
document.addEventListener('pointerup', handleMouseUp);
return () => {
document.removeEventListener('pointermove', processMouseMove);
document.removeEventListener('pointerdown', handleMouseDown);
document.removeEventListener('pointerup', handleMouseUp);
};
}); */
</script>
<svelte:window
onmousemove={handleMouseMove}
onmousedown={handleMouseDown}
onmouseup={handleMouseUp}
/>
<div class="h-7 w-7 fixed pointer-events-none z-[99999]" bind:this={cursor}>
<div class="relative">
<img class="absolute top-0 left-0" src={cursor_default} bind:this={cursorInner} alt="cursor" />
<img
class="absolute top-0 left-0 opacity-0"
src={cursor_additive}
bind:this={cursorAdditive}
alt="cursor"
/>
</div>
</div>
<style>
:global(html),
:global(body),
:global(*),
:global(*:hover),
:global(button),
:global(a),
:global(input),
:global(select),
:global(textarea) {
cursor: none !important;
}
</style>