<div id="shop">
  <header>
    <p>Stamppot-Shop</p>
    <div>
      <svg id="cart" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 446.853 446.853">
	<path d="M444.274,93.36c-2.558-3.666-6.674-5.932-11.145-6.123L155.942,75.289c-7.953-0.348-14.599,5.792-14.939,13.708   c-0.338,7.913,5.792,14.599,13.707,14.939l258.421,11.14L362.32,273.61H136.205L95.354,51.179   c-0.898-4.875-4.245-8.942-8.861-10.753L19.586,14.141c-7.374-2.887-15.695,0.735-18.591,8.1c-2.891,7.369,0.73,15.695,8.1,18.591   l59.491,23.371l41.572,226.335c1.253,6.804,7.183,11.746,14.104,11.746h6.896l-15.747,43.74c-1.318,3.664-0.775,7.733,1.468,10.916   c2.24,3.184,5.883,5.078,9.772,5.078h11.045c-6.844,7.617-11.045,17.646-11.045,28.675c0,23.718,19.299,43.012,43.012,43.012   s43.012-19.294,43.012-43.012c0-11.028-4.201-21.058-11.044-28.675h93.777c-6.847,7.617-11.047,17.646-11.047,28.675   c0,23.718,19.294,43.012,43.012,43.012c23.719,0,43.012-19.294,43.012-43.012c0-11.028-4.2-21.058-11.042-28.675h13.432   c6.6,0,11.948-5.349,11.948-11.947c0-6.6-5.349-11.948-11.948-11.948H143.651l12.902-35.843h216.221   c6.235,0,11.752-4.028,13.651-9.96l59.739-186.387C447.536,101.679,446.832,97.028,444.274,93.36z M169.664,409.814   c-10.543,0-19.117-8.573-19.117-19.116s8.574-19.117,19.117-19.117s19.116,8.574,19.116,19.117S180.207,409.814,169.664,409.814z    M327.373,409.814c-10.543,0-19.116-8.573-19.116-19.116s8.573-19.117,19.116-19.117s19.116,8.574,19.116,19.117   S337.916,409.814,327.373,409.814z"/>
    </svg>
      <span id="cartCounter"></span>
    </div>
    </header> 
  <section class="products">
    <article>
        <img src="https://www.limburgsmaaktnaarmeer.be/site/data/images/product/thumb_gele-aardappel_15271573345b0692561ca48.png" alt="logo">      
      <p>Aardappel</p>
      <p>€0,69</p>
    </article>
    <article>
      <img src="https://cdn.pixabay.com/photo/2018/02/28/22/42/kale-3189314_960_720.png" />
      <p>Boerenkool</p>
      <p>€4,20</p>
    </article>
    <article>
      <img src="https://www.unox.nl/sk-eu/content/dam/brands/unox/netherlands/1587677-8712100647864.png.rendition.767.767.png" />
      <p>Rookworst</p>
      <p>€4,20</p>
    </article>
    <article>
      <img src="https://www.groentehal.nl/app/uploads/2020/06/2-635938271922064256.png"/>
      <p>Jus</p>
      <p>€4,20</p>
    </article>
  </section> 
</div>
/* *** Init *** */

*{
  box-sizing: border-box;
  font-family: sans-serif
}

body {
  background-color: #173F5F
}

#shop {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 400px;
  height: 400px;
  transform: translate(-50%, -50%);
  border-radius: 10px;
  background-color: #F6D55C;
  display: flex;
  flex-direction: column;
  box-shadow: 0 0 5px #333;
}

/* *** Header *** */

#shop > header {
  width: 100%;
  height: 3rem;
  display: flex;
  padding: 0 1rem;
  justify-content: space-between;
}

#shop header div {
    display: flex;
    justify-content: center;
    align-items: flex-end;
}

#shop svg {
  width: 1.5rem;
  height: 100%;
}

#shop svg > path {
/*   stroke-dasharray: 3237; */
  stroke-dashoffset: 3237;
  fill: none;
  stroke: black;
  stroke-width: 15px;
}

#shop svg:hover > path {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: dash .5s linear alternate infinite;
}

@keyframes dash {
  from {
    stroke-dashoffset: 1000;
  }
  to {
    stroke-dashoffset: 0;
  }
}
/* *** Products *** */

.products {
  width: 100%;
  height: 100%;
  padding: .5rem 1rem 0 1rem;
}

.products > article {
  user-select: none;
  position: relative;
  width: 100%;
  background-color: white;
  display: flex;
  justify-content: space-between;
  padding: 0 .5rem;
  margin-bottom: .5rem;
  border-radius: 10px;
  align-items: center;
  cursor: pointer;
}

.products img {
  width: 3rem;
  height: 3rem;
}

.productClone {
  position: absolute;
  left: 5px;
  top: 5px;
  transition: transform 1s, opacity .3s ease-out 0.6s;
  pointer-event: none;
}

@media(prefers-reduced-motion) {
  .productClone {
    transition: none;
  }
}
const products = document.querySelectorAll(".products > article");
const productImgs = document.querySelectorAll(".products > article > img");
const cart = document.querySelector("#cart")
const cartCounter = document.querySelector("#cartCounter")

let cartPos = cart.getBoundingClientRect()
let cartItems = 0

window.addEventListener("resize", () => {
  cartPos = cart.getBoundingClientRect()
})


products.forEach((product, i) => {
    product.addEventListener("click", () => {
      // initiate timer "[TIMERNAME]"
      console.time(`responseTime`)
      
      cartItems++
      cartCounter.innerHTML = cartItems
      
      // get and set img
      const productImg = productImgs[i].cloneNode()
      productImg.classList.add("productClone")
      product.appendChild(productImg)
      
      // create animation
      productImg.style.transform = calculateDifference(productImg)
      productImg.style.opacity = 0
      
      requestAnimationFrame(() => {
        // stop timer "[TIMERNAME]"
        console.timeEnd("responseTime")
      })
      
      // remove el
      // kan beter met requestTimeFrame()
      setTimeout(() => {
        productImg.remove()
      }, 1100)
    })
})

const calculateDifference = (img) => {
  
  // For an even better performance, you can create an Array filled with all img-getboundingClientRect() info
  const imgPos = img.getBoundingClientRect()
  
  const deltaX = cartPos.left - imgPos.left
  const deltaY = cartPos.top - imgPos.top
  
  return `translate3d(${deltaX}px, ${deltaY}px, 0)`
}

let number = 0

const getFPS = (highResTimeStamp) => {
  if(highResTimeStamp) {
      const diff = highResTimeStamp - number
      // console.log(`${diff}ms per frame`)
      console.log(`${1000 / diff}fps`)
    
    number = highResTimeStamp
  } 
  requestAnimationFrame(getFPS)
}

window.requestAnimationFrame(getFPS)

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.