SVG动态模拟示波图
<style>.artBox { margin: 20px auto; font: normal 18px/26px sans-serif; }
.artBox p { margin: 10px 0; }
</style>
<div class="artBox">
<p>实现原理:JS 动态生成 SVG path 元素 d 属性值,由 setTimeout、setInterval 定时器或 requestAnimationFrame(请求关键帧动画)或其它机制不断重绘 path 路径。下例 path 元素 d 属性值仅用到 M、H、L 三个绘图指令,代码有详尽说明,支持在线预览:</p>
<div class="hEdiv" data-prev="1"><pre class="hEpre">
<h1>点击页面任意地方运行/暂停动画</h1>
<svg id="msvg" widt="800" height="400" viewBox="0 0 400 200" xmlns="http://www.w3.org/2000/svg">
<path id="p1" d="M0 100 H400" fill="none" stroke="green" stroke-width="4" stroke-dasharray="4" />
</svg>
<script>
var timeID, go = false; // timeID : 定时器标识、go : 动画开关
// 页面点击事件
document.onclick = () => {
go = !go; // go开关取反
draw(); // 执行draw 函数
};
function draw() {
var tt = 15;// 路径节点总数
var str = ''; // 路径字符串
// 遍历节点、生成动态路径
Array.from({length: tt}).forEach((_,k) => {
var x = (k + 1) * (360 / tt); // 节点X坐标(360取值依据是viewBox宽度去头尾)
// 节点Y坐标 :节点序列号被2整除定在Y轴中心,否则按viewBox高度值取随机值
var y = k % 2 === 0 ? 100 : Math.floor(Math.random() * 200);
// 拼接路径字串 :开始时是M指令,其余L指令
str += k === 0 ? `M0 100 H${x}` : ` L${x} ${y}`;
});
var path = `${str}L400 100`; // 路径终点
p1.setAttribute('d', path);// 给path d属性赋值
// setTimeout定时器递归调用本函数 :根据 go 开关运行或取消动画
go ? timeID = setTimeout(draw, 200) : cancelTimeout(timeID);
}
</script>
</pre></div>
<p>核心在于路径各个节点的算法及其路径字符串的拼接。上例仅是演示,可根据需求做相应调整。</p>
</div>
<script type="module">
import hl from 'https://638183.freep.cn/638183/web/js/hl.js';
const divs = document.querySelectorAll('.hEdiv');
const pres = document.querySelectorAll('.hEpre');
divs.forEach((div,idx) => hl.hl(div, pres));
</script> 这路径是不断重绘的,拼接起来就是心电图了{:4_173:} 原来是一条直线,任意一点就变成劝态曲线了。这很稀奇。{:4_187:} 代码简洁,设计新颖,效果逼真,谢谢马老师精彩示范{:4_190:} 杨帆 发表于 2026-8-13 21:14
代码简洁,设计新颖,效果逼真,谢谢马老师精彩示范
吃透 draw() 函数,哪里不理解的就问下 红影 发表于 2026-8-13 14:57
这路径是不断重绘的,拼接起来就是心电图了
大致如此 梦江南 发表于 2026-8-13 15:05
原来是一条直线,任意一点就变成劝态曲线了。这很稀奇。
就是说,路径开始时是一条直线(也可以设计为别的,简单的、合适的就好),然后,如果启动了动画,则每隔两百毫秒路径改变一次,都是按 tt 个点坐标绘制的曲线。 马黑黑 发表于 2026-8-14 08:08
就是说,路径开始时是一条直线(也可以设计为别的,简单的、合适的就好),然后,如果启动了动画,则每隔 ...
黑黑老师早上嚎!{:4_190:} 马黑黑 发表于 2026-8-14 08:05
吃透 draw() 函数,哪里不理解的就问下
是,谢谢老师~{:4_180:}
尽管老师有详见说明,但对函数 draw()还谈不上吃透
比如:节点坐标算法、路径字符串拼接、定时器递归调用 杨帆 发表于 2026-8-14 20:07
是,谢谢老师~
尽管老师有详见说明,但对函数 draw()还谈不上吃透
函数虽简短,知识含量确实非常丰厚。仅以 29 行定时器 setTimeout 为例,它:
首先是有条件的——
如果 go 变量为真,则令 setTimeout 定时器运行定时器所在函数 draw(),反之注销定时器id;
其次,定时器在函数里调用函数自身,这叫递归调用,只要执行的条件符合,定时器就会定时执行函数,不间断。因此,定时器执行函数得给个 id,这样,条件不符合时注销定时器才有依据。
除了定时器,三元运算符、取余数、随机数、向下(或向上、四舍五入等)等取整数学方法,都是JS常用知识点,需要一一熟悉掌握。 马黑黑 发表于 2026-8-14 21:51
函数虽简短,知识含量确实非常丰厚。仅以 29 行定时器 setTimeout 为例,它:
首先是有条件的——
是,努力掌握常用知识点最重要。谢谢老师精彩讲解{:4_190:} 杨帆 发表于 2026-8-15 17:24
是,努力掌握常用知识点最重要。谢谢老师精彩讲解
{:4_190:}
页:
[1]