Подтвердить что ты не робот

Почему переходы на svg не работают на DOMContentLoaded без задержки?

У меня есть svg с установленными на нем переходами. Теперь, когда я добавляю к нему класс, у которого есть некоторые свойства, тогда переход происходит только в том случае, если я добавляю задержку между событием DOMContentLoaded и событием addclass. Вот два примера: сначала без задержки второй с бесконечно малой задержкой:

Без задержки:

! function() {
  window.addEventListener('DOMContentLoaded', function() {
    var logo2 = document.querySelector("svg");
    logo2.classList.add('start');
  });
}();
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 104.75 32.46">
            <defs>
                <style>
                polygon {
                    fill: red;
                    transition: opacity 3s ease-out, transform 3s ease-out;
                    opacity: 0;
                }

                .start polygon {
                	opacity: 1;
                }
				
				#A1 polygon {
					transform: translate(100px, 100px);
					transition-delay: 1s;
				}

				/*styles after animation starts*/
				.start #A1 polygon {
					transform: translate(0px, 0px);						
				}


            </style>
            </defs>
            <title>Logo</title>
            <g id="A1">
                
                <polygon  class="right" points="0.33 31.97 0.81 26.09 13.61 3.84 13.13 9.72 0.33 31.97" />
            </g>
            </svg>
4b9b3361

Ответ 1

Потому что то, что DOMContentLoaded делает: он срабатывает, когда DOM анализируется, но до того, как CSSOM был (и, следовательно, перед стилями были применены).

Если вы не хотите ждать события load,
одним из способов является заставить браузер рисовать перед выполнением script (синхронно), вызывая свойство offsetXXX для любого элемента документа (например, <body>):

! function() {
  window.addEventListener('DOMContentLoaded', function(){
    document.body.offsetTop; // force a CSS repaint
    var logo2 = document.querySelector("svg");
    logo2.classList.add('start');
  });
}();
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 104.75 32.46">
  <defs>
    <style>
      polygon {
        fill: red;
        transition: opacity 3s ease-out, transform 3s ease-out;
        opacity: 0;
      }
      .start polygon {
        opacity: 1;
      }
      #A1 polygon {
        transform: translate(100px, 100px);
        transition-delay: 1s;
      }
      /*styles after animation starts*/
      .start #A1 polygon {
        transform: translate(0px, 0px);
      }
    </style>
  </defs>
  <title>Logo</title>
  <g id="A1">
    <polygon class="right" points="0.33 31.97 0.81 26.09 13.61 3.84 13.13 9.72 0.33 31.97" />
  </g>
</svg>

Ответ 2

Как вы можете видеть во втором примере, я добавил задержку в 0 секунд, но она заставил анимацию работать, почему?

Так как объектная модель CSS не была загружена, когда событие DOMContentLoaded запускает

Событие DOMContentLoaded запускается, когда исходный HTML-документ был полностью загружен и проанализирован, не дожидаясь таблиц стилей, изображений и подкадров для завершения загрузки. Очень различная загрузка события следует использовать только для обнаружения полностью загруженной страницы. Это невероятно популярной ошибкой использовать нагрузку, где DOMContentLoaded будет намного больше поэтому будьте осторожны.

https://developer.mozilla.org/en/docs/Web/Events/DOMContentLoaded

Итак, добавление класса css не приведет к анимации.

Метод setTimeOut является событием javascript, после его запуска (даже с 0 раз) он будет добавлен в конец текущей очереди выполнения браузера (который в вашем случае будет добавлен после загрузки модели CSS). Следовательно, анимация будет срабатывать должным образом.

Update:

Но jquery domready запускается после загрузки CSSOM. Итак, все эти сообщения на SO технически неверны?

domready использует DOMContentLoaded так теоретически, они ведут себя одинаково.

Отложенные теги script (как встроенные, так и внешние), выполненные до Загружается CSSOM

script, отложенный атрибутом defer, выполняется до запуска DOMContentLoaded. Итак, ответ ДА.