马黑黑 发表于 2025-11-9 12:39

tzMaker中级教程二

本帖最后由 马黑黑 于 2025-11-9 22:38 编辑 <br /><br /><style>
        .artBox { font-size: 18px; margin: 20px auto; max-width: 1200px; }
        .artBox > p { margin: 10px 0; line-height: 30px; }
        .artBox mark { padding: 4px 6px; background: lightblue; }
</style>

<div class="artBox">
        <p>在帖子中使用SVG会有很多惊喜。做圆弧形或其他任意形状的进度条,SVG很擅长,其自身就拥有绘制基本形状图像的标签,加之 &lt;path&gt; 路径标签的加持,没有什么形状SVG画不出来。tzMaker深知SVG的强大,add() 指令支持给帖子容器添加SVG标签:</p>
        <div class="codebox" data-title="使用 add() 指令添加SVG标签:">
tz.add('svg', 'mysvg', '', {
        width: 200,
        height: 200,
        viewBox: '0 0 200 200'
});
        </div>
        <p>SVG标签有宽、高和视口viewBox等属性,严谨的话还需要命名空间属性 <mark>xmlns="http://www.w3.org/2000/svg"</mark>(做帖可以不要)。上述指令生成的SVG标签代码如下:</p>
        <div class="codebox" data-title="SVG代码:">&lt;svg id="mysvg" width="200" height="200" viewBox="0 0 200 200"&gt;&lt;/svg&gt;</div>
        <p>也可以直接将SVG标签代码写在帖子容器代码内,注意给它一个id以便后续使用它。这就是SVG画布了,可以在其上绘制所需要的图形,tzMaker有一个生成SVG子元素的指令,<mark>svgson(svg节点, 子svg元素标签, { 配置 })</mark>,指令参数一指定SVG标签(画布),参数二指明画的是什么(子元素),参数三使用配置方式设置子元素的具体细节,看例子:</p>
        <div class="codebox" data-title="在SVG中绘制一个圆:">
tz.svgson('mysvg', 'circle', {
        cx: 100,
        cy: 100,
        r: 95,
        fill: 'plum'
});
        </div>
        <p>上例代码,使用 svgson() 指令在 id="mysvg" 的SVG中画一个圆(circle),圆心坐标为(100,100),与SVG的中心点重合,半径为95,用紫红色(plum)填充。花括号 {} 里的配置键中,名实际上是 &lt;circle&gt; 所需要的基础属性名称、键值为对应的属性值,还可以根据设计预期设置更多的属性。</p>
        <p>圆(或其它图形)是SVG进度条制作的基础,而且,一,我们得绘制两个形状一模一样的圆(或其它图形),二,图形不填充或根据需要填充透明色,使用描边样式来充当进度指示和控制器,三,使用指令 svgprog() 设置上述两个图形为进度指示控制器。下面给出具体的实现代码:</p>
        <div class="codebox" data-title="SVG进度条:">
<txt-green>// 创建音频 : 没有音频标签会报错</txt-green>
tz.add('audio', '', '', { src: 'Mp3地址' });

tz.svgson('mysvg', 'circle', {
        <txt-blue>id: 'track',</txt-blue>
        cx: 100,
        cy: 100,
        r: 95,
        fill: 'none',
        stroke: 'gray',
        'stroke-width': 10
});

tz.svgson('mysvg', 'circle', {
        <txt-blue>id: 'prog',</txt-blue>
        cx: 100,
        cy: 100,
        r: 95,
        fill: 'none',
        stroke: 'plum',
        'stroke-width': 10
});

tz.svgprog(<txt-blue>'mysvg', 'track', 'prog'</txt-blue>);
        </div>
        <p>除了id 和描边色(stroke),两个圆的配置属性是一样的;指令 svgprog() 是做进度条的核心,它的三个参数,参数一指向SVG父容器,参数二是底轨圆,参数三是进度圆。这就做成了圆形进度条,其它图形参照此原理配置即可。特别重要的是:<txt-red>和HTML代码一样,SVG及SVG子元素标签有些属性需要短横连线 - 表示,它们做JS键名时必须用上小角引号,单双小角引号都可以,前后统一就行。</txt-red></p>
        <p>友情提示:如果想节省JS代码,可以事先在帖子HTML代码中创建SVG和其子元素代码,这样,tz仅需要一行指令就能创建圆形(或其它图形)的进度条。以下代码是上述代码的简化:</p>
        <div class="codebox" data-title="环保型SVG进度条:" data-prev="1">
&lt;div id="pa" class="pa"&gt;
        &lt;svg id="mysvg" width="200" height="200" viewBox="0 0 200 200"&gt;
                &lt;circle id="track" cx="100" cy="100" r="90" fill="none" stroke="silver" stroke-width="10" /&gt;
                &lt;circle id="prog" cx="100" cy="100" r="90" fill="none" stroke="red" stroke-width="10" /&gt;
        &lt;/svg&gt;
&lt;/div&gt;

&lt;script type="module"&gt;
        import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js';
        const tz = TZ.TZ('pa');
       
        tz.add('audio', '', '', { src: 'https://music.163.com/song/media/outer/url?id=2088974054' });
        tz.svgprog('mysvg', 'track', 'prog');
&lt;/script&gt;
        </div>
        <p>可以看到,JS的代码量极少。和CSS配置原理一样,能不用tz指令就可以完成的尽量不用,这是个好习惯——JS代码总是越少越好。</p>
        <p>像上面的圆形进度条,内里空空荡荡,我们可以考虑在里面安放小播,其它形状的进度条也可以通过精心设计将小播和它融为一体。最简单的做法是在圆环里面放置一个剪裁路径的div或img图片标签,只需设置好位置使之与进度条成为有机的组合并确保小播浮于进度条上层便可。出于一体化设计理念,我们也可以使用 svgsonsRot() 指令在同一个SVG标签内绘制SVG复合图像充当小播,这将有点繁琐,代码量也偏大:</p>
        <div class="codebox" data-prev="1">
&lt;style&gt;
        @import 'https://638183.freep.cn/638183/web/tz/tz.min.css';
        <txt-green>/* .gRot选择器是 tz.svgsonsRot() 指令约定的父元素 */</txt-green>
        .gRot { animation: rotate 8s linear infinite var(--state) }
&lt;/style&gt;
&lt;div id="pa" class="pa"&gt;
        &lt;svg id="mysvg" width="200" height="200" viewBox="0 0 200 200"&gt;&lt;/svg&gt;
&lt;/div&gt;

&lt;script type="module"&gt;
        import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js';
        const tz = TZ.TZ('pa');
       
        tz.add('audio', '', '', { src: 'https://music.163.com/song/media/outer/url?id=2088974054' });
       
        <txt-green>//加入小播,小播默认置入 class="gRot" 的g分组标签</txt-green>
        tz.svgsonsRot(5, 'mysvg', 'path', {
                d: 'M100 100 L80 15 Q100 60,120 15 L100 100z',
                fill: 'plum'
        }).playmp3();

        <txt-green>/* 下面是进度圆环组合 */</txt-green>
        tz.svgson('mysvg', 'circle', {
                id: 'track',
                cx: 100,
                cy: 100,
                r: 95,
                fill: 'none',
                stroke: 'silver',
                'stroke-width': 10
        });
        tz.svgson('mysvg', 'circle', {
                id: 'prog',
                cx: 100,
                cy: 100,
                r: 95,
                fill: 'none',
                stroke: 'red',
                'stroke-width': 10
        });

        tz.svgprog('mysvg', 'track', 'prog'); <txt-green>/* 将两个圆环设置为进度条 */</txt-green>
&lt;/script&gt;
        </div>
        <p>如果事先在帖子容器内设置好SVG代码结构,JS代码将非常简洁。看下面改装后的实例代码:</p>
        <div class="codebox" data-prev="1">
&lt;style&gt;
        @import 'https://638183.freep.cn/638183/web/tz/tz.min.css';
        <txt-green>/* tz.svgsonsRot() 指令约定放入class="gRot" 的g标签 */</txt-green>
        .gRot { animation: rotate 8s linear infinite var(--state); }
&lt;/style&gt;
&lt;div id="pa" class="pa"&gt;
        &lt;svg id="mysvg" width="200" height="200" viewBox="0 0 200 200" style="position: absolute"&gt;
                <txt-blue>&lt;g class="gRot"&gt;&lt;/g&gt;</txt-blue>
                &lt;circle id="track" cx="100" cy="100" r="95" fill="none" stroke="gray" stroke-width="10" z-index="9" /&gt;
                &lt;circle id="prog" cx="100" cy="100" r="95" fill="none" stroke="red" stroke-width="10" z-index="10" /&gt;
        &lt;/svg&gt;
&lt;/div&gt;

&lt;script type="module"&gt;
        import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v3.js';
        const tz = TZ.TZ('pa');
       
        tz.add('audio', '', '', { src: 'https://music.163.com/song/media/outer/url?id=2088974054' });

        <txt-green>// 创建小播</txt-green>
        tz.svgsonsRot(5, 'mysvg', 'path', {
                d: 'M100 100 L80 15 Q100 60,120 15 L100 100z',
                fill: 'plum'
        }).playmp3();

        tz.svgprog('mysvg', 'track', 'prog'); <txt-green>// 进度条</txt-green>
&lt;/script&gt;
        </div>
        <p>svg代码中有一个约定好class类名的g标签,可以缺省——如果没有模块也会自动创建——这里主要是展示一下小播和进度条的层级关系:进度条应放在小播之后,以确保进度条的交互操作不被抢占。分组标签会令SVG内部代码层级变多,但g标签能有效地组织和管理同类子元素,应被合理使用,实际上,模块也会将小播、进度条元素放入不同的分组中——如果它们此前没有放入分组的话。</p>
        <p>本讲主要讨论在tzMaker中使用相关指令绘制SVG进度条和播放控制器,涉及到的指令有 svgprog()、svgson() 和 svgsonsRot() 三个,这些指令需要使用者具备一定的SVG基础知识和应用能力,难度中上;此外,使用svgsonsRot() 做复合小播需要注意SVG子元素之间的层级关系:小播代码写在前,进度条代码写在后,这样可以避免复合小播所在g分组抢占所有点击交互、影响进度条对音频进度的调节操作;最后需要注意,定位SVG可在CSS代码中完成。</p>
        <p>【附】说明一下 tzMaker 当前版本:tz.v3.js,它和此前 v2 的区别在于 svg 相关指令做了更新,其余功能不变。</p>
</div>

<script type="module">
        import linenumber from 'https://638183.freep.cn/638183/web/js/linenumber.js?v0';
        linenumber();
</script>

红影 发表于 2025-11-9 14:14

使用SVG标签设计各种形状的进度条,以及一体化设计小播,设定好层级,可以非常简便地完成小播和进度条的设计。
感谢黑黑的耐心讲解,学习了{:4_199:}

马黑黑 发表于 2025-11-9 19:18

红影 发表于 2025-11-9 14:14
使用SVG标签设计各种形状的进度条,以及一体化设计小播,设定好层级,可以非常简便地完成小播和进度条的设 ...

晚上嚎

杨帆 发表于 2025-11-9 21:39

tzMaker 当前版本:tz.v3.js很好地整合了 svg 相关指令。讲的真好~{:4_180:}

马黑黑 发表于 2025-11-9 22:21

杨帆 发表于 2025-11-9 21:39
tzMaker 当前版本:tz.v3.js很好地整合了 svg 相关指令。讲的真好~

之前从某个版本开始已经有了 svg* 指令,就是有点粗糙,一些算法是得过且过的,现在才开始进行修正、优化

杨帆 发表于 2025-11-9 23:00

马黑黑 发表于 2025-11-9 22:21
之前从某个版本开始已经有了 svg* 指令,就是有点粗糙,一些算法是得过且过的,现在才开始进行修正、优化

tzMaker日臻完善,马老师您辛苦了{:4_180:}

马黑黑 发表于 2025-11-11 11:57

杨帆 发表于 2025-11-9 23:00
tzMaker日臻完善,马老师您辛苦了

{:4_190:}

绿叶清舟 发表于 2025-12-14 20:46

这个算计头最疼了

马黑黑 发表于 2025-12-14 21:37

绿叶清舟 发表于 2025-12-14 20:46
这个算计头最疼了

咋地啦
页: [1]
查看完整版本: tzMaker中级教程二