SVG переход не работает

1

Пока нет индекса z для SVG, я заставил мои прямоугольники менять z-позицию с помощью DOM-манипуляций. Однако у меня есть новая проблема. По какой-то причине переход перестает работать. Я подозреваю, что это связано с переупорядочиванием DOM, но я должен использовать его таким образом.

function redZ() {
  document.getElementById('svgField').appendChild(document.getElementById('redRect'));
  document.getElementById('redRect').style.transition = "2s linear";
  document.getElementById('redRect').style.fill = "black";
}

function blueZ() {
  document.getElementById('svgField').appendChild(document.getElementById('blueRect'));
  document.getElementById('blueRect').style.transition = "2s linear";
  document.getElementById('blueRect').style.fill = "yellow";
}
<svg width="180" height="150" id="svgField">
   <rect onclick="redZ()" id="redRect" x="0" y="0" width="100" height="100" fill="red" />
   <rect onclick="blueZ()" id="blueRect" x="60" y="40" width="100" height="100" fill="blue" />
</svg>
  • 0
    В зависимости от общей структуры вашего фактического SVG, у вас есть возможность разделить элементы в SVG на отдельные элементы <svg> и применить к ним z-index .
Теги:
svg

2 ответа

0
Лучший ответ

Это, по-видимому, проблема с перерисовкой, вызванной манипуляциями DOM. Следующий пример не очень изящный, но установка тайм-аута с низким значением в миллисекундах (в некоторых случаях вы могли бы иметь немного более высокое значение 50/100 мс) часто может решить проблемы, связанные с перерисовкой, в качестве крайней меры.

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

document.getElementById('redRect').style.transition = "2s linear";
document.getElementById('blueRect').style.transition = "2s linear";

function redZ() {
  document.getElementById('svgField').appendChild(document.getElementById('redRect'));
  window.setTimeout(function() {
    document.getElementById('redRect').style.fill = "black";
  }, 10);
}

function blueZ() {
  document.getElementById('svgField').appendChild(document.getElementById('blueRect'));
  window.setTimeout(function() {
    document.getElementById('blueRect').style.fill = "yellow";
  }, 10);
}
<svg width="180" height="150" id="svgField">
   <rect onclick="redZ()" id="redRect" x="0" y="0" width="100" height="100" fill="red" />
   <rect onclick="blueZ()" id="blueRect" x="60" y="40" width="100" height="100" fill="blue" />
</svg>
  • 1
    «Похоже, это проблема перерисовки, вызванной манипулированием DOM». - точнее говоря, это проблема с передачей «управления» движку рендеринга. Все манипуляции с DOM и стилем выполняются как одна непрерывная задача. Элемент добавляется в указанную позицию DOM, а свойства CSS transition и fill устанавливаются. Только тогда это передается механизму рендеринга, который (для исходного redZ функции redZ ) смотрит на него и работает, хорошо, так что вы дали мне элемент с черным цветом заливки, [...]
  • 1
    [...] и я должен все переходить, когда некоторые свойства меняются. Понял! Дай мне проверить ... Нет, цвет заливки все еще вернулся, все остальное осталось прежним - я думаю, что мы закончили? Небольшой тайм-аут (более «современные» подходы обычно используют requestAnimationFrame ) исправляют это, потому что он передает управление рендерингу между двумя шагами, также добавляя элемент в DOM и изменяя цвет заливки - так, когда RE смотрит на это снова после изменения цвета заливки, теперь у него есть изменение, чтобы распознать это изменение в первую очередь.
Показать ещё 4 комментария
0

Вместо того, чтобы перемещать активный rect над другим rect в порядке DOM, переместите другой rect ниже активного rect. Это позволяет переходам работать должным образом.

Другими словами, когда redRect, вместо перемещения redRect в нижней части порядка DOM (так визуально сверху) переместите blueRect в верхнюю часть порядка DOM (так что визуально снизу). С:

document.getElementById('svgField').prepend(document.getElementById('blueRect'));

Как это:

function redZ() {
  document.getElementById('svgField').prepend(document.getElementById('blueRect'));
  document.getElementById('redRect').style.transition = "2s linear";
  document.getElementById('redRect').style.fill = "black";
}

function blueZ() {
  document.getElementById('svgField').prepend(document.getElementById('redRect'));
  document.getElementById('blueRect').style.transition = "2s linear";
  document.getElementById('blueRect').style.fill = "yellow";
}
<svg width="180" height="150" id="svgField">
   <rect onclick="redZ()" id="redRect" x="0" y="0" width="100" height="100" fill="red" />
   <rect onclick="blueZ()" id="blueRect" x="60" y="40" width="100" height="100" fill="blue" />
   
</svg>

Ещё вопросы

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