Home > database >  Animated CSS play button
Animated CSS play button

Time:06-09

I'm trying to reproduce this piece of code (animated button using SVG and CSS): https://codepen.io/jscottsmith/pen/azRObp/

To keep the code clean, I wanted to use xlink with that. My current code looks as follows:

    @import "compass/css3";
    
    body {background:violet}
    
    @keyframes spin {
      to { transform: rotate(360deg); }
    }
    
    .stroke-dotted {
      opacity: 0;
      stroke-dasharray: 4,5;
      stroke-width: 1px;
      transform-origin: 50% 50%;
      animation: spin 4s infinite linear;
      transition: opacity 1s ease, 
                  stroke-width 1s ease;
    }
    .stroke-solid {
      stroke-dashoffset: 0;
      stroke-dashArray: 300;
      stroke-width: 4px;
      transition: stroke-dashoffset 1s ease, 
                  opacity 1s ease;
    }
    
    .icon {
      transform-origin: 50% 50%;
      transition: transform 200ms ease-out;
    }
    
    #play:hover .stroke-dotted {
      stroke-width: 4px;
      opacity: 1;  
    }
    
    #play:hover .stroke-solid {
      opacity: 0;
      stroke-dashoffset: 300;
    } 
    
    #play:hover .icon {
      transform: scale(1.05);
    }
    
    #PlayNow {
      cursor: pointer;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translateY(-50%) translateX(-50%);
        width:10em;
      height:auto;
      display:block;
    }
    <a href="#">
    <svg xmlns="http://www.w3.org/2000/svg" id="PlayNow" viewBox="0 0 100 100" x="0px" y="0px" ><use xlink:href="#play" id="playTrailerButton" /></svg>
    </a> 
    
    <svg xmlns="http://www.w3.org/2000/svg">
      <symbol id="play" viewBox="0 0 100 100">
         <path  fill="none" stroke="white"  d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
        C97.3,23.7,75.7,2.3,49.9,2.5"/>
      <path  fill="none" stroke="white"  d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
        C97.3,23.7,75.7,2.3,49.9,2.5"/>
      <path  fill="white" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z"/>
      </symbol>
    </svg>

But the animation doesn't work.. Any ideas or hints - why? jsfiddle is here: https://jsfiddle.net/4ztwr3c9/6

CodePudding user response:

You have this:

    #PlayNow {
      cursor: pointer;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translateY(-50%) translateX(-50%);
      width:10em;
      height:auto;
      display:block;
    }

There is no element with the id #PlayNow. The example below has #PlayNow selector replaced by the original #play and your changes have been added, and I removed the Compass as well which I guess you can add it back, just be mindful of each change and retest so it's easier to debug and backtrack.

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.stroke-dotted {
  opacity: 0;
  stroke-dasharray: 4, 5;
  stroke-width: 1px;
  transform-origin: 50% 50%;
  animation: spin 4s infinite linear;
  transition: opacity 1s ease, stroke-width 1s ease;
}

.stroke-solid {
  stroke-dashoffset: 0;
  stroke-dashArray: 300;
  stroke-width: 4px;
  transition: stroke-dashoffset 1s ease, opacity 1s ease;
}

.icon {
  transform-origin: 50% 50%;
  transition: transform 200ms ease-out;
}

#play:hover .stroke-dotted {
  stroke-width: 4px;
  opacity: 1;
}

#play:hover .stroke-solid {
  opacity: 0;
  stroke-dashoffset: 300;
}

#play:hover .icon {
  transform: scale(1.05);
}

html {
  height: 100%;
}

body {
  height: 100%;
  /*background-color: #30FF98;
  background: radial-gradient(#71edb5, #30ff98);*/
}

#play {
  cursor: pointer;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
/* Your Changes */  
  width:10em;
  height:auto;
  display:block;
}
body {background:violet}
<svg version="1.1" id="play" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" height="100px" width="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
  <path  fill="none" stroke="white"  d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
    C97.3,23.7,75.7,2.3,49.9,2.5"/>
  <path  fill="none" stroke="white"  d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
    C97.3,23.7,75.7,2.3,49.9,2.5"/>
  <path  fill="white" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z"/>
</svg>

CodePudding user response:

You can change/override some properties of a <use> element - provided these are not already set in your <symbol> element (see first example).

Since you need to change the dash-array values for different elements you can use css variables, that could be changed on hover.

body {
  background: violet;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

:root {
  --fill: #fff;
  --strokeWidth: 4px;
  --scale: 1;
  --strokeDashOffset: 10;
  --strokeDashArray: 4 5;
  --opacity: 0;
  --strokeDashArraySolid: 300;
  --strokeDashOffsetSolid: 0;
  --opacitySolid: 1;
}

.PlayNow {
  display: inline-block;
  height: 10em;
}

.PlayNow2 {
  --fill: #ccc;
  --strokeWidth: 6px;
  --scale: 1.5;
}

.PlayNow:hover {
  --scale: 1.05;
  --strokeDashOffset: 10;
  --strokeDashArray: 4 5;
  --strokeDashArraySolid: 300;
  --strokeDashOffsetSolid: 300;
  --opacity: 1;
  --opacitySolid: 0;
}

#playTrailerButtonSimple:hover {
  fill: green!important;
  stroke: green!important;
  stroke-dasharray: 10 5;
}
<a href="#">
  <svg  xmlns="http://www.w3.org/2000/svg" id="PlayNowSimple" viewBox="0 0 100 100">
    <use href="#playSimple" id="playTrailerButtonSimple" stroke-width="4" fill="red" stroke="red"/>
  </svg> Simple icon
</a>

<a href="#">
  <svg  xmlns="http://www.w3.org/2000/svg" id="PlayNow" viewBox="0 0 100 100">
    <use href="#play" id="playTrailerButton" />
  </svg>
</a>
<a href="#">
  <svg  xmlns="http://www.w3.org/2000/svg" id="PlayNow2" viewBox="0 0 100 100">
    <use href="#play" id="playTrailerButton" />
  </svg>
</a>

<svg xmlns="http://www.w3.org/2000/svg">
  <symbol id="circle">
    <path fill="none" style="stroke:var(--fill)" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7 C97.3,23.7,75.7,2.3,49.9,2.5" />
  </symbol>
  <symbol id="play" viewBox="0 0 100 100">
    <use href="#circle" transform-origin="center"  style="stroke-width: var(--strokeWidth); stroke-dasharray: var(--strokeDashArraySolid); stroke-dashoffset: var(--strokeDashOffsetSolid); opacity:var(--opacitySolid); transition: stroke-dashoffset 1s ease,  opacity 1s ease;" />
    <use href="#circle" transform-origin="center"  style="stroke-width: var(--strokeWidth); stroke-dasharray: var(--strokeDashArray); stroke-dashoffset: var(--strokeDashOffset); opacity:var(--opacity); animation: spin 4s infinite linear; transition: opacity 1s ease, stroke-width 1s ease;" />
    <path  transform-origin="center" style="fill:var(--fill);transform:scale(var(--scale));transition:0.3s"  d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z" />
  </symbol>
</svg>

<svg xmlns="http://www.w3.org/2000/svg">
  <symbol id="circle2">
    <path fill="none" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7 C97.3,23.7,75.7,2.3,49.9,2.5" />
  </symbol>
  <symbol id="playSimple" viewBox="0 0 100 100">
    <use href="#circle2" transform-origin="center"   />
    <path stroke-width="0"  transform-origin="center" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z" />
  </symbol>
</svg>

External <use> reference

To some extent, you could also use external svg files like so:

  <a href="#">
    <svg  xmlns="http://www.w3.org/2000/svg" id="PlayNow" viewBox="0 0 100 100" x="0px" y="0px">
      <use href="button.svg#play" id="playTrailerButton" style="transition:0.3s"/>
    </svg>
  </a>

** Drawback:** Your animations/transitions won#t work in most browsers (Firefox can render them)

  • Related