SVG animation via keyframes

127
04 сентября 2019, 00:50

Пользуюсь сборщиком в node и лайв сервером, при первом открытии страницы анимация на svg элементах не срабатывает: элементы вместо падения просто появляются. В сафари вообще всё плохо(даже без JS), падает только круг, остальные просто появляются. В чём баг? Возможно ли то, что элементы svg не дружат с анимациями/трансформами? Долго гуглил, но так и не нашёл решение проблемы.

Первый фикс: В slideInDown заменил при 100% translate(0,0) на translate3d(0, 0, 0), чтобы 0% от 100% не отличался стилем(функцией, которая задаёт позицию?). Это привело к правильному появлению в сафари. Насчёт решения бага с резким появлением без анимации/опасити ещё не уверен, поэтому не буду закрывать вопрос.

function getXY(elem) { 
  // (1) 
  var box = elem.getBoundingClientRect(); 
 
  var body = document.body; 
  var docEl = document.documentElement; 
 
  // (2) 
  var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; 
  var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft; 
 
  // (3) 
  var clientTop = docEl.clientTop || body.clientTop || 0; 
  var clientLeft = docEl.clientLeft || body.clientLeft || 0; 
 
  // (4) 
  var top = box.top + scrollTop - clientTop; 
  var left = box.left + scrollLeft - clientLeft; 
 
  return { 
    top: top, 
    left: left 
  }; 
} 
 
function getStyle(item, style) { 
  return getComputedStyle(item)[style]; 
} 
 
function setStyle(item, style, str) { 
  item.style[style] = str; 
} 
 
function getAll(str) { 
  return document.querySelectorAll(`.${str}`); 
} 
class Anime { 
  constructor(item) { 
    this.item = item; 
    this.top = undefined; 
    this.animationName = getStyle(this.item, 'animationName'); 
    this.animated = false; 
    // 
 
    this.scrollFunction = this.scrollFunction.bind(this); 
  } 
 
  prepareItem() { 
    setStyle(this.item, 'animationName', 'none'); 
    setStyle(this.item, 'visibility', 'hidden'); 
    // Только теперь выставим top, чтобы мы не взяли значение у спозиционированного из-за анимации блока 
    this.top = getXY(this.item).top; 
  } 
 
  playAnimation() { 
    setStyle(this.item, 'animationName', this.animationName); 
    setStyle(this.item, 'visibility', 'visible'); 
  } 
 
  scrollFunction() { 
    const y = window.scrollY + window.innerHeight; // Низ окна 
    if (y >= this.top) { 
      console.log('playing...'); 
      this.playAnimation(); 
      window.removeEventListener('scroll', this.scrollFunction, false); 
    } 
  } 
 
  handleAnimationEnd() { 
    console.log(this.item); 
    this.item.style = ''; 
    console.log(this.item.style); 
  } 
 
  listen() { 
    this.prepareItem(); 
    window.addEventListener('scroll', this.scrollFunction, false); 
    this.item.addEventListener('animationend', () => { 
      this.item.style = ''; 
    }); 
  } 
} 
 
 
const itemsToAnimate = getAll('anime'); 
for (let i = 0; i < itemsToAnimate.length; i += 1) { 
  const item = itemsToAnimate[i]; 
  new Anime(item).listen(); 
}
.anime { 
  animation-duration: 1500ms; 
  animation-fill-mode: both; 
} 
 
@media (prefers-reduced-motion) { 
  .anime { 
    transition: none !important; 
    animation: unset !important; 
  } 
} 
 
.slideInDown { 
  animation-name: slideInDown; 
} 
 
.slideInLeft { 
  animation-name: slideInLeft; 
} 
 
.slideInRight { 
  animation-name: slideInRight; 
} 
 
.slideInUp { 
  animation-name: slideInUp; 
} 
 
@keyframes slideInLeft { 
  from { 
    transform: translate3d(-100%, 0, 0); 
  } 
  to { 
    transform: translate3d(0, 0, 0); 
  } 
} 
 
@keyframes slideInDown { 
  from { 
    transform: translate3d(0, -100%, 0); 
    opacity: 0; 
  } 
  to { 
    transform: translate(0, 0); 
    opacity: 1; 
  } 
} 
 
@keyframes slideInRight { 
  from { 
    transform: translate3d(100%, 0, 0); 
    visibility: visible; 
  } 
  to { 
    transform: translate3d(0, 0, 0); 
  } 
} 
 
@keyframes slideInUp { 
  from { 
    transform: translate3d(0, 30%, 0); 
    opacity: 0; 
  } 
  to { 
    transform: translate3d(0, 0, 0); 
    opacity: 1; 
  } 
}
<div class="browser__body"> 
  <svg xmlns="http://www.w3.org/2000/svg" class="isometric-wrapper" viewBox="0 0 1125 790" preserveAspectRatio="xMinYMin meet"> 
      <defs> 
        <filter id="filter-1" width="132.5%" height="152.8%" x="-15.3%" y="-26.4%" filterUnits="objectBoundingBox"> 
          <feGaussianBlur in="SourceGraphic" stdDeviation="50" /> 
        </filter> 
      </defs> 
      <g class="isometric-browser" fill="none" fill-rule="evenodd" transform="translate(101 54.342)"> 
        <g class="isometric-browser__isometric-body" fill-rule="nonzero"> 
          <polyline class="isometric-body__iso" fill="#2B5166" points="34.124 227.316 34 233.984 579.087 560.506 958.99 332.949 959 326.217" /> 
          <polygon class="isometric-body__blur" fill="#407899" points="923 391.675 543.933 624.861 0 290.252 346.146 77.367 379.119 57.089" 
            filter="url(#filter-1)" /> 
          <polygon class="isometric-body__background" fill="#407899" points="959 326.635 579.111 554.278 34 227.622 380.896 19.796 413.94 0" /> 
        </g> 
        <g class="isometric-browser__isometric-header"> 
          <polygon class="isometric-header__iso" fill="#2E4660" fill-rule="nonzero" points="381.041 19.722 381 23.819 909.942 340.456 943 320.656 942.979 316.504" /> 
          <polyline class="isometric-header" fill="#456990" fill-rule="nonzero" points="414.072 0 943 316.521 909.928 336.304 381 19.783" /> 
        </g> 
        <g class="isometric-browser__isometric-tabs" fill-rule="nonzero" transform="translate(380 9.342)"> 
          <polygon class="isometric-tabs__tab-small" fill="#D9D8D7" points="17.408 .204 66.875 29.818 50.338 39.689 .85 10.107" /> 
          <polygon class="isometric-tabs__tab-long1" fill="#E6E5E5" points="66.875 29.818 149.428 79.217 132.911 89.088 50.338 39.689" /> 
          <polygon class="isometric-tabs__tab-long3" fill="#D9D8D7" points="149.47 79.195 232.022 128.595 215.516 138.477 132.942 89.067" /> 
          <polygon class="isometric-tabs--long__iso" fill="#9E9FA1" points="215.506 138.423 215.464 141.213 298.038 190.601 314.554 180.73 314.586 177.951" /> 
          <polygon class="isometric-tabs__tab-long2" fill="#C7C6C6" points="232.033 128.552 314.586 177.951 298.069 187.822 215.506 138.423" /> 
        </g> 
        <g class="isometric-browser__isometric-ui" fill-rule="nonzero" transform="translate(332 5.19)"> 
          <polygon class="background-ui__iso" fill="#BCBEC0" points=".069 44.07 .027 48.164 529.083 364.507 578.72 334.891 578.73 330.808" /> 
          <polyline class="isometric-ui__background" fill="#E6E5E5" points="49.633 14.432 .069 44.07 529.114 360.456 578.73 330.808" /> 
          <polygon class="isometric-ui__left-square" fill="#FFF" points="33.136 44.048 49.623 34.205 66.162 44.048 49.706 53.935" /> 
          <polygon class="isometric-ui__left-square" fill="#FFF" points="66.203 63.821 82.711 53.956 99.208 63.81 82.659 73.75" /> 
          <polygon class="isometric-ui__adress-barr" fill="#FFF" points="115.84 73.761 496.047 301.127 479.518 310.992 99.281 83.615 115.799 73.729" /> 
          <polygon class="isometric-ui__right-square" fill="#FFF" points="497.893 320.9 514.901 311.003 531.93 320.878 514.911 330.775" /> 
          <g class="isometric-browser__isometric-controls" transform="translate(76.818)"> 
            <ellipse class="isometric-controls__close" cx="4.145" cy="3.211" fill="#EC6565" rx="2.22" ry="3.987" 
              transform="rotate(-89.69 4.145 3.211)" /> 
            <ellipse class="isometric-controls__hide" cx="14.003" cy="8.981" fill="#FBBF58" rx="2.22" ry="3.987" 
              transform="rotate(-89.69 14.003 8.981)" /> 
            <path class="isometric-controls__maximize" fill="#59B35D" d="M26.9041145,16.8068861 C25.196737,17.7100744 23.1746405,17.7100744 21.467263,16.8068861 C19.9627907,15.9149605 19.952415,14.4534922 21.467263,13.5830588 C23.1722353,12.6852743 25.1887665,12.6852743 26.8937388,13.5830588 C27.5264814,13.8742793 27.9614289,14.4926594 28.0350626,15.2057185 C27.9689733,15.9134093 27.5353214,16.5273625 26.9041145,16.8068861 Z" /> 
          </g> 
        </g> 
        <g class="isometric-browser__isometric-nav" fill="#C7C6C6" fill-rule="nonzero" transform="translate(322 76.81)"> 
          <g class="isometric-nav__isometric-menu" transform="translate(66.37 34.423)"> 
            <path class="anime slideInDown isometric-menu__menu-item1" d="M5.18518519,1.00041887 L2.07407407,2.82914154 C0.414814815,3.82956041 0.414814815,5.43238205 2.07407407,6.42204373 L23.4266667,19.2123452 C25.3133218,20.2069057 27.544456,20.2069057 29.4311111,19.2123452 L32.48,17.3728654 C34.1392593,16.3724465 34.1392593,14.7588677 32.48,13.769206 L11.1792593,1.00041887 C9.29344256,0.0181124553 7.07100188,0.0181124553 5.18518519,1.00041887 Z" /> 
            <path class="anime slideInDown isometric-menu__menu-item2" d="M55.7718519,29.6145501 L52.6607407,31.4540299 C51.0014815,32.4436916 51.0014815,34.0572704 52.6607407,35.0469321 L74.0133333,47.8372336 C75.8999885,48.8317941 78.1311226,48.8317941 80.0177778,47.8372336 L83.0666667,46.0085109 C84.7259259,45.0080921 84.7259259,43.3945132 83.0666667,42.3940944 L61.7555556,29.6360644 C59.8766311,28.647169 57.65734,28.6391896 55.7718519,29.6145501 Z" /> 
            <path class="anime slideInDown isometric-menu__menu-item3" d="M105.124444,59.4765155 L102.013333,61.3159954 C100.354074,62.3056571 100.354074,63.9192359 102.013333,64.9088976 L123.407407,77.6991991 C125.294063,78.6937596 127.525197,78.6937596 129.411852,77.6991991 L132.460741,75.8597192 C134.12,74.8700575 134.12,73.2564787 132.460741,72.2560598 L111.139259,59.4872727 C109.250639,58.4891746 107.016372,58.4851787 105.124444,59.4765155 Z" /> 
          </g> 
          <path class="anime slideInDown isometric-nav__isometric-contacts" d="M333.604444,191.155305 L330.068148,193.306743 C328.14963,194.447006 328.14963,196.308 330.068148,197.45902 L491.4,294.069362 C493.579381,295.220839 496.158397,295.220839 498.337778,294.069362 L501.925926,291.917924 C503.844444,290.766904 503.844444,288.90591 501.925926,287.765648 L340.542222,191.155305 C338.360441,190.014248 335.786225,190.014248 333.604444,191.155305 Z" /> 
          <g transform="rotate(-89.69 24.913 14.502)"> 
            <ellipse class="anime slideInRight isometric-nav__isometric-logo" cx="24.913" cy="14.502" rx="13.782" ry="24.763"></ellipse> 
          </g> 
        </g> 
        <g class="isometric-browser__isometric-slider" transform="translate(174 93.418)"> 
          <polygon class="isometric-slider__background" fill="#C7C6C6" fill-rule="nonzero" points="627.337 307.931 512.556 377.446 495.996 366.919 .611 69.763 116.201 .506 116.242 .527 611.626 297.608" /> 
          <g class="isometric-slider__navigation" stroke="#FFF" transform="translate(72.541 40.904)"> 
            <g class="anime slideInDown isometric-slider__arrow-left" stroke-wclassth="1.01"> 
              <path class="Shape" d="M0 .613558368L.642508251 49.2568964 0 .613558368zM0 .613558368L81.5778218.721200188 0 .613558368z" /> 
            </g> 
            <g transform="translate(397.94 241.118)"> 
              <g class="anime slideInDown isometric-slider__arrow-right" stroke-wclassth="1.03"> 
                <path class="Shape" d="M83.5986139.688907642L83.070099 50.4624848 83.5986139.688907642zM83.070099 50.4624848L.55960396 50.4624848 83.070099 50.4624848z" /> 
              </g> 
            </g> 
          </g> 
        </g> 
        <g transform="translate(381 207.595)"> 
          <g class="anime slideInDown isometric-browser__isometric-image" fill="#F4F4F4" fill-rule="nonzero"> 
            <path class="isometric-image__borders" d="M65.4302206,0.19393046 L0.269558824,39.292466 L75.7460294,84.5429066 L140.906691,45.455145 L65.4302206,0.19393046 Z M75.2794853,76.1715751 L13.8615441,39.3247877 L65.2125,8.52216632 L126.868897,45.2504406 L75.2794853,76.1715751 Z" /> 
            <g class="isometric-image__img" transform="translate(27.993 22.625)"> 
              <polygon class="Shape" points=".238 16.301 47.598 .226 40.724 16.926 61.387 20.751 51.092 47.384" /> 
              <ellipse class="Oval" cx="75.674" cy="16.004" rx="2.654" ry="4.784" transform="rotate(-89.69 75.674 16.004)" /> 
            </g> 
          </g> 
        </g> 
        <g class="isometric-browser__isometric-features" fill="#C7C6C6" fill-rule="nonzero" transform="translate(129 226.24)"> 
          <g transform="translate(322.214 189.64)"> 
            <g class="anime slideInDown isometric-features__isometric-feature3"> 
              <g transform="rotate(-89.69 86.017 13.78)"> 
                <ellipse class="isometric-feature3__feature-image3" cx="86.017" cy="13.781" rx="12.806" ry="23.06" /> 
              </g> 
              <g class="isometric-feature3__feature-text3" transform="translate(0 8.616)"> 
                <polygon class="feature-text3__text-short3" points="47.099 11.298 76.544 28.994 69.178 33.421 39.733 15.725" /> 
                <polygon class="feature-text3__text-middle3" points="68.38 50.633 61.013 55.059 31.569 37.352 31.652 37.299 2.932 20.055 10.298 15.628 39.743 33.324 39.66 33.378" /> 
                <polygon class="feature-text3__text-long3" points="96.011 53.422 88.635 57.849 59.231 40.164 59.19 40.131 29.942 22.543 29.921 22.564 .477 4.868 7.843 .442 37.132 18.052 37.143 18.03 66.556 35.715 66.598 35.748" /> 
              </g> 
            </g> 
          </g> 
          <g transform="translate(157.48 92.627)"> 
            <g class="anime slideInDown isometric-features__isometric-feature2"> 
              <g transform="rotate(-89.69 85.946 13.371)"> 
                <ellipse class="isometric-feature2__feature-image2" cx="85.946" cy="13.371" rx="12.806" ry="23.06" /> 
              </g> 
              <g class="isometric-feature2__feature-text2" transform="translate(0 8.654)"> 
                <polygon class="feature-text2__text-short2" points="47.027 10.864 76.471 28.57 69.105 32.986 39.66 15.29" /> 
                <polygon class="feature-text2__text-middle2" points="68.307 50.198 60.941 54.635 31.496 36.928 31.579 36.875 2.86 19.62 10.226 15.204 39.671 32.9 39.588 32.943" /> 
                <polygon class="feature-text2__text-long2" points="95.939 52.998 88.573 57.414 59.159 39.729 59.117 39.707 29.87 22.119 29.849 22.13 .404 4.433 7.77 .018 37.06 17.617 37.081 17.606 66.484 35.291 66.525 35.313" /> 
              </g> 
            </g> 
          </g> 
          <g class="anime slideInDown isometric-features__isometric-feature1"> 
            <g transform="rotate(-89.69 86.497 13.147)"> 
              <ellipse class="isometric-feature1__feature-image1" cx="86.497" cy="13.147" rx="12.806" ry="23.06" /> 
            </g> 
            <g class="isometric-feature1__feature-text1" transform="translate(0 8.616)"> 
              <polygon class="feature-text1__text-short1" points="47.565 11.675 77.021 29.382 69.644 33.798 40.199 16.102" /> 
              <polygon class="feature-text1__text-middle1" points="68.846 51.01 61.49 55.436 32.035 37.729 32.128 37.676 3.398 20.432 10.765 16.005 40.209 33.701 40.127 33.755" /> 
              <polygon class="feature-text1__text-long1" points="96.478 53.799 89.111 58.226 59.698 40.541 59.656 40.519 30.408 22.92 30.398 22.941 .943 5.245 8.32 .819 37.599 18.429 37.619 18.407 67.033 36.092 67.064 36.125" /> 
            </g> 
          </g> 
        </g> 
      </g> 
    </svg> 
</div>

READ ALSO
как повесить событие на часть элемента? Элемент Canvas

как повесить событие на часть элемента? Элемент Canvas

Есть элемент canvas, нужно чтобы событие клика отрабатывало только в одной части этого элементаПодскажите идеи, пожалуйста

117
Привязка к каптче

Привязка к каптче

Как можно сделать так, чтобы до введения каптчи кнопка "зарегистрироваться" была не активна, а после ввода становилась активной?

99
v-bind:key в v-for error

v-bind:key в v-for error

У меня есть переменная file_url в которая может содержать любое количество адресов для загрузки файлов или не содержать вовсеЯ пытаюсь вывести...

123