如何使用 javascript 生成 SMIL

How to generate SMIL with javascript

我正在尝试用 SMIL 生成一个 svg 并且很难弄清楚为什么它不起作用。

代码如下

// targeting the svg itself
const svg = document.querySelector("svg");

// variable for the namespace 
const svgns = "http://www.w3.org/2000/svg"

//assigning svg element attribute 
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', '0 0 1280 720');

let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", '1280');
bg.setAttribute("height", '720');
bg.setAttribute("fill", "#F1C40F");
svg.appendChild(bg);

let pth = document.createElementNS(svgns, 'path');
pth.setAttribute('class', 'pth');
pth.setAttribute('id', 'pth');
pth.setAttribute('d',
    'M10,20, L110,20, L110,140, L10,140 ,Z'
);
pth.style.setProperty("stroke-width", ".5");
pth.style.setProperty("stroke", "red");
pth.setAttribute('fill', 'red');

svg.appendChild(pth);

let anim = document.createElementNS(svgns, 'animate');
anim.setAttribute('attributeName', 'd');
anim.setAttribute('attributeType', 'XML');
anim.setAttribute('values', "M10,20, L110,20, L110,140, L10,140 ,Z; M10,20, L210,20, L210,140, L10,140 ,Z; M10,20, L110,20, L110,140, L10,140 ,Z");
anim.setAttribute('keyTimes', '0;0.5;1');
anim.setAttribute('begin', '0s');
anim.setAttribute('end', '1s');
anim.setAttribute('repeatCount', 'indefinite');
svg.appendChild(anim);
pth.appendChild(anim);
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <link rel="stylesheet" href="style.css">
    </link>
    <svg>
        <script href="index.js"></script>
        <!--
        <rect class="bg" id="bg" width="1280" height="720" fill="#F1C40F"></rect>
        <path class="pth" id="pth" d="M10,20, L110,20, L110,140, L10,140 ,Z" fill="red"
            style="stroke-width: 0.5; stroke: red;">
            <animate attributeName="d" 
                attributeType="XML" 
                values=
                "M10,20, L110,20, L110,140, L10,140 ,Z
                ;M10,20, L210,20, L210,140, L10,140 ,Z
                ;M10,20, L110,20, L110,140, L10,140 ,Z" 
                keyTimes="0;.5;1"
                begin="0s"
                dur="1s" 
                repeatCount="indefinite"
                />
        </path>-->
    </svg>

</html>

但是,未注释的 SVG 可以与 SMIL 一起正常工作

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <link rel="stylesheet" href="style.css">
    </link>
    <svg>
        <script href="index.js"></script>
        
        <rect class="bg" id="bg" width="1280" height="720" fill="#F1C40F"></rect>
        <path class="pth" id="pth" d="M10,20, L110,20, L110,140, L10,140 ,Z" fill="red"
            style="stroke-width: 0.5; stroke: red;">
            <animate attributeName="d" 
                attributeType="XML" 
                values=
                "M10,20, L110,20, L110,140, L10,140 ,Z
                ;M10,20, L210,20, L210,140, L10,140 ,Z
                ;M10,20, L110,20, L110,140, L10,140 ,Z" 
                keyTimes="0;.5;1"
                begin="0s"
                dur="1s" 
                repeatCount="indefinite"
                />
        </path>
    </svg>

</html>

更新

动画效果很好,具有完全相同的 d 值以及 begindur

// targeting the svg itself
const svg = document.querySelector("svg");

// variable for the namespace 
const svgns = "http://www.w3.org/2000/svg"

//assigning svg element attribute 
/*
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', '0 0 1280 720');
*/
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", '1280');
bg.setAttribute("height", '720');
bg.setAttribute("fill", "#F1C40F");
svg.appendChild(bg);

let pth = document.createElementNS(svgns, 'path');
pth.setAttribute('class', 'pth');
pth.setAttribute('id', 'pth');
pth.setAttribute('d',
    'M10,20, L110,20, L110,140, L10,140 ,Z'
);
pth.style.setProperty("stroke-width", ".5");
pth.style.setProperty("stroke", "red");
pth.setAttribute('fill', 'red');

svg.appendChild(pth);

let anim = document.createElementNS(svgns, 'animate');
anim.setAttribute('attributeName', 'd');
anim.setAttribute('attributeType', 'XML');
anim.setAttribute('values', "M10,20, L110,20, L110,140, L10,140 ,Z; M10,20, L210,20, L210,140, L10,140 ,Z; M10,20, L110,20, L110,140, L10,140 ,Z");
anim.setAttribute('keyTimes', '0;0.5;1');
anim.setAttribute('begin', '2s');
anim.setAttribute('dur', '1s');
anim.setAttribute('repeatCount', 'indefinite');
svg.appendChild(anim);
pth.appendChild(anim);
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <svg>
        <script href="index.js"></script>-
        <!--
        <rect class="bg" id="bg" width="1280" height="720" fill="#F1C40F"></rect>
        <path class="pth" id="pth" d="M10,20, L110,20, L110,140, L10,140 ,Z" fill="red"
            style="stroke-width: 0.5; stroke: red;">
            <animate attributeName="d" 
                attributeType="XML" 
                values="M10,20, L110,20, L110,140, L10,140 ,Z; M10,20, L210,20, L210,140, L10,140 ,Z; M10,20, L110,20, L110,140, L10,140 ,Z"                
                keyTimes="0;.5;1"
                begin="2s"
                dur="1s" 
                repeatCount="indefinite"
                />
        </path>-->
    </svg>

</html>

我通过删除逗号(字母前不允许,谢谢,@ccprog)清理了 d 值,删除了 beginend 属性并添加了 dur 属性。就是这样。

更新

如果您将 begin 属性设置为“不确定”,动画将开始,然后您在 <animate> 上调用函数 beginElement()。这里我加了一个setTimeout()来说明。

// targeting the svg itself
const svg = document.querySelector("svg");

// variable for the namespace 
const svgns = "http://www.w3.org/2000/svg"

//assigning svg element attribute 
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', '0 0 1280 720');

let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", '1280');
bg.setAttribute("height", '720');
bg.setAttribute("fill", "#F1C40F");
svg.appendChild(bg);

let pth = document.createElementNS(svgns, 'path');
pth.setAttribute('class', 'pth');
pth.setAttribute('id', 'pth');
pth.setAttribute('d', 'M 10 20 L 110 20 L 110 140 L 10 140 Z');
pth.style.setProperty("stroke-width", ".5");
pth.style.setProperty("stroke", "red");
pth.setAttribute('fill', 'red');

svg.appendChild(pth);

let anim = document.createElementNS(svgns, 'animate');
anim.setAttribute('attributeName', 'd');
anim.setAttribute('attributeType', 'XML');
anim.setAttribute('values', "M 10 20 L 110 20 L 110 140 L 10 140 Z;M 10 20 L 210 20 L 210 140 L 10 140 Z;M 10 20 L 110 20 L 110 140 L 10 140 Z");
anim.setAttribute('keyTimes', '0;.5;1');
anim.setAttribute('begin', 'indefinite');
anim.setAttribute('dur', '2s');
anim.setAttribute('repeatCount', 'indefinite');
svg.appendChild(anim);
pth.appendChild(anim);

setTimeout(function(){anim.beginElement();}, 2000);
<svg></svg>