tomater/index.html

174 lines
4.4 KiB
HTML
Raw Permalink Normal View History

2024-10-04 20:11:17 -03:00
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tomater</title>
<style>
body {
background: #db4343;
}
.col {
display: flex;
flex-direction: column;
gap: 10px;
margin: auto;
max-width: 900px;
background: #97b73d;
border-radius: 99px;
}
* {
text-align: center;
color: #fff;
}
h1 {
font-family: sans;
}
#picture-container {
position: relative;
margin: auto;
}
.tomato {
position: absolute;
width: 50px;
height: 50px;
object-fit: contain;
pointer-events: none;
z-index: 10;
}
#picture {
flex: 1;
max-width: 80vw;
max-height: 80vh;
object-fit: contain;
cursor: url(/crosshair.png), default;
}
#file-picker {
background: brown;
max-width: max-content;
margin: 20px auto;
padding: 10px;
border-radius: 10px;
}
#sign {
position: absolute;
bottom: 0;
rotate: 3deg;
height: 187px;
right: -120px;
}
</style>
</head>
<body>
<div class="col">
<h1>Tomater</h1>
<div id="picture-container">
<img ondragstart="return false;" src="wall.jpg" alt="" id="picture" />
<img src="/tomate-with-me.png" alt="" id="sign" />
</div>
<input type="file" id="file-picker" />
</div>
<script>
const picture = document.getElementById("picture");
const pictureContainer = document.getElementById("picture-container");
const filePicker = document.getElementById("file-picker");
filePicker.onchange = () => {
var reader = new FileReader();
reader.onload = (e) => {
picture.src = e.target.result;
};
reader.readAsDataURL(filePicker.files[0]);
const tomatos = document.querySelectorAll(".tomato");
tomatos.forEach((tomato) => {
tomato.remove();
});
};
const updateTomato = (tomato) => {
if (tomato.progress > 100) {
tomato.src = "/splat.png";
tomato.style.left = `${tomato.end_x - 50}px`;
tomato.style.top = `${tomato.end_y - 50}px`;
tomato.style.width = "100px";
tomato.style.height = "100px";
return;
}
let new_x = lerp(tomato.progress, tomato.start_x, tomato.end_x);
let new_y = lerp(tomato.progress, tomato.start_y, tomato.end_y);
// apply a curve effect to path
// the lower the target height, the bigger the "curve"
const targetHeightContribution = tomato.end_y / picture.height / 2;
// the closer to the middle of the path
// the bigger the curve effect
const progressContribution = Math.sin(
(tomato.progress / 100) * Math.PI,
);
new_y -= 500 * targetHeightContribution * progressContribution;
const scale = lerp(tomato.progress, 150, 40);
const imageSize = (50 * scale) / 100;
tomato.style.left = `${new_x - imageSize / 2}px`;
tomato.style.top = `${new_y - imageSize / 2}px`;
tomato.style.rotate = `${tomato.rotation}deg`;
tomato.style.width = `${scale}px`;
tomato.style.height = `${scale}px`;
tomato.progress += 2.0;
tomato.rotation += tomato.angularMomentum;
};
picture.onclick = (e) => {
let rect = e.target.getBoundingClientRect();
let x = e.clientX - rect.left;
let y = e.clientY - rect.top;
let tomato = document.createElement("img");
tomato.src = "/tomato.png";
tomato.classList.add("tomato");
tomato.progress = 0;
tomato.start_x = picture.width / 2;
tomato.start_y = picture.height;
tomato.end_x = x;
tomato.end_y = y;
tomato.angularMomentum = Math.random() * 20 - 10;
tomato.rotation = 0;
tomato.scale = 1;
updateTomato(tomato);
pictureContainer.appendChild(tomato);
};
const lerp = (progress, start, end) => {
return start + (end - start) * (progress / 100);
};
setInterval(() => {
const tomatos = document.querySelectorAll(".tomato");
tomatos.forEach(updateTomato);
}, 10);
</script>
</body>
</html>