Tomater
This commit is contained in:
		
						commit
						efff561c74
					
				
					 6 changed files with 173 additions and 0 deletions
				
			
		
							
								
								
									
										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>
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue