动画全屏SVG叠加

时间:2017-07-31 13:19:45

标签: javascript css svg

我正在尝试使用Tympanus.net上的这个示例来创建一个很酷的动画菜单:

https://tympanus.net/Development/FullscreenOverlayStyles/index9.html

对于我的生活,我无法弄清楚如何设置从左上角到右下角打开路径的动画,我可以看到路径和路径,但我不理解坐标。我创建了一个codepen,看看我是否可以使用它 工作,但我完全卡住了。



/*!
 * classie - class helper functions
 * from bonzo https://github.com/ded/bonzo
 * 
 * classie.has( elem, 'my-class' ) -> true/false
 * classie.add( elem, 'my-new-class' )
 * classie.remove( elem, 'my-unwanted-class' )
 * classie.toggle( elem, 'my-class' )
 */

/*jshint browser: true, strict: true, undef: true */
/*global define: false */

(function(window) {
  'use strict';

  // class helper functions from bonzo https://github.com/ded/bonzo
  function classReg(className) {
    return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
  }

  // classList support for class management
  // altho to be fair, the api sucks because it won't accept multiple classes at once
  var hasClass, addClass, removeClass;

  if ('classList' in document.documentElement) {
    hasClass = function(elem, c) {
      return elem.classList.contains(c);
    };
    addClass = function(elem, c) {
      elem.classList.add(c);
    };
    removeClass = function(elem, c) {
      elem.classList.remove(c);
    };
  } else {
    hasClass = function(elem, c) {
      return classReg(c).test(elem.className);
    };
    addClass = function(elem, c) {
      if (!hasClass(elem, c)) {
        elem.className = elem.className + ' ' + c;
      }
    };
    removeClass = function(elem, c) {
      elem.className = elem.className.replace(classReg(c), ' ');
    };
  }

  function toggleClass(elem, c) {
    var fn = hasClass(elem, c) ? removeClass : addClass;
    fn(elem, c);
  }

  var classie = {
    // full names
    hasClass: hasClass,
    addClass: addClass,
    removeClass: removeClass,
    toggleClass: toggleClass,
    // short names
    has: hasClass,
    add: addClass,
    remove: removeClass,
    toggle: toggleClass
  };

  // transport
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(classie);
  } else {
    // browser global
    window.classie = classie;
  }

})(window);
(function() {
  var triggerBttn = document.getElementById('trigger-overlay'),
    overlay = document.querySelector('div.overlay'),
    closeBttn = overlay.querySelector('button.overlay-close');
  transEndEventNames = {
      'WebkitTransition': 'webkitTransitionEnd',
      'MozTransition': 'transitionend',
      'OTransition': 'oTransitionEnd',
      'msTransition': 'MSTransitionEnd',
      'transition': 'transitionend'
    },
    transEndEventName = transEndEventNames[Modernizr.prefixed('transition')],
    support = {
      transitions: Modernizr.csstransitions
    };
  s = Snap(overlay.querySelector('svg')),
    path = s.select('path'),
    pathConfig = {
      from: path.attr('d'),
      to: overlay.getAttribute('data-path-to')
    };

  function toggleOverlay() {
    if (classie.has(overlay, 'open')) {
      classie.remove(overlay, 'open');
      classie.add(overlay, 'close');

      var onEndTransitionFn = function(ev) {
        classie.remove(overlay, 'close');
      };

      path.animate({
        'path': pathConfig.from
      }, 400, mina.linear, onEndTransitionFn);
    } else if (!classie.has(overlay, 'close')) {
      classie.add(overlay, 'open');
      path.animate({
        'path': pathConfig.to
      }, 400, mina.linear);
    }
  }

  triggerBttn.addEventListener('click', toggleOverlay);
  closeBttn.addEventListener('click', toggleOverlay);
})();

.svgcontainer {
  width: 600px;
  height: 300px;
  margin: 0 auto;
  border: 1px solid red;
}


/* Overlay style */
.overlay {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background: rgba(28, 105, 212, 0.95);
}

/* Overlay closing cross */
.overlay .overlay-close {
  width: 80px;
  height: 80px;
  position: absolute;
  right: 20px;
  top: 20px;
  overflow: hidden;
  border: none;
  font-size: 18px;
  color: white;
  outline: none;
  z-index: 100;
}

/* Menu style */
.overlay nav {
  text-align: center;
  position: relative;
  top: 50%;
  height: 60%;
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
}

.overlay ul {
  list-style: none;
  padding: 0;
  margin: 0 auto;
  display: inline-block;
  height: 100%;
  position: relative;
}

.overlay ul li {
  display: block;
  height: 20%;
  height: calc(100% / 5);
  min-height: 54px;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.overlay ul li a {
  font-size: 54px;
  font-weight: 300;
  display: block;
  color: #fff;
  -webkit-transition: color 0.2s;
  transition: color 0.2s;
}

.overlay ul li a:hover,
.overlay ul li a:focus {
  color: #f0f0f0;
}


/* Effects */
.overlay-cornershape {
  background: transparent;
  visibility: hidden;
  -webkit-transition: visibility 0s 0.5s;
  transition: visibility 0s 0.5s;
}

.overlay-cornershape.open {
  visibility: visible;
  -webkit-transition: none;
  transition: none;
}

.overlay-cornershape svg {
  position: absolute;
  top: 0;
  left: 0;
}

.overlay-cornershape .overlay-path {
  fill: rgba(153, 204, 51, 0.9);
  fill: rgba(28, 105, 212, 0.95);
}

.overlay-cornershape nav,
.overlay-cornershape .overlay-close {
  opacity: 0;
  -webkit-transition: opacity 0.4s 0.4s;
  transition: opacity 0.4s 0.4s;
}

.overlay-cornershape.open nav,
.overlay-cornershape.open .overlay-close {
  opacity: 1;
  -webkit-transition-delay: 0.4s;
  transition-delay: 0.4s;
}

.overlay-cornershape.close nav,
.overlay-cornershape.close .overlay-close {
  -webkit-transition-delay: 0s;
  transition-delay: 0s;
}

@media screen and (max-height: 30.5em) {
  .overlay nav {
    height: 70%;
    font-size: 34px;
  }
  .overlay ul li {
    min-height: 34px;
  }
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>

<div class="container">
  <button id="trigger-overlay" type="button">Open Overlay</button>
</div>
<!-- /container -->
<!-- open/close -->
<div class="overlay overlay-cornershape" data-path-to="m 0,0 1439.999975,0 0,805.99999 -1439.999975,0 z">
  <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1440 806" preserveAspectRatio="none">
    <path class="overlay-path" d="m 0,0 1439.999975,0 0,805.99999 0,-805.99999 z" />
  </svg>
  <button type="button" class="overlay-close">Close</button>
  <nav>
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Work</a></li>
      <li><a href="#">Clients</a></li>
      <li><a href="#">Contact</a></li>
    </ul>
  </nav>
</div>
&#13;
&#13;
&#13;

https://codepen.io/jenkinspg/pen/wqGMoV

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:3)

你必须反转(水平翻转)两个路径定义。可能不明显的是他们使用的是小写m,因此每个坐标对都是相对于最后一个坐标对。

例如,原始中的起始路径是:

m 0,0 1440,0 0,806 0,-806 z

这些点分别是左上角,右上角,右下角,右上角(按此顺序)。它的动画是:

m 0,0 1440,0 0,806 -1440,0 z

或者:左上角,右上角,右下角,左下角。换句话说,最后一点从右上角移动到左下角。

要改为从左上角到右下角,我们必须颠倒该形状中坐标的顺序。所以来自:

m 1440,0 -1440,0 0,806 0,-806 z  (TR, TL, BL, TL)

为:

m 1440,0 -1440,0 0,806 1440,0 z  (TR, TL, BL, BR)

&#13;
&#13;
/*!
 * classie - class helper functions
 * from bonzo https://github.com/ded/bonzo
 * 
 * classie.has( elem, 'my-class' ) -> true/false
 * classie.add( elem, 'my-new-class' )
 * classie.remove( elem, 'my-unwanted-class' )
 * classie.toggle( elem, 'my-class' )
 */

/*jshint browser: true, strict: true, undef: true */
/*global define: false */

(function(window) {
  'use strict';

  // class helper functions from bonzo https://github.com/ded/bonzo
  function classReg(className) {
    return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
  }

  // classList support for class management
  // altho to be fair, the api sucks because it won't accept multiple classes at once
  var hasClass, addClass, removeClass;

  if ('classList' in document.documentElement) {
    hasClass = function(elem, c) {
      return elem.classList.contains(c);
    };
    addClass = function(elem, c) {
      elem.classList.add(c);
    };
    removeClass = function(elem, c) {
      elem.classList.remove(c);
    };
  } else {
    hasClass = function(elem, c) {
      return classReg(c).test(elem.className);
    };
    addClass = function(elem, c) {
      if (!hasClass(elem, c)) {
        elem.className = elem.className + ' ' + c;
      }
    };
    removeClass = function(elem, c) {
      elem.className = elem.className.replace(classReg(c), ' ');
    };
  }

  function toggleClass(elem, c) {
    var fn = hasClass(elem, c) ? removeClass : addClass;
    fn(elem, c);
  }

  var classie = {
    // full names
    hasClass: hasClass,
    addClass: addClass,
    removeClass: removeClass,
    toggleClass: toggleClass,
    // short names
    has: hasClass,
    add: addClass,
    remove: removeClass,
    toggle: toggleClass
  };

  // transport
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(classie);
  } else {
    // browser global
    window.classie = classie;
  }

})(window);
(function() {
  var triggerBttn = document.getElementById('trigger-overlay'),
    overlay = document.querySelector('div.overlay'),
    closeBttn = overlay.querySelector('button.overlay-close');
  transEndEventNames = {
      'WebkitTransition': 'webkitTransitionEnd',
      'MozTransition': 'transitionend',
      'OTransition': 'oTransitionEnd',
      'msTransition': 'MSTransitionEnd',
      'transition': 'transitionend'
    },
    transEndEventName = transEndEventNames[Modernizr.prefixed('transition')],
    support = {
      transitions: Modernizr.csstransitions
    };
  s = Snap(overlay.querySelector('svg')),
    path = s.select('path'),
    pathConfig = {
      from: path.attr('d'),
      to: overlay.getAttribute('data-path-to')
    };

  function toggleOverlay() {
    if (classie.has(overlay, 'open')) {
      classie.remove(overlay, 'open');
      classie.add(overlay, 'close');

      var onEndTransitionFn = function(ev) {
        classie.remove(overlay, 'close');
      };

      path.animate({
        'path': pathConfig.from
      }, 400, mina.linear, onEndTransitionFn);
    } else if (!classie.has(overlay, 'close')) {
      classie.add(overlay, 'open');
      path.animate({
        'path': pathConfig.to
      }, 400, mina.linear);
    }
  }

  triggerBttn.addEventListener('click', toggleOverlay);
  closeBttn.addEventListener('click', toggleOverlay);
})();
&#13;
.svgcontainer {
  width: 600px;
  height: 300px;
  margin: 0 auto;
  border: 1px solid red;
}


/* Overlay style */
.overlay {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background: rgba(28, 105, 212, 0.95);
}

/* Overlay closing cross */
.overlay .overlay-close {
  width: 80px;
  height: 80px;
  position: absolute;
  right: 20px;
  top: 20px;
  overflow: hidden;
  border: none;
  font-size: 18px;
  color: white;
  outline: none;
  z-index: 100;
}

/* Menu style */
.overlay nav {
  text-align: center;
  position: relative;
  top: 50%;
  height: 60%;
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
}

.overlay ul {
  list-style: none;
  padding: 0;
  margin: 0 auto;
  display: inline-block;
  height: 100%;
  position: relative;
}

.overlay ul li {
  display: block;
  height: 20%;
  height: calc(100% / 5);
  min-height: 54px;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.overlay ul li a {
  font-size: 54px;
  font-weight: 300;
  display: block;
  color: #fff;
  -webkit-transition: color 0.2s;
  transition: color 0.2s;
}

.overlay ul li a:hover,
.overlay ul li a:focus {
  color: #f0f0f0;
}


/* Effects */
.overlay-cornershape {
  background: transparent;
  visibility: hidden;
  -webkit-transition: visibility 0s 0.5s;
  transition: visibility 0s 0.5s;
}

.overlay-cornershape.open {
  visibility: visible;
  -webkit-transition: none;
  transition: none;
}

.overlay-cornershape svg {
  position: absolute;
  top: 0;
  left: 0;
}

.overlay-cornershape .overlay-path {
  fill: rgba(153, 204, 51, 0.9);
  fill: rgba(28, 105, 212, 0.95);
}

.overlay-cornershape nav,
.overlay-cornershape .overlay-close {
  opacity: 0;
  -webkit-transition: opacity 0.4s 0.4s;
  transition: opacity 0.4s 0.4s;
}

.overlay-cornershape.open nav,
.overlay-cornershape.open .overlay-close {
  opacity: 1;
  -webkit-transition-delay: 0.4s;
  transition-delay: 0.4s;
}

.overlay-cornershape.close nav,
.overlay-cornershape.close .overlay-close {
  -webkit-transition-delay: 0s;
  transition-delay: 0s;
}

@media screen and (max-height: 30.5em) {
  .overlay nav {
    height: 70%;
    font-size: 34px;
  }
  .overlay ul li {
    min-height: 34px;
  }
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>

<div class="container">
  <button id="trigger-overlay" type="button">Open Overlay</button>
</div>
<!-- /container -->
<!-- open/close -->
<div class="overlay overlay-cornershape" data-path-to="m 1440,0 -1440,0 0,806 1440,0 z">
  <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1440 806" preserveAspectRatio="none">
    <path class="overlay-path" d="m 1440,0 -1440,0 0,806 0,-806 z" />
  </svg>
  <button type="button" class="overlay-close">Close</button>
  <nav>
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Work</a></li>
      <li><a href="#">Clients</a></li>
      <li><a href="#">Contact</a></li>
    </ul>
  </nav>
</div>
&#13;
&#13;
&#13;