我想创建一个动画,该动画是由几个“组件”的运动产生的。目前,我对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/
哪个是通过javascript创建具有自定义属性的svg实例的好方法?
答案 0 :(得分:2)
必须使用document.createElementNS
方法创建SVG元素,并显式提供SVG名称空间URI“ http://www.w3.org/2000/svg”。
通常可以使用元素的setAttribute
或setAttributeNS
方法添加svg元素的属性值。
如果使用xlink:
添加带有前缀setAttribute
的属性名称,则不能正常使用-请将setAttributeNS
与xlink名称空间URI“ http://www.w3.org/1999/xlink”一起使用。
请注意,deprecated in SVG2为xlink:
属性使用href
前缀,而使用了没有前缀的名称“ href”。
另请参见:Namespaces Crash Course在MDN上
尝试通过将属性值设置为svg元素的属性名称来设置属性值,如果 property 是只读的,则会导致失败。与属性同名的SVG属性可能有一个getter(不带setter),并返回一个实现SVG animated length或 SVGAnimatedString接口的对象。
例如,
svgElement.className
可能是只读的-最好使用setAttribute("class", value)
或element.classList.add(name, value)
代替。参见className notes。
circleShape.r
是只读的(其他元素的可动画属性的其他属性名称也是如此)。参见SVGCircleElement properties。
请注意,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
,但是它不起作用。记录创建的元素并在一个浏览器中进行向下钻取,只是停止列出mpath元素的外部HTML,不幸的是,该HTML与在source中创建的元素相同。另一个浏览器允许我进一步深入研究,以发现内部属性值与源代码中的mpath
元素设置不同。
animateMotion
,animateTransform
或已弃用的animateColor
元素的SVG动画基于SMIL animation W3C standard。 Microsoft浏览器不支持SMIL,并且Microsoft先前已声明不考虑支持。在编写本文时,该示例在Edge中不起作用。