Анимация полноэкранного оверлея SVG

1

Я пытаюсь использовать этот пример, найденный на Tympanus.net, чтобы создать классное анимированное меню:

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

Для жизни я не могу понять, как оживить путь, чтобы открыть из верхнего левого угла вправо, я вижу путь и путь, но я не понимаю координаты. Я создал кодекс, чтобы посмотреть, смогу ли я заставить его работать, но я полностью застрял.

/*!
 * 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>

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

Пожалуйста, кто-нибудь может мне помочь?

Теги:
svg

1 ответ

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)

/*!
 * 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 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>
  • 0
    Вау, спасибо, Пол, в этом столько смысла! Спасибо :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню