Лучший способ создания модульной SVG-анимации - PullRequest
0 голосов
/ 18 апреля 2019

Я хочу создать анимацию, которая возникает в результате движения нескольких «компонентов». На данный момент я вручную кодирую теги SVG, но нацеливаюсь на их создание; Вот как выглядит один из моих компонентов и мой код:

<g style="transform-origin:39%;transform: rotate(180deg);">
   <circle id="pippo" cx="0" cy="0" r="5" fill="#333333">
       <animateMotion dur="0.7s" repeatCount="once" fill="freeze"
calcMode="spline" keyTimes="0;1" keySplines="0.27 0 0 1">
           <mpath xlink:href="#shorterPath"/>
       </animateMotion>
   </circle>
</g>

https://jsfiddle.net/fillotassi/by3Lxf0h/19/

Какой хороший способ создания экземпляров SVG с пользовательскими свойствами с помощью javascript?

1 Ответ

2 голосов
/ 25 апреля 2019

Создание динамических 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 на момент написания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...