2012-06-08 6 views
1

Я создал монтированный анимированный SVG-файл с более чем 3000 дорожками. Каждый путь анимируется независимо, используя декларативные анимации SMIL. Он играет медленно, но красиво во всех новых браузерах, используя небольшой js-резерв для IE9. (Я бы опубликовал ссылку, но это ничего не разъясняло.)Сбой SMIL-анимации при динамически загружаемом внешнем SVG

Я разработал страницу с использованием HTML5 и встроенного SVG. Так же, как я заканчивал, я понял, что не хочу заставлять мобильные браузеры задыхаться от этого огромного файла. Поэтому я переместил svg во внешний файл и снова добавил все объявления xml. Я вызываю внешний svg после того, как важная информация на странице уже отображена, используя некоторую условную логику и некоторый учебник ajax:

function loadThatSvg(){ 
    var xhr = new XMLHttpRequest; 
    xhr.open('get','floral.svg',true); 
    xhr.onreadystatechange = function(){ 
     if (xhr.readyState === 4) { 
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) { 
       var flowers = xhr.responseXML.getElementById('floralpaths'); 
       var stage = document.getElementById('stage'); 
       stage.appendChild(flowers); 
      } 
     } 
    }; 
    xhr.send(null); 
} 

window.onload = function(){ 
    setTimeout(loadThatSvg,3000); 
} 

Инструменты инспектора в различных браузерах показывают, что файл загружается правильно. Проблема в том, что анимация никогда не срабатывает, поэтому ничего не происходит! Они там в DOM. Я их вижу. Но любой таймер или событие, которое запускает анимацию SMIL в разметке, как представляется, не относится к динамически загружаемым элементам анимации.

Но тогда я прочитал this bug report о Bugzilla, в котором основное внимание уделяется этому варианту использования, и предполагает, что проблема решена (хотя для моих тестов в FF13 явно нет). Hmm ...

Есть ли какая-то пользовательская функция или объявление, которое я могу использовать для запуска часов анимации SMIL в динамически загружаемом SVG-содержимом? Даже если ответ будет плоским, «нет», было бы хорошо, если бы такие люди, как я, знали одно или другое. Спасибо за любые разъяснения!

UPDATE:

Вот исходный файл SVG. Он работает в FF, Opera и Webkit. Будьте терпеливы, пожалуйста:

http://bit.ly/LC3LEQ

А вот страница, что ссылки в тот же файл SVG, из того же домена. Я изменил заявление AppendChild в моем предыдущем коде включить метод adoptNode(), который получает его работы в FF13 и Opera 11.64, но анимация не все еще никогда не стартовал в WebKit:

http://bit.ly/Mk0lnz

+1

Вы уверены, что загруженный svg находится в правильном пространстве имен? Вероятно, вы должны использовать stage.appendChild (document.importNode (цветы, истина)). Если вы все еще застряли, то предоставление полного примера в Интернете было бы полезно. –

+0

Спасибо, Роберт. Я уверен, что вы правы, но можете ли вы объяснить, почему использовать importNode()? Кроме того, если я перехожу на этот маршрут, вы можете объяснить разницу между importNode() и acceptNode()? В чем разница между «копированием» и «перемещением» узлов? Документы неясны. Похоже, что acceptNode был бы более уместным в этом случае, так как я хочу все поддерево SVG (предполагая, конечно, что поддержка браузера есть). – Ben

ответ

0

Есть множество ошибок в Webkit происходит здесь:

https://bugs.webkit.org/show_bug.cgi?id=82647

https://bugs.webkit.org/show_bug.cgi?id=74801

Единственный способ, которым я был в состоянии получить анимации, идущие в Webkit было перебрать их, получить целевые значения из разметки svg и анимировать их вручную с помощью jquery animate(). Ни один из специальных методов svg не работал для меня.

2

Там некоторые способы, которыми вы можете это сделать. Обратите внимание, что я предположил, что вы уже ввели анимированный документ в основной документ.

Первый путь, начав анимации с помощью сценария:

  • получить каждый элемент анимации, который вы хотите вызвать, а затем вызвать beginElement() на нем

Второй способ сбросить текущее время в документе, к которому относятся элементы анимации.Это может работать, вы должны проверить и посмотреть:

  • получить корневой элемент SVG анимированного документа, и вызовите setCurrentTime(0) на него

Если вы идете на второй, и не работает, вы можете также попробовать паузу и Изменение вступит, как это:

+0

Спасибо Эрик. См. Обновление выше. Ваш первый метод (итерация по всем путям) не работает для меня. Вот ссылка: http://bit.ly/KQjcuU. Две проблемы. Во-первых, FF выдает ошибку, указывающую, что параметр beginElementAt() в элементе «set» является незаконным. Тем не менее, анимация работает в любом случае с методом acceptNode(), как и раньше, в FF, поэтому никакого вреда не было сделано. Chrome, однако, полностью падает на этой странице. Я немного беспомощно пытаюсь отлаживать без консоли в Chrome! Кроме того, beginElement() и beginElementAt() работают над элементами «set» или просто «анимируют» элементы? Спецификации/документы неясны. – Ben

+0

Мне нужны элементы 'set', которые нужно искать вместе с анимированными элементами, потому что элементы 'set' работают над известной ошибкой в ​​Chrome с 'fill = "freeze", которая не работает корректно в анимированных элементах. (Это исправлено в Canary builds of Chrome, но мне это нужно на данный момент.) Кроме того, некоторые документы говорят, что beginElement() работает только с анимированными элементами, которые имеют значение разметки begin = "indefinite", что явно не так. , Наконец, я попробовал обе версии вашего второго метода (сброс таймера). См. Вторую ссылку в обновлении. В Webkit ни один из методов не работает. – Ben

+0

с использованием setCurrentTime работает в текущих версиях Chrome (32), но не в Safari. – stevendaniels

Смежные вопросы