Создание динамических SVG-элементов и анимации в JavaScript.
* Namespaces 1003 *
Элементы SVG должны быть созданы с использованием метода document.createElementNS
с явным указанием URI пространства имен SVG "http://www.w3.org/2000/svg".
Значения атрибутов элемента svg обычно можно добавить с помощью метода setAttribute
или setAttributeNS
элемента.
Имена атрибутов с префиксом xlink:
не работают должным образом при добавлении с использованием setAttribute
- используйте setAttributeNS
с URI пространства имен xlink "http://www.w3.org/1999/xlink" вместо.
Обратите внимание, что использование префикса xlink:
для атрибутов href
было исключено в SVG2 , в пользу названия "href" без префикса.
См. Также: Ускоренный курс по пространствам имен на MDN
Свойства
Попытка установить значения атрибутов путем задания их в качестве имен свойств элементов svg может привести к сбою, когда свойство доступно только для чтения. Свойства SVG с тем же именем, что и у атрибутов, могут иметь геттер (без сеттера) и возвращать объект, реализующий анимированную длину SVG или
SVGAnimated String интерфейс.
Например,
svgElement.className
может быть только для чтения - желательно использовать setAttribute("class", value)
или element.classList.add(name, value)
. См. примечания className .
circleShape.r
только для чтения (как и другие имена свойств для анимируемых атрибутов других элементов). См. Свойства SVGCircleElement .
Пример
Обратите внимание, что вспомогательная функция createSvgElement
использует цикл for ... in
и не была записана для обработки случайных перечисляемых свойств, добавленных в Object.prototype
. Код для xlink:
имен префиксных атрибутов был протестирован, но здесь не использовался.
"use strict";
function createSvgElement( tagName, attributes) {
var element = document.createElementNS(
"http://www.w3.org/2000/svg", tagName);
if( attributes) {
for( var attr in attributes) {
if( /^xlink:/.test( attr)) {
element.setAttributeNS( "http://www.w3.org/1999/xlink",
attr, attributes[ attr]);
}
else {
element.setAttribute( attr, attributes[ attr]);
}
}
}
return element;
}
let svg = createSvgElement("svg", {
width: "200",
height: "200",
viewBox: "0 0 200 200",
style: "background:aquamarine",
});
let defs = createSvgElement("defs");
defs.appendChild(createSvgElement( "path", {
id: "verticalMotionPath",
d: "m 100,100 0, 50"
}));
defs.appendChild( createSvgElement( "path", {
id: "shorterPath",
d: "m 100,70 0, 50"
}));
svg.appendChild( defs);
function circleGroup( originTx, rotateDegrees, pathId, circleId) {
let group = createSvgElement("g");
group.style =
"transform-origin: "+originTx
+"; transform: rotate("+ rotateDegrees + "deg);";
let circle = createSvgElement("circle", { r: 5, fill: "#333333"});
let am = createSvgElement("animateMotion", {
dur:"0.7s",
repeatCount: 1,
fill: "freeze",
calcMode: "spline",
keyTimes: "0;1",
keySplines: "0.27 0 0 1"
});
am.appendChild( createSvgElement("mpath", {
"href": "#" + pathId
}));
circle.appendChild( am);
group.appendChild(circle);
return group;
}
// draw animations and append svg to body
[180, 0, 60, -60].forEach( function( angle) {
svg.appendChild( circleGroup("50%", angle, "verticalMotionPath"));
});
["61%", "39%"].forEach( function( originTx) {
svg.appendChild( circleGroup(originTx, 180, "shorterPath"));
});
document.body.appendChild( svg);
Обсуждение (в сторону)
Пример демонстрирует, как можно написать функцию, circleGroup
, для реализации анимации, показанной в посте, и многократного вызова ее для повторяющихся эффектов. Это не точно то же самое, что и скрипка из-за выбора того, что и как передавать аргументы в circleGroup
и некоторых упрощений. Они могут быть изменены в конечном приложении - или полностью переписана функция: -)
Раннее тестирование и в нескольких браузерах может помочь. Например, чтобы что-то (что-нибудь!) Работало, я вернулся к одному изменению в рабочем исходном коде, которое заключалось в удалении элемента mpath
из первой группы и создании его в JavaScript. Я неправильно использовал setAttribute
для атрибута xlink:href
, и он не работал. Регистрация созданного элемента и детализация в одном браузере остановились на выводе внешнего HTML-кода элемента mpath, который, к сожалению, был таким же, как элемент, созданный в исходном коде. Другой браузер позволил мне углубиться в детализацию, чтобы обнаружить, что значение внутреннего свойства не было таким же, как для элемента mpath
, происходящего из исходного кода.
Поддержка браузера
SVG-анимация с использованием animateMotion
, animateTransform
или устаревших animateColor
элементов основана на SMIL анимации W3C . SMIL не поддерживается браузерами Microsoft, и Microsoft ранее заявляла, что поддержка не рассматривается. Пример не работает в Edge на момент написания.