Перезапустить фоновую анимацию SVG

У меня есть SVG, установленный в качестве фонового изображения элемента. При первом отображении элемента анимация воспроизводится правильно.

При последующих отображениях (например, если дубликат элемента вводится через JavaScript или если фоновое изображение удаляется и добавляется обратно с помощью CSS/JavaScript), анимация не начинается с самого начала. Я думаю, что это предполагаемая функциональность, поскольку изображение не считается перезагруженным браузером - он использует версию в памяти, которая уже анимируется.

Вот демонстрация этого (не моя): http://www.luigifab.info/public/svg-smil/test.html

Существуют некоторые связанные отчеты об ошибках браузера для Firefox и Chrome, но, как и выше, я думаю, что это предполагаемая функциональность.

Есть ли способ заставить мою анимацию SVG сбрасываться/воспроизводиться всякий раз, когда отображается изображение?

В идеале я ищу решение, использующее только CSS и SVG, иначе решение с JavaScript, если это невозможно.


person Alasdair McLeay    schedule 04.10.2013    source источник
comment
Ваши изображения SVG не отображаются правильно..? это проблема..?..   -  person Vivek Vikranth    schedule 04.10.2013
comment
SVG отображаются, они просто не анимируются на последующих дисплеях. Если вы нажмете демонстрационную ссылку выше, а затем нажмете «показать», вы увидите анимацию SVG. Нажмите «скрыть», затем снова «показать», и SVG не будет анимироваться.   -  person Alasdair McLeay    schedule 04.10.2013
comment
Можете ли вы показать мне свой код Animate..?   -  person Vivek Vikranth    schedule 05.10.2013
comment
Он использует анимацию SVG, код аналогичен SVG, используемому в демонстрационной ссылке выше: luigifab.info/public/svg-smil/error.svg.php   -  person Alasdair McLeay    schedule 05.10.2013


Ответы (7)


Как сказал @netsurfer, я решил эту проблему, используя файл object. Вот пример:

<object type="image/svg+xml" data="my.svg"></object>

Каждый раз, когда я динамически вставляю SVG object, анимация начинается с самого начала.

person IvanRF    schedule 26.05.2017

Я думаю, что ваше предположение «... поскольку изображение не считается перезагруженным браузером - он использует версию в памяти, которая уже анимируется», верно, поскольку файл SVG кэшируется! Таким образом, без (настоящей) «перезагрузки» анимация не запускается (снова).

Ну, во-первых, давайте посмотрим на анимацию SVG. Внутри элемента анимации можно использовать два атрибута, которые используются для повторения анимации — см. Повторяющиеся анимации и Элемент 'animate' . В вашем случае анимация запускается только один раз (без повторения).

Таким образом, вам понадобится Javascript, чтобы как-то «запустить» анимацию.
В принципе это возможно (пример: Расширенные методы анимации SVG), но только в том случае, если файл SVG является частью модели DOM, доступ к которой можно получить через Javascript. Поэтому вы должны включить файл SVG как <object>.

Как только вы используете файл SVG в теге <img> или в качестве CSS background-image, у вас нет доступа к файлу с помощью сценария.

Таким образом, единственный способ, который я мог придумать для достижения вашей цели, — запретить браузеру кэшировать файл SVG (см. Как (и как нельзя) управлять кешем) или использовать файл SVG в элементе <object>, чтобы можно было управлять анимацией через Javascript.

Кстати: ответ luigifab не так уж и плох. Это часто используемый «трюк» для принудительной перезагрузки файла/изображения — см. Трюк с кэшем< /а>

person Netsurfer    schedule 28.01.2014

Можно изменить URL-адрес изображения, чтобы принудительно перезагрузить браузер.

person luigifab    schedule 11.11.2013
comment
Менять его каждый раз, когда кто-то заходит на страницу!? - person Display Name is missing; 11.11.2013

Реализация для ответа luigifab. поместите немного random things в конце параметра URL, это заставит браузер думать, что ресурс является «новым ресурсом». Демо

person AzDesign    schedule 30.01.2014

Это сработало для меня, просто добавив и удалив класс «play» в элемент div, добавив setTimeout для задержки classList.add('play'), чтобы класс можно было удалить, а затем применить

CSS

@keyframes play60 {
        0% {
            background-position: 0px 0px;
        }
        100% {
            background-position: -38400px 0px;
        }
    }
    .shapeshifter {
        animation-duration: 1000ms;
        animation-timing-function: steps(60);
        animation-fill-mode: forwards;
        width: 640px;
        height: 640px;
        background-repeat: no-repeat;
    }
    .shapeshifter.play {
        animation-name: play60;
    }

JS:

document.getElementById('shape').addEventListener('mouseover', () => {
    document.getElementById('shape').classList.remove('play')
    setTimeout(() => {
        document.getElementById('shape').classList.add('play');
    }, 1)
})

HTML

<div class="shapeshifter " id="shape" style="background-image: url(shape.svg)"></div>
person Stefan Avramovic    schedule 16.09.2019

Используйте случайный ключ в URL-адресе для очистки кеша. Хотя в вашем примере нет длинной анимации для правильной проверки, я добавил повторение загрузки изображения, чтобы разница была заметна.

url + "&" + Math.random()

Демо без перезагрузки с постоянным URL: http://jsfiddle.net/4ZBLr/8/

Перезагрузить демонстрацию со случайным URL-адресом: http://jsfiddle.net/4ZBLr/9/

person DhruvPathak    schedule 31.01.2014
comment
В 2020 году &, похоже, разорвет ссылку на изображение в Chrome и FF. Использование # или ? вместо этого, кажется, работает. - person V. Rubinetti; 22.07.2020

Я думаю, что во многих случаях setCurrentTime(0) является лучшим решением, если оно поддерживается браузером. Вот пример (при условии, что вы используете тег <object> для встраивания, конечно):

let content = document.getElementById("object-id").contentDocument;
let svg = content.getElementsByTagName("svg")[0];
if(svg.getCurrentTime() > 10)
  svg.setCurrentTime(0);

Дополнительную информацию о соответствующем API можно найти здесь: https://developer.mozilla.org/en-US/docs/Web/API/SVGSVGElement

person Martin R.    schedule 28.05.2017