Tomater
This commit is contained in:
commit
efff561c74
BIN
crosshair.png
Normal file
BIN
crosshair.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2 KiB |
173
index.html
Normal file
173
index.html
Normal file
|
@ -0,0 +1,173 @@
|
|||
<!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>
|
BIN
tomate-with-me.png
Normal file
BIN
tomate-with-me.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 116 KiB |
BIN
tomato.png
Normal file
BIN
tomato.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 226 KiB |
Loading…
Reference in a new issue