rayncorg
rayncorg

Reputation: 993

SVG animation with CSS onclick

I have a heart button when onclick it will fill the SVG with red from bottom to top and when unclicked it will unfill the SVG from top to bottom. Heres what I've searched so far:JSFiddle

I'm new with this kind of techniques like keyframes and clip-path thing. These can all be done via css only?

body {
  display: -webkit-box;
  display: flex;
  -webkit-box-pack: center;
          justify-content: center;
  -webkit-box-align: center;
          align-items: center;
  height: 100vh;
}

.heart-container {
  position: relative;
  width: 40px;
  height: 40px;
}

.heart-clip {
  display: block;
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
  -webkit-clip-path: url(#svgPath);
          clip-path: url(#svgPath);
}
.heart-clip:hover {
  -webkit-animation: pulse .6s .3s infinite;
          animation: pulse .6s .3s infinite;
}
.heart-clip:hover::before {
  -webkit-transform: scale(1);
          transform: scale(1);
  opacity: 1;
}
.heart-clip::before {
  content: '';
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background-color: #D32F2F;
  opacity: 0;
  -webkit-transform: scale(0);
          transform: scale(0);
  -webkit-transition: opacity .2s linear, -webkit-transform .2s linear;
  transition: opacity .2s linear, -webkit-transform .2s linear;
  transition: transform .2s linear, opacity .2s linear;
  transition: transform .2s linear, opacity .2s linear, -webkit-transform .2s linear;
  -webkit-transform-origin: center 60%;
          transform-origin: center 60%;
}

.heart-stroke {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  fill: #D32F2F;
}

@-webkit-keyframes pulse {
  0% {
    -webkit-transform: scale(1);
            transform: scale(1);
  }
  30% {
    -webkit-transform: scale(1.2);
            transform: scale(1.2);
  }
  60% {
    -webkit-transform: scale(1);
            transform: scale(1);
  }
}

@keyframes pulse {
  0% {
    -webkit-transform: scale(1);
            transform: scale(1);
  }
  30% {
    -webkit-transform: scale(1.2);
            transform: scale(1.2);
  }
  60% {
    -webkit-transform: scale(1);
            transform: scale(1);
  }
}
<svg height="0" width="0">
    <defs>
        <clipPath id="svgPath">
            <path d="M20,35.09,4.55,19.64a8.5,8.5,0,0,1-.13-12l.13-.13a8.72,8.72,0,0,1,12.14,0L20,10.79l3.3-3.3a8.09,8.09,0,0,1,5.83-2.58,8.89,8.89,0,0,1,6.31,2.58,8.5,8.5,0,0,1,.13,12l-.13.13Z"/>
        </clipPath>
    </defs>
</svg>

<div class="heart-container">
   <svg width="40" height="40" viewBox="0 0 40 40" class='heart-stroke'>
      <path d="M20,35.07,4.55,19.62a8.5,8.5,0,0,1-.12-12l.12-.12a8.72,8.72,0,0,1,12.14,0L20,10.77l3.3-3.3A8.09,8.09,0,0,1,29.13,4.9a8.89,8.89,0,0,1,6.31,2.58,8.5,8.5,0,0,1,.12,12l-.12.12ZM10.64,7.13A6.44,6.44,0,0,0,6.07,18.19L20,32.06,33.94,18.12A6.44,6.44,0,0,0,34,9l0,0a6.44,6.44,0,0,0-4.77-1.85A6,6,0,0,0,24.83,9L20,13.78,15.21,9A6.44,6.44,0,0,0,10.64,7.13Z"/>
   </svg>
   
   <a href='#' class='heart-clip'></a>
</div>

any alternatives and solutions is much appreciated! Thanks in advance!

Upvotes: 3

Views: 1031

Answers (1)

Alexandr_TT
Alexandr_TT

Reputation: 14545

Consider filling with color using the feFlood filters and animating with changing thedy attribute of the feoffset filter.
Repeated clicks change the color direction animation

var svg1 = document.getElementById("svg1"),
  close = document.getElementById('close'),
  open = document.getElementById("open");

let flag = true;

svg1.addEventListener('click', function() {
  if (flag == true) {
    close.beginElement();
    flag = false;
  } else {
    open.beginElement();
    flag = true;
  }
});
<div class="heart-container">
      
   <svg id="svg1" width="40" height="40" viewBox="0 0 40 40"  class='heart-stroke'>
       <defs>
    <filter id="red_fill" x="0%" y="0%">
      <feFlood flood-color="#ded9d5" />
      <feOffset dx="0"> 
	     <!-- Animation fills of color  from top to bottom. -->
        <animate id="close" attributeName="dy" values="0;40" dur="1s" begin="indefinite" repeatCount="3" restart="whenNotActive" fill="freeze"/> 
           <!-- Animation fills of color  from bottom to top.		   -->
		  <animate id="open" attributeName="dy" values="40;0" dur="1s" begin="indefinite" repeatCount="3" restart="whenNotActive" fill="freeze"/> 
     
	 </feOffset>
      <feComposite operator="in" in2="SourceGraphic" />
      <feComposite operator="over" in2="SourceGraphic" />
    </filter>
  </defs>
	  
	   <path filter="url(#red_fill)"  stroke="red" stroke-width="2" fill="red" d="M20,35.07,4.55,19.62a8.5,8.5,0,0,1-.12-12l.12-.12a8.72,8.72,0,0,1,12.14,0L20,10.77l3.3-3.3A8.09,8.09,0,0,1,29.13,4.9a8.89,8.89,0,0,1,6.31,2.58,8.5,8.5,0,0,1,.12,12l-.12.12Z"/> 
	 
   </svg>
     <a href='#' class='heart-clip'></a>
</div>  

Upvotes: 2

Related Questions