CSS-переход не запускается/обратный вызов не вызывается

У меня есть большой игровой проект, в коде которого используется обширный jquery. Некоторое время назад я удалил весь jquery и заменил его чистым JS, но единственное, с чем у меня возникли проблемы, это замена вызовов .animation для снарядов в игре.

Оказалось, что я должен заменить их переходами CSS, а игре нужно было знать, когда переход был выполнен, поэтому мне нужно было добавить обратный вызов к переходу. Все хорошо, за исключением того, что когда я назначал новые значения местоположения для снаряда, переход был полностью пропущен, и обратный вызов не вызывался. По какой-то безбожной причине он начал работать, если я обернул изменение его позиции css в SetTimeout на 1 мс - и даже тогда иногда он все равно пропускал переход.

Теперь это обычно работает, за исключением примерно одного раза из 10, когда переход будет воспроизводиться, но тогда обратный вызов не будет вызван. Я не знаю, почему settimeout помогает быть там, и я не знаю, почему обратный вызов иногда не работает. Может ли кто-нибудь помочь мне понять?

let tablehtml = '<div id = "'+animid+'" style = "position: absolute; left: ' + ammocoords.fromx + 'px; top: ' + ammocoords.fromy + 'px; background-image:url(\'graphics/' + ammographic.graphic + '\');background-repeat:no-repeat; background-position: ' + ammographic.xoffset + 'px ' + ammographic.yoffset + 'px; transition: left '+duration+'ms linear 0s, top '+duration+'ms linear 0s;"><img src = "graphics/spacer.gif" width = "32" height = "32" /></div>';

document.getElementById('combateffects').innerHTML += tablehtml;
let animdiv = document.getElementById(animid);
animdiv.addEventListener("transitionend", function(event) { 
  FinishFirstAnimation();
}, false);

setTimeout(function() { Object.assign(animdiv.style, {left: ammocoords.tox+"px", top: ammocoords.toy+"px" }); }, 1); // THIS IS A TOTAL KLUDGE
// For some reason, the transition would not run if the 1ms pause was not there. It would skip to the end, and not
// fire the transitionend event. This should not be necessary.
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
0
473
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

это связано со временем, когда новый элемент фактически "нарисован"...

Я знаю, что это тоже кладж, но...

единственный способ, который я обнаружил, чтобы гарантировать 100% успех, - это подождать чуть менее двух кадров (при 60 кадрах в секунду это около 33,333 мс - но в браузерах в наши дни добавлена ​​​​искусственная "выдумка" из-за призрака или чего-то еще - в любом случае .. .

setTimeout делает то же самое, за исключением того, что задержка может составлять всего 16,7 мс, то есть чуть более одного кадра.

let tablehtml = `
	<div id = "spanky" 
  	style = "position: absolute; 
    	left: 10px; 
      top: 10px; 
      background-color:blue; 
      width:20px; 
      height:20px;
      transition: left 1000ms linear 0s, top 1000ms linear 0s;">
</div>`;

document.body.innerHTML += tablehtml;
let animdiv = document.getElementById('spanky');
animdiv.addEventListener("transitionend", function(event) { 
  animdiv.style.backgroundColor='red';
}, false);
requestAnimationFrame(() => requestAnimationFrame(() => {
  animdiv.style.backgroundColor='green';
	Object.assign(animdiv.style, {
		left: "100px", 
  	top: "100px" 
	}); 
}));

одиночный requestAmiationFrame(() => requestAnimationFrame() => { ... your code ...})) потерпел неудачу примерно в 1 случае из 10 для меня, но двойной запрос делает невозможным провал

Ответ принят как подходящий

Подробное объяснение того, почему это происходит, см. в статьях этот вопрос/ответ и Вот этот.

По сути, в то время, когда вы устанавливаете новый style, браузер все еще не применил встроенный набор, вычисляемый стиль вашего элемента все еще имеет значение display, установленное на "" , потому что это элементы, которых нет в DOM по умолчанию. Его вычисленные значения left и top по-прежнему равны 0px, даже если вы установили его в разметке.

Это означает, что когда свойство transition будет применено перед отрисовкой следующего кадра, left и top уже будут теми, которые вы установили, и, таким образом, переходу нечего будет делать: он не сработает.

Чтобы обойти это, вы можете заставить браузер выполнить этот пересчет. Действительно, некоторые методы DOM нуждаются в обновлении стилей, и поэтому браузеры будут вынуждены запускать то, что также называется перекомпоновкой. Element.offsetHeight геттер является одним из следующих методов:

let tablehtml = `
<div id = "spanky" 
  style = "position: absolute; 
    left: 10px; 
    top: 10px; 
    background-color:blue; 
    width:20px; 
    height:20px;
    transition: left 1000ms linear 0s, top 1000ms linear 0s;">
</div>`;

document.body.innerHTML += tablehtml;

let animdiv = document.getElementById('spanky');
animdiv.addEventListener("transitionend", function(event) { 
  animdiv.style.backgroundColor='red';
}, false);
// force a reflow
animdiv.offsetTop;
// now animdiv will have all the inline styles set
// it will even have a proper display

animdiv.style.backgroundColor='green';
Object.assign(animdiv.style, {
  left: "100px", 
  top: "100px" 
});

Хорошо - никогда не рассматривал возможность форсирования перекомпоновки!

Jaromanda X 14.03.2019 10:26

Другие вопросы по теме