Home > Software engineering >  Animation should start when I hover over the div
Animation should start when I hover over the div

Time:12-02

I would like to implement the following: The animation should only start when I hover the mouse over the div. After I hovered over the div, the end number should remain visible and not change to the start value.

This is my code:

<!DOCTYPE html>
<html lang="en">
<head>
<title>Animation</title>
<style>
    .counter{
        color: white;
        font-size: 100px;
        height: 300px;
        width: 400px;
        background-color: black;
        display: flex;
        align-items:center;
        justify-content: center;
    }

    .animate{
        position:absolute;
        opacity:0;
        transition:0s 180s;
    }
    .animate:hover {
        opacity:1;
        transition:0s;
    }

   
</style>
</head>

<body>
    
    <div id="animate" style="background-color: orange; width: 300px; height: 200px;" class="counter" data-target="500">0</div>

<script>
const counters = document.querySelectorAll('.counter');
for(let n of counters) {
  const updateCount = () => {
    const target =   n.getAttribute('data-target');
    const count =   n.innerText;
    const speed = 5000; // change animation speed here
    const inc = target / speed; 
    if(count < target) {
      n.innerText = Math.ceil(count   inc);
      setTimeout(updateCount, 1);
    } else {
      n.innerText = target;
    }
  }
  updateCount();
}
</script>

</body>
</html>

CodePudding user response:

Add onmousover to id="animate"

<div id="animate" style="background-color: orange; width: 300px; height: 200px;" class="counter" data-target="500" onmouseover="animationEffect();">0</div>

Wrap the whole script in a method:

function animationEffect(){
    const counters = document.querySelectorAll('.counter');
    for(let n of counters) {
    const updateCount = () => {
        const target =   n.getAttribute('data-target');
        const count =   n.innerText;
        const speed = 5000; // change animation speed here
        const inc = target / speed; 
        if(count < target) {
        n.innerText = Math.ceil(count   inc);
        setTimeout(updateCount, 1);
        } else {
        n.innerText = target;
        }
    }
    updateCount();
    }
}

Should solve the problem

CodePudding user response:

EDIT:

The old answer was refering to the question before being edited. For the current case the following could be done:

const updateCount = n => {
  const target =  n.getAttribute('data-target')
  const count =  n.innerText
  const speed = 5000 // change animation speed here
  const inc = target / speed
  if (count < target) {
    n.innerText = Math.ceil(count   inc)
    requestAnimationFrame(() => updateCount(n))
  } else {
    n.innerText = target
  }
}

const counters = document.querySelectorAll('.counter')
for (let n of counters) {
  n.addEventListener('mouseenter', () => updateCount(n), {
    once: true
  })
}
.counter {
  color: white;
  font-size: 100px;
  height: 300px;
  width: 400px;
  background-color: black;
  display: flex;
  align-items: center;
  justify-content: center;
}

.animate {
  position: absolute;
  opacity: 0;
  transition: 0s 180s;
}

.animate:hover {
  opacity: 1;
  transition: 0s;
}
<div id="animate" style="background-color: orange; width: 300px; height: 200px" class="counter" data-target="500">
  0
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Old answer:

You would need to add a mouseenter event to the parent element. Note that the {once: true} option will make the event only fire once.

const parent = document.getElementById('parent')
parent.addEventListener('mouseenter', mouseEnterHandler, {once: true})

Then define the mouseEnterHandler callback as follows:

function mouseEnterHandler() {

  for (let n of counters) {
    n.style.display = 'block'
    updateCount(n)
  }

  /* If you only have one counter then just get it by its Id:
   const div = document.getElementById('hover-content')
   div.style.display = 'block'
   updateCount(div)
  */
}

n.style.display = 'block' will make the counter visible so no need for the css rule #parent:hover #hover-content { display:block; }.

Here is a working example:

Show code snippet

const updateCount = n => {
  const target =  n.getAttribute('data-target')
  const count =  n.innerText
  const speed = 5000 // change animation speed here
  const inc = target / speed
  if (count < target) {
    n.innerText = Math.ceil(count   inc)
    requestAnimationFrame(() => updateCount(n))
  } else {
    n.innerText = target
  }
}

const counters = document.querySelectorAll('.counter')
const parent = document.getElementById('parent')
parent.addEventListener('mouseenter', mouseEnterHandler, {
  once: true
})

function mouseEnterHandler() {
  for (let n of counters) {
    n.style.display = 'block'
    updateCount(n)
  }
}
.counter {
  color: white;
  font-size: 100px;
  height: 140px;
  width: 400px;
  background-color: black;
  display: flex;
  align-items: center;
  justify-content: center;
}

#hover-content {
  display: none;
}
<div id="parent">
  Some content
  <div hidden id="hover-content" class="counter" data-target="232">0</div>
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related