<div class="main-view-container">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">

    <svg id="PlayPauseButton" class="svg-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">

      <g id="keylines" fill="none">
        <circle id="keyline-outer-circle--play-button" cx="24" cy="24" r="22" stroke="#000" stroke-miterlimit="10" />
      </g>

      <g id="guide-shapes" fill="none">
        <polygon id="guide-shape--pause-right" class="guide-element guide-element__pause-right" points="26.5,13 38,13 38,36 26.5,36" />
        <polygon id="guide-shape--pause-left" class="guide-element__pause-left" points="10,13 21.5,13 21.5,36 10,36" />
      </g>

      <!--
                        In the start state, these will be shaped and positioned to
                        perfectly match the play triangle
                    -->
      <g id="main-shapes">
        <polygon id="pause-bar--left" class="shape-element shape-element__pause-left" points="18,13 24.35,16.585 24.35,32.415 18,36" />
        <polygon id="pause-bar--right" class="shape-element shape-element__pause-right" points="24.2,16.5 38,24.5 38,24.5 24.2,32.5" />
      </g>

    </svg>
  </svg>
</div>
body {
  width: 100%;
  height: 100vh;
  position: relative;
  background-color: lightgrey;
}

.main-view-container {
  width: 80%;
  height: 80%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate3d(-50%, -50%, 0);
}

.svg-icon {
  pointer-events: all;
}
View Compiled
const
  DURATIONS = {
    toggleIcon: 0.5
  },

  SELECTORS = {

    pauseBarRight: {
      origin: '.shape-element__pause-right',
      destinationGuide: '.guide-element__pause-right'
    },
    pauseBarLeft: {
      origin: '.shape-element__pause-left',
      destinationGuide: '.guide-element__pause-left'
    }
  },

  EASINGS = {
    toggleIcon: Power2.easeOut // ~= linear-in-slow-out
  },

  boundUpdateAttr = function boundUpdateAttr(attr, value) {
    this.setAttribute(attr, value.toString());
  },

  /**
   * Helper that parses the "d" (for a path) or "points" (for a polygon) attribute
   * from an SVG and returns a numeric array or, for paths, a mixed array of 
   * numeric values and string letters
   */
  parsePathPointsAttr = function parsePathPointsAttr(attrString) {

    // Split the string into path commands and points
    let
      pathExpression = /[achlmrqstvz]|(-?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig,

      path = attrString.match(pathExpression).map((n) => {
        return isNaN(+n) ? n : +n;
      });

    // The first element needs to be a number, so remove if it's not
    // Calling the string method will return the path with the removed element
    path.prefix = isNaN(path[0]) ? path.shift() : '';
    path.string = function() {
      return path.prefix + path.join(' ');
    };

    return path;
  },

  /**
   * onComplete and onReverseComplete callback that helps us 
   * track the proper state of the icon
   */
  boundSetStateOnToggle = function boundSetStateOnToggle() {
    this.isAnimating = false;
    this.isShowingPlay = !this.isShowingPlay;
  };

let init = ((svgElem, opts) => {

  let
    icon = Object.create(null),
   
    wireUpPolygonPoints = function wireUpPolygonPoints() {
      
      icon.POLYGON_POINTS = {
        pauseBarRight: {
          start: parsePathPointsAttr(icon.DOM_REFS.pauseBarRight.getAttribute('points')),
          end: parsePathPointsAttr(icon.DOM_REFS.pauseBarRightGuide.getAttribute('points')),
          correspondingDOMElem: icon.DOM_REFS.pauseBarRight
        },
        pauseBarLeft: {
          start: parsePathPointsAttr(icon.DOM_REFS.pauseBarLeft.getAttribute('points')),
          end: parsePathPointsAttr(icon.DOM_REFS.pauseBarLeftGuide.getAttribute('points')),
          correspondingDOMElem: icon.DOM_REFS.pauseBarLeft
        }
      }
    },

    /**
     * Creates a timeline that animates the play symbol the pause symbol,
     * which is then ready to be reversed when we want to go in the opposite direction
     */
    createPlayPauseTL = function createPlayPauseTL() {
      let TL = new TimelineMax({
        paused: true,
        onComplete: boundSetStateOnToggle.bind(icon),
        onReverseComplete: boundSetStateOnToggle.bind(icon)
      });

      // Animate polygons to their destinations by interpolating the
      // "points" attribute for each
      for (let pointSet of 
           [
              icon.POLYGON_POINTS.pauseBarLeft,
              icon.POLYGON_POINTS.pauseBarRight
           ]
      ) {
          TL.to(
            pointSet.start,
            DURATIONS.toggleIcon, {
              endArray: pointSet.end,
              ease: EASINGS.toggleIcon,

              // update the DOM with the value that's being interpolated
              onUpdate: boundUpdateAttr.bind(
                pointSet.correspondingDOMElem,
                'points',
                pointSet.start
              )
            },
            0
          );
      }
      return TL;
    };

  icon.svgElem = svgElem;
  icon.isAnimating = false;
  icon.isShowingPlay = true;

  ////// Cache DOM references and use then to compute our polygon start and end points
  icon.DOM_REFS = {
    pauseBarLeft: icon.svgElem.querySelector(SELECTORS.pauseBarLeft.origin),
    pauseBarLeftGuide: icon.svgElem.querySelector(SELECTORS.pauseBarLeft.destinationGuide),
    pauseBarRight: icon.svgElem.querySelector(SELECTORS.pauseBarRight.origin),
    pauseBarRightGuide: icon.svgElem.querySelector(SELECTORS.pauseBarRight.destinationGuide)
  };
  wireUpPolygonPoints();

  ///// Once everything is computed in the DOM, make and cache our timeline
  icon.mainIconTL = createPlayPauseTL();

  icon.handleClick = function handleClick() {
    
    if (!this.isAnimating) {
      
      this.isAnimating = true;

      if (this.isShowingPlay) {
        // animate to the pause symbol
        this.mainIconTL.play(0);

      } else {
        // Reverse back to the play symbol.
        // NOTE: 0 sets the playhead at the end of the animation,
        // and we reverse from there
        this.mainIconTL.reverse(0);
      }

      this.isPlaying = !this.isPlaying;
    }
  };

  icon.svgElem.addEventListener('click', icon.handleClick.bind(icon), false);

  return icon;

});

let icon = init(document.querySelector('#PlayPauseButton'));
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/plugins/EndArrayPlugin.min.js