This commit is contained in:
2025-02-14 18:05:52 -05:00
parent ef372f34b2
commit 80cba8ded1
4 changed files with 119 additions and 7 deletions
+3 -4
View File
@@ -4,10 +4,9 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Svelte + TS</title> <title>Rana</title>
</head> </head>
<body> <body id="app">
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body> </body>
<script type="module" src="/src/main.ts"></script>
</html> </html>
+110 -1
View File
@@ -1,10 +1,119 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte";
import rana from "./rana.png"
const duration = 0.3
// Pos: % from 0 to 1 on the axis perpendicular to the direction
let pos = 0.5
// top | bottom | left | right
const directions = ["top", "bottom", "left", "right"]
let direction = "bottom"
// 0: idle, 1: entering, 2: leaving
let state = 0
// Reference to the image element
let divEl: HTMLDivElement
let imgEl: HTMLImageElement
function getInitTrans() {
const dirC = direction === 'top' || direction === 'bottom' ? 'Y' : 'X'
const dirN = direction === 'top' || direction === 'left' ? '-' : ''
const dirV = direction === 'top' || direction === 'bottom' ? '300px' : '200px'
return `translate${dirC}(${dirN}${dirV})`
}
const sleep = (s: number) => new Promise(resolve => setTimeout(resolve, s * 1000))
async function enter() {
console.log("Entering")
state = 1
divEl.style.transform = "translate(0, 0)"
await sleep(duration)
state = 0
}
async function onHover() {
if (state !== 0 || divEl === undefined) return
// Animate the image to leave
state = 2
divEl.style.transform = getInitTrans()
await sleep(duration)
// Randomize the direction
state = 1
direction = directions[Math.floor(Math.random() * directions.length)]
console.log("New direction:", direction)
await divStyles()
}
async function divStyles() {
if (divEl === undefined) return
let obj: any = {}
obj.transform = getInitTrans()
obj[direction] = '-50px'
for (let dir of directions) {
if (dir !== direction) obj[dir] = 'unset'
}
let perpendicular = direction === 'bottom' || direction === 'top' ? 'left' : 'top'
obj[perpendicular] = `calc(${pos * 100}% - 100px)`
divEl.style.transition = `none`
divEl.style.cssText = Object.keys(obj).map(key => `${key}: ${obj[key]}`).join('; ')
await sleep(0.1)
divEl.style.transition = `transform ${duration}s`
imgStyles()
enter()
}
function imgStyles() {
if (imgEl === undefined) return
let obj: any = {}
obj['rotate'] = direction === 'top' ? '180deg'
: direction === 'left' ? '30deg'
: direction === 'right' ? '-30deg'
: '0deg'
if (direction === 'right') {
obj['transform'] = 'scaleX(-1)'
}
imgEl.style.cssText = Object.keys(obj).map(key => `${key}: ${obj[key]}`).join('; ')
}
onMount(() => {
setTimeout(() => divStyles(), 100)
})
</script> </script>
<main> <main>
<div class="img" bind:this={divEl}>
<img bind:this={imgEl} src={rana} alt="rana" on:mouseenter={onHover}/>
</div>
</main> </main>
<style lang="sass"> <style lang="sass">
main
position: relative
width: 100%
max-width: 100%
height: 100%
max-height: 100%
overflow: hidden
.img
position: absolute
img
width: 200px
</style> </style>
+6 -2
View File
@@ -8,7 +8,11 @@
-webkit-font-smoothing: antialiased -webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale -moz-osx-font-smoothing: grayscale
html
width: 100%
height: 100%
body body
margin: 0 margin: 0
display: flex width: 100%
place-items: center height: 100%
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 707 KiB