Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add CSS bounce animation to a div on click only for once

Tags:

javascript

css

I have a CSS map pin which has some CSS3 animations, here it is:'

https://jsfiddle.net/xg7xfzeq/

body {
  background: #e6e6e6;
}

.pin {
  width: 30px;
  height: 30px;
  border-radius: 50% 50% 50% 0;
  background: #00cae9;
  position: absolute;
  transform: rotate(-45deg);
  left: 50%;
  top: 50%;
  margin: -20px 0 0 -20px;
}
.pin:after {
  content: "";
  width: 14px;
  height: 14px;
  margin: 8px 0 0 8px;
  background: #e6e6e6;
  position: absolute;
  border-radius: 50%;
}

.bounce {
  animation-name: bounce;
  animation-fill-mode: both;
  animation-duration: 1s;
}

.pulse {
  background: #d6d4d4;
  border-radius: 50%;
  height: 14px;
  width: 14px;
  position: absolute;
  left: 50%;
  top: 50%;
  margin: 11px 0px 0px -12px;
  transform: rotateX(55deg);
  z-index: -2;
}
.pulse:after {
  content: "";
  border-radius: 50%;
  height: 40px;
  width: 40px;
  position: absolute;
  margin: -13px 0 0 -13px;
  animation: pulsate 1s ease-out;
  animation-iteration-count: infinite;
  opacity: 0;
  box-shadow: 0 0 1px 2px #00cae9;
  animation-delay: 1.1s;
}

@keyframes pulsate {
  0% {
    transform: scale(0.1, 0.1);
    opacity: 0;
  }

  50% {
    opacity: 1;
  }

  100% {
    transform: scale(1.2, 1.2);
    opacity: 0;
  }
}

@keyframes bounce {
  0% {
    opacity: 0;
    transform: translateY(-2000px) rotate(-45deg);
  }

  60% {
    opacity: 1;
    transform: translateY(30px) rotate(-45deg);
  }

  80% {
    transform: translateY(-10px) rotate(-45deg);
  }

  100% {
    transform: translateY(0) rotate(-45deg);
  }
}
.myBounceDiv { 
        -moz-animation:bounce .40s linear;  
        -webkit-animation:bounce .40s linear; 
} 

@-moz-keyframes bounce {


 0%{ -moz-transform:scale(0); opacity:0;}
        50%{ -moz-transform:scale(1.3); opacity:0.4; }
        75%{ -moz-transform:scale(0.9); opacity:0.7;}
        100%{ -moz-transform:scale(1); opacity:1;}
}

@-webkit-keyframes bounce {
        0%{ -webkit-transform:scale(0); opacity:0;}
        50%{ -webkit-transform:scale(1.3); opacity:0.4;}
        75%{ -webkit-transform:scale(0.9); opacity:0.7;}
        100%{ -webkit-transform:scale(1); opacity:1;}
}

and its HTML

<div class='myBounceDiv'>
<div class='pin bounce'></div>
<div class='pulse'></div>
</div>

Well, I want to add bounce css3 animation on click, I have found some solutions for it such as changing CSS style when we click on its div using javascript. While it is possible but when I change its CSS class it will start to bounce every forever. How can make it animate only once? One way could be triggering a timer and after 1000 ms changing its css class into its first class, but there is another problem, my div's class has another animation (when it first appears in page, it drops from top to bottom) so if I change its css class to bouncing animation and again change it to its original the appearance animation trigers again and it is not what I need. Is there any way to achieve what I need using pure javascript and CSS? In fact, i need to make something like this http://dynamicsjs.com/examples/pin.html but its animation appears on click using CSS.

like image 668
Majid Hojati Avatar asked Dec 18 '17 18:12

Majid Hojati


2 Answers

As far as I understood you mean this:

  • In the first version pulse effect and bounce effect run only clicking once
  • In the second version pulse effect run always like present version but bounce effect run only clicking once

First version

element = document.getElementById("marker");

element.addEventListener("click", function(e) {
  e.preventDefault;
  
  // -> removing the class
  element.classList.remove("bounce");
  
  // -> triggering reflow /* The actual magic */
  // without this it wouldn't work. Try uncommenting the line and the transition won't be retriggered.
  element.offsetWidth = element.offsetWidth;
  
  // -> and re-adding the class
  element.classList.add("bounce");
}, false);
body {
  background: #e6e6e6;
}

.pin {
  width: 30px;
  height: 30px;
  border-radius: 50% 50% 50% 0;
  background: #00cae9;
  position: absolute;
  transform: rotate(-45deg);
  left: 50%;
  top: 50%;
  margin: -20px 0 0 -20px;
}
.pin:after {
  content: "";
  width: 14px;
  height: 14px;
  margin: 8px 0 0 8px;
  background: #e6e6e6;
  position: absolute;
  border-radius: 50%;
}

.bounce {
  animation-name: bounce;
  animation-fill-mode: both;
  animation-duration: 0.9s;
}

.pulse {
  background: #d6d4d4;
  border-radius: 50%;
  height: 14px;
  width: 14px;
  position: absolute;
  left: 50%;
  top: 50%;
  margin: 11px 0px 0px -12px;
  transform: rotateX(55deg);
  z-index: -2;
}
.bounce+.pulse:after {
  content: "";
  border-radius: 50%;
  height: 40px;
  width: 40px;
  position: absolute;
  margin: -13px 0 0 -13px;
  animation: pulsate 1s ease-out;
  opacity: 0;
  box-shadow: 0 0 1px 2px #00cae9;
  animation-delay: 0.1s;  
  -webkit-animation-iteration-count: 1;
  animation-iteration-count: 1;
}

@keyframes pulsate {
  0%, 100% {
    transform: scale(0.1, 0.1);
    opacity: 0;
  }

  50% {
    opacity: 1;
  }

  100% {
    transform: scale(1.2, 1.2);
    opacity: 0;
  }
}

@keyframes bounce {
  0% {
    opacity: 0;
    transform: translateY(-1000px) rotate(-45deg);
  }

  60% {
    opacity: 1;
    transform: translateY(30px) rotate(-45deg);
  }

  80% {
    transform: translateY(-10px) rotate(-45deg);
  }

  100% {
    transform: translateY(0) rotate(-45deg);
  }
}
.myBounceDiv { 
        -moz-animation:bounce .40s linear;  
        -webkit-animation:bounce .40s linear; 
} 

@-moz-keyframes bounce {
        0%{ -moz-transform:scale(0); opacity:0;}
        50%{ -moz-transform:scale(1.3); opacity:0.4; }
        75%{ -moz-transform:scale(0.9); opacity:0.7;}
        100%{ -moz-transform:scale(1); opacity:1;}
}

@-webkit-keyframes bounce {
        0%{ -webkit-transform:scale(0); opacity:0;}
        50%{ -webkit-transform:scale(1.3); opacity:0.4;}
        75%{ -webkit-transform:scale(0.9); opacity:0.7;}
        100%{ -webkit-transform:scale(1); opacity:1;}
}
<div class='myBounceDiv'>
<div id="marker" class='pin'></div>
<div class='pulse'></div>
</div>

Second version

/*
  Reference: https://css-tricks.com/restart-css-animation/
*/

element = document.getElementById("marker");

element.addEventListener("click", function(e) {
  e.preventDefault;
  
  // -> removing the class
  element.classList.remove("bounce");
  
  // -> triggering reflow /* The actual magic */
  // without this it wouldn't work. Try uncommenting the line and the transition won't be retriggered.
  element.offsetWidth = element.offsetWidth;
  
  // -> and re-adding the class
  element.classList.add("bounce");
}, false);
body {
  background: #e6e6e6;
}

.pin {
  width: 30px;
  height: 30px;
  border-radius: 50% 50% 50% 0;
  background: #00cae9;
  position: absolute;
  transform: rotate(-45deg);
  left: 50%;
  top: 50%;
  margin: -20px 0 0 -20px;
}
.pin:after {
  content: "";
  width: 14px;
  height: 14px;
  margin: 8px 0 0 8px;
  background: #e6e6e6;
  position: absolute;
  border-radius: 50%;
}

.bounce {
  animation-name: bounce;
  animation-fill-mode: both;
  animation-duration: 0.9s;
}

.pulse {
  background: #d6d4d4;
  border-radius: 50%;
  height: 14px;
  width: 14px;
  position: absolute;
  left: 50%;
  top: 50%;
  margin: 11px 0px 0px -12px;
  transform: rotateX(55deg);
  z-index: -2;
}
.pulse:after {
  content: "";
  border-radius: 50%;
  height: 40px;
  width: 40px;
  position: absolute;
  margin: -13px 0 0 -13px;
  animation: pulsate 1s ease-out;
  animation-iteration-count: infinite;
  opacity: 0;
  box-shadow: 0 0 1px 2px #00cae9;
  animation-delay: 0.1s;  
}

@keyframes pulsate {
  0%, 100% {
    transform: scale(0.1, 0.1);
    opacity: 0;
  }

  50% {
    opacity: 1;
  }

  100% {
    transform: scale(1.2, 1.2);
    opacity: 0;
  }
}

@keyframes bounce {
  0% {
    opacity: 0;
    transform: translateY(-1000px) rotate(-45deg);
  }

  60% {
    opacity: 1;
    transform: translateY(30px) rotate(-45deg);
  }

  80% {
    transform: translateY(-10px) rotate(-45deg);
  }

  100% {
    transform: translateY(0) rotate(-45deg);
  }
}
.myBounceDiv { 
        -moz-animation:bounce .40s linear;  
        -webkit-animation:bounce .40s linear; 
} 

@-moz-keyframes bounce {
        0%{ -moz-transform:scale(0); opacity:0;}
        50%{ -moz-transform:scale(1.3); opacity:0.4; }
        75%{ -moz-transform:scale(0.9); opacity:0.7;}
        100%{ -moz-transform:scale(1); opacity:1;}
}

@-webkit-keyframes bounce {
        0%{ -webkit-transform:scale(0); opacity:0;}
        50%{ -webkit-transform:scale(1.3); opacity:0.4;}
        75%{ -webkit-transform:scale(0.9); opacity:0.7;}
        100%{ -webkit-transform:scale(1); opacity:1;}
}
<div class='myBounceDiv'>
<div id="marker" class='pin'></div>
<div class='pulse'></div>
</div>

UPDATE

/*
  Reference: https://css-tricks.com/restart-css-animation/
*/




element = document.getElementById("marker");


setTimeout(function() {
  element.classList.remove("bounce");
}, 1000);


element.addEventListener("click", function(e) {
  e.preventDefault;
  
  // -> removing the class
  element.classList.remove("drop");
  
  // -> triggering reflow /* The actual magic */
  // without this it wouldn't work. Try uncommenting the line and the transition won't be retriggered.
  element.offsetWidth = element.offsetWidth;
  
  // -> and re-adding the class
  element.classList.add("drop");
}, false);
body {
  background: #e6e6e6;
}

.pin {
  width: 30px;
  height: 30px;
  border-radius: 50% 50% 50% 0;
  background: #00cae9;
  position: absolute;
  transform: rotate(-45deg);
  left: 50%;
  top: 50%;
  margin: -20px 0 0 -20px;
}
.pin:after {
  content: "";
  width: 14px;
  height: 14px;
  margin: 8px 0 0 8px;
  background: #e6e6e6;
  position: absolute;
  border-radius: 50%;
}

.bounce {
  animation-name: bounce;
  animation-fill-mode: both;
  animation-duration: 0.9s;
}

.pulse {
  background: #d6d4d4;
  border-radius: 50%;
  height: 14px;
  width: 14px;
  position: absolute;
  left: 50%;
  top: 50%;
  margin: 11px 0px 0px -12px;
  transform: rotateX(55deg);
  z-index: -2;
}
.pulse:after {
  content: "";
  border-radius: 50%;
  height: 40px;
  width: 40px;
  position: absolute;
  margin: -13px 0 0 -13px;
  animation: pulsate 1s ease-out;
  animation-iteration-count: infinite;
  opacity: 0;
  box-shadow: 0 0 1px 2px #00cae9;
  animation-delay: 0.1s;  
}

@keyframes pulsate {
  0%, 100% {
    transform: scale(0.1, 0.1);
    opacity: 0;
  }

  50% {
    opacity: 1;
  }

  100% {
    transform: scale(1.2, 1.2);
    opacity: 0;
  }
}

@keyframes bounce {
  0% {
    opacity: 0;
    transform: translateY(-1000px) rotate(-45deg);
  }

  60% {
    opacity: 1;
    transform: translateY(5px) rotate(-45deg);
  }

  80% {
    transform: translateY(-10px) rotate(-45deg);
  }

  100% {
    transform: translateY(0) rotate(-45deg);
  }
}
.myBounceDiv { 
        -moz-animation:bounce .40s linear;  
        -webkit-animation:bounce .40s linear; 
} 

@-moz-keyframes bounce {
        0%{ -moz-transform:scale(0); opacity:0;}
        50%{ -moz-transform:scale(1.3); opacity:0.4; }
        75%{ -moz-transform:scale(0.9); opacity:0.7;}
        100%{ -moz-transform:scale(1); opacity:1;}
}

@-webkit-keyframes bounce {
        0%{ -webkit-transform:scale(0); opacity:0;}
        50%{ -webkit-transform:scale(1.3); opacity:0.4;}
        75%{ -webkit-transform:scale(0.9); opacity:0.7;}
        100%{ -webkit-transform:scale(1); opacity:1;}
}



@keyframes drop {
  0% {
    transform: translateY(-40px) rotate(-45deg);
  }

  80% {
    transform: translateY(3px) rotate(-45deg);
  }

  100% {
    transform: translateY(0) rotate(-45deg);
  }
}

.drop {
  animation-name: drop;
  animation-fill-mode: both;
  animation-duration: 0.5s;
}
<div class='myBounceDiv'>
<div id="marker" class='pin bounce'></div>
<div class='pulse'></div>
</div>
like image 198
Elvin Mammadov Avatar answered Oct 02 '22 22:10

Elvin Mammadov


Instead of changing CSS classes to the bouncing animation and back to the original, you can instead add (on click) and remove (after 1s) classes to either pin or myBounceDiv. Something to note is that you'll also need to remove the bounce class once the animation completes.

It would look something like this:

const pinEl = document.querySelector('.pin');

setTimeout(() => pinEl.classList.remove('bounce'), 1000);
function removeMiniBounce() {
    pinEl.classList.remove("miniBounce");
  }
pinEl.onclick = () => {
  pinEl.classList.add("miniBounce");
  setTimeout(removeMiniBounce, 1000);
}

And your CSS would be:

@keyframes miniBounce {
    0%{ -webkit-transform:translateY(0px) rotate(-45deg);}
    30%{ -webkit-transform:translateY(-20px) rotate(-45deg);}
    60%{ -webkit-transform:translateY(0px) rotate(-45deg);}
    70%{ -webkit-transform:translateY(-5px) rotate(-45deg);}
    100%{ -webkit-transform:translateY(0) rotate(-45deg);}
}

.miniBounce {
  animation: miniBounce 0.4s ease-in-out; 
}
like image 30
goldins Avatar answered Oct 02 '22 21:10

goldins