马黑黑 发表于 2024-9-11 19:39

js+svg绘制动画六边形

<style>
.artbox { position: relative; }
.artbox > p { position: relative; margin: 10px 0; font: normal 18px / 26px sans-serif; }
.artbox mark { color: black; background: lightblue; padding: 2px 4px; }
.textRed { color: red; }
.textMid { text-align: center; }
.showDiv { position: relative; display: grid; place-items: center; }
.artbox mark { background: lightblue; padding: 0 6px; }
#codebox { display: none; }
#text { width: 98%; height: 360px; padding: 8px; font-size: 16px; border: 3px solid lightblue; border-radius: 6px; resize: none; tab-size: 4; }
</style>

<div class="artbox">
        <p>实现原理:① 使用 <span class="textRed">path</span> 路径绘制一个 <mark>^</mark> 形状的图案,path图案的 <span class="textRed">d</span> 属性通过动画标签 <mark>&lt;animate&gt;&lt;/animate&gt;</mark> 以 <span class="textRed">values</span> 多值的形式动态设置路径图案动画,令 <mark>^</mark> 图案向上移动直至消失,同时同步运行另一个 animate 动画,令图像线条按粗细 <mark>0;4;4;4;0</mark> 进行循环变化。共创建六组这样的path动画,使用 <mark>&lt;defs&gt;&lt;/def&gt;</mark> 标签包裹起来留待后续引用。② 创建六组 <mark>&lt;user/&gt;</mark> 标签,每一组对标一个 <mark>^</mark> path图案,依次从 0~360 度均分旋转形成六边形的六个大角,构成最终效果。这里,<span class="textRed">defs</span> 标签群负责描述路径动画,<span class="textRed">user</span> 标签群负责呈现结果;如果使用XML来写svg代码,代码量会很大,因此使用JS来快捷生成svg代码,相对简洁。以下是具体代码和效果演示:</p>

<div class="hE"><pre id="code">
&lt;svg id="hsvg" width="320" height="320" viewBox="0 0 320 320" fill="none" stroke="#008000" stroke-linecap="round"&gt;&lt;/svg&gt;

&lt;script&gt;
drawHexagon = (total) =&gt; {
        let pathstr = '\n\t&lt;defs&gt;', usestr = '\n';
        Array(total).fill(0).forEach((id,idx) =&gt; {
                id = idx + 1;
                pathstr += `\n\t\t&lt;path id="r${id}"&gt;\n\t\t\t&lt;animate id="p${id}" attributeName="d" values="m160,160l0,0 0,0;m130,110l30,-17 30,17;m130,60l30,-17 30,17;m160,20l0,0 0,0" dur="6s" repeatCount="indefinite"/&gt;\n\t\t\t&lt;animate attributeName="stroke-width" values="0;4;4;4;0" dur="6s" repeatCount="indefinite" begin="0s"/&gt;\n\t\t&lt;/path&gt;`;
                usestr += `\t&lt;use xlink:href="#r${id}" transform="rotate(${360 / total * idx} 160 160)"/&gt;\n`
        });
        pathstr += '\n\t&lt;/defs&gt;\n';
        return pathstr + usestr;
};

hsvg.innerHTML = drawHexagon(6);
&lt;/script&gt;
</pre></div>

        <p><button id="btn1" type="button" value="1">点击查看效果</button></p>
        <div id="sbox1" class="showDiv"></div>
        <div id="codebox">
                <p>XML代码:</p>
                <p><textarea id="text"></textarea></p>
        </div>
</div>

<script>
var sc = document.createElement('script');
sc.chartset = 'utf-8';
sc.src = 'https://638183.freep.cn/638183/web/js2024/helight.js';
document.body.appendChild(sc);

var runCodes = (str,ele) => {
        let reg = /(<script(.*?)>)(.|\n)*?(<\/script>)/g;
        let js_str, html_str;
        if(str.match(reg) !== null) {
                js_str = str.match(reg);
                html_str = str.replace(js_str, '').trim();
                js_str = js_str.replace(/<[\/]{0,1}script[^>]*>/g,'').trim();
        } else {
                js_str = '';
                html_str = str.trim();
        }
        ele.innerHTML = html_str;
        let myfunc = new Function(js_str);
        myfunc();
};

btn1.onclick = () => {
        runCodes(code.innerText, sbox1);
        btn1.disabled = true;
        text.value = sbox1.innerHTML;
        codebox.style.display = 'block';
}
</script>

马黑黑 发表于 2024-9-11 19:42

一楼代码理论上可以绘制任意多边形,不过最好计算或估算一下路径的值。当然,作为动画,使用现有的路径也不是什么问题,或许会得到一些意想不到的结果。

svg标签设置了 viewBox 属性,这意味着可以不用纠结整体图案的尺寸,放大或缩小都是清晰的。

马黑黑 发表于 2024-9-11 19:46

如果需要像隐喻一帖的动画效果,那么,需要做更多的工作:animate动画的 begin 属性指向上一个动画结束;use标签总数要乘以6

花飞飞 发表于 2024-9-11 20:00

我的天,它真的可以用代码画出来的。。。。{:4_173:}
今天我的认知在不断被你刷新。。。
早中晚刷三遍

花飞飞 发表于 2024-9-11 20:02

马黑黑 发表于 2024-9-11 19:46
如果需要像隐喻一帖的动画效果,那么,需要做更多的工作:animate动画的 begin 属性指向上一个动画结束;us ...

begin 属性是个关键。。。
这是作业么,整一半留 一半的{:4_173:}

红影 发表于 2024-9-11 20:06

这个就是隐喻帖子里的svg图案的代码呢,虽然只是一个六边形的动态,也很漂亮呢{:4_187:}

红影 发表于 2024-9-11 20:14

这个还和XML对照着看的,果然XML更繁琐,但好像更容易懂点?{:4_204:}

马黑黑 发表于 2024-9-11 20:16

红影 发表于 2024-9-11 20:14
这个还和XML对照着看的,果然XML更繁琐,但好像更容易懂点?

是的,XML代码更直观

马黑黑 发表于 2024-9-11 20:17

红影 发表于 2024-9-11 20:06
这个就是隐喻帖子里的svg图案的代码呢,虽然只是一个六边形的动态,也很漂亮呢

乘以六就可以了,当然不是简单地乘

马黑黑 发表于 2024-9-11 20:17

花飞飞 发表于 2024-9-11 20:02
begin 属性是个关键。。。
这是作业么,整一半留 一半的

这是展示单个六边形的动画

马黑黑 发表于 2024-9-11 20:17

花飞飞 发表于 2024-9-11 20:00
我的天,它真的可以用代码画出来的。。。。
今天我的认知在不断被你刷新。。。
早中晚刷三遍

一日三餐

红影 发表于 2024-9-11 20:55

马黑黑 发表于 2024-9-11 20:16
是的,XML代码更直观

应该先从直观的学起,等弄明白了再简洁{:4_173:}

马黑黑 发表于 2024-9-11 20:56

红影 发表于 2024-9-11 20:55
应该先从直观的学起,等弄明白了再简洁

是这个道理

红影 发表于 2024-9-11 20:56

马黑黑 发表于 2024-9-11 20:17
乘以六就可以了,当然不是简单地乘

是的,还有转向,让各个六边形错落有致{:4_204:}

马黑黑 发表于 2024-9-11 20:57

红影 发表于 2024-9-11 20:56
是的,还有转向,让各个六边形错落有致

对的

红影 发表于 2024-9-11 21:03

马黑黑 发表于 2024-9-11 20:56
是这个道理

先学走,走稳了才能跑,否则只能摔跟头。

红影 发表于 2024-9-11 21:04

马黑黑 发表于 2024-9-11 20:57
对的

然后组合出来的效果像花儿一样绽放着{:4_187:}

马黑黑 发表于 2024-9-11 22:25

红影 发表于 2024-9-11 21:04
然后组合出来的效果像花儿一样绽放着

这个倒是容易的

马黑黑 发表于 2024-9-11 22:25

红影 发表于 2024-9-11 21:03
先学走,走稳了才能跑,否则只能摔跟头。

有道理

红影 发表于 2024-9-12 10:40

马黑黑 发表于 2024-9-11 22:25
这个倒是容易的

效果特别好。{:4_204:}
页: [1] 2 3
查看完整版本: js+svg绘制动画六边形