57 lines
1.3 KiB
Svelte
57 lines
1.3 KiB
Svelte
<script lang="ts">
|
|
let cardElement: HTMLDivElement
|
|
let isHovering = false
|
|
let transform = ''
|
|
|
|
function handleMouseMove(e: MouseEvent) {
|
|
if (!cardElement || !isHovering) return
|
|
|
|
const rect = cardElement.getBoundingClientRect()
|
|
const x = e.clientX - rect.left
|
|
const y = e.clientY - rect.top
|
|
|
|
const centerX = rect.width / 2
|
|
const centerY = rect.height / 2
|
|
|
|
const rotateX = ((y - centerY) / centerY) * -5 // -4 to 4 degrees
|
|
const rotateY = ((x - centerX) / centerX) * 5 // -4 to 4 degrees
|
|
|
|
transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.014, 1.014, 1.014)`
|
|
}
|
|
|
|
function handleMouseEnter() {
|
|
isHovering = true
|
|
}
|
|
|
|
function handleMouseLeave() {
|
|
isHovering = false
|
|
transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)'
|
|
}
|
|
</script>
|
|
|
|
<div
|
|
class="tilt-card"
|
|
bind:this={cardElement}
|
|
on:mousemove={handleMouseMove}
|
|
on:mouseenter={handleMouseEnter}
|
|
on:mouseleave={handleMouseLeave}
|
|
style="transform: {transform};"
|
|
>
|
|
<slot />
|
|
</div>
|
|
|
|
<style lang="scss">
|
|
.tilt-card {
|
|
transition:
|
|
transform 0.15s ease-out,
|
|
box-shadow 0.15s ease-out;
|
|
transform-style: preserve-3d;
|
|
will-change: transform;
|
|
cursor: pointer;
|
|
border-radius: $card-corner-radius;
|
|
|
|
&:hover {
|
|
box-shadow: $card-shadow-hover;
|
|
}
|
|
}
|
|
</style>
|