feat: Improve cursor behavior and link hover animation

This commit is contained in:
Keisuke Hirata 2024-08-25 10:45:12 +09:00
parent 53fba96092
commit 02f0f318eb
2 changed files with 75 additions and 52 deletions

View File

@ -1,52 +1,52 @@
<script lang="ts">
import { onMount } from 'svelte';
import { onMount } from 'svelte';
let cursor: HTMLDivElement;
let cursor: HTMLDivElement;
type position = {
x: number;
y: number;
};
type position = {
x: number;
y: number;
};
let disabled = false;
let rawPosition: position = { x: 0, y: -100 };
let position: position = { x: 0, y: 0 };
let disabled = false;
let rawPosition: position = { x: 0, y: -100 };
let position: position = { x: 0, y: 0 };
onMount(() => {
window.addEventListener('mousemove', (e) => {
rawPosition = { x: e.clientX, y: e.clientY };
});
window.addEventListener('touchstart', (e) => {
cursor.style.display = 'none';
disabled = true;
});
const loop = () => {
if (disabled) return;
position.x += (rawPosition.x - position.x) / 12;
position.y += (rawPosition.y - position.y) / 12;
cursor.style.top = `${position.y}px`;
cursor.style.left = `${position.x}px`;
cursor.style.rotate = `rotate(${position.x}deg)`;
requestAnimationFrame(loop);
};
loop();
});
onMount(() => {
window.addEventListener('mousemove', (e) => {
rawPosition = { x: e.clientX, y: e.clientY };
});
window.addEventListener('touchstart', (e) => {
cursor.style.display = 'none';
disabled = true;
});
const loop = () => {
if (disabled) return;
position.x += (rawPosition.x - position.x) / 12;
position.y += (rawPosition.y - position.y) / 12;
cursor.style.top = `${position.y}px`;
cursor.style.left = `${position.x}px`;
cursor.style.rotate = `rotate(${position.x}deg)`;
requestAnimationFrame(loop);
};
loop();
});
</script>
<div class="cursor" bind:this={cursor} />
<div class="cursor" bind:this={cursor}></div>
<style lang="scss">
.cursor {
position: fixed;
top: -100px;
left: 0px;
width: 20px;
height: 20px;
border-radius: 50%;
background: #ffffff;
pointer-events: none;
z-index: 999;
mix-blend-mode: difference;
transform: translate(-50%, -50%);
}
.cursor {
position: fixed;
top: -100px;
left: 0px;
width: 20px;
height: 20px;
border-radius: 50%;
background: #ffffff;
pointer-events: none;
z-index: 999;
mix-blend-mode: difference;
transform: translate(-50%, -50%);
}
</style>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import type { PageData } from './$types';
// import Cursor from '$lib/components/cursor.svelte';
import Cursor from '$lib/components/cursor.svelte';
import Footer from '$lib/components/footer.svelte';
import FormattedDate from '$lib/components/formatted_date.svelte';
@ -90,7 +90,14 @@
<ul>
{#each data.recent as post}
<li>
<a href={post.link}>{post.title} - {post.date}</a>
<a
href={post.link}
on:mouseenter={(e) =>
(e.target as HTMLAnchorElement).style.setProperty(
'--mouse-position',
`${e.offsetX}px`
)}>{post.title}</a
>
</li>
{/each}
</ul>
@ -107,6 +114,7 @@
</div>
<Footer />
</main>
<Cursor />
</div>
<style lang="scss">
@ -121,7 +129,7 @@
width: 100vw;
height: 100dvh;
backdrop-filter: blur(2px);
overflow: auto;
overflow: hidden;
}
.controls {
position: fixed;
@ -142,6 +150,8 @@
color: white;
display: flex;
flex-direction: column;
overflow-x: hidden;
overflow-y: auto;
> div {
margin: 10px 0;
}
@ -250,6 +260,26 @@
}
a {
backdrop-filter: blur(10px);
text-decoration: none;
border-bottom: 1px solid var(--line-primary);
color: white;
box-sizing: border-box;
--mouse-position: 0;
&::after {
content: ' ';
position: absolute;
bottom: 0;
left: var(--mouse-position);
right: calc(100% - var(--mouse-position));
height: 1px;
background-color: white;
transition: 0.2s ease-in-out;
transition-property: left right;
}
&:hover::after {
left: 0px;
right: 0px;
}
}
button {
font-size: 1rem;
@ -285,13 +315,6 @@
}
}
a {
text-decoration: none;
border-bottom: 1px solid var(--line-primary);
color: white;
box-sizing: border-box;
}
@media (max-width: 1000px) {
main {
width: 100%;