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:
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>