马黑黑 发表于 2024-11-9 07:30

svgdr教程·容器元素

本帖最后由 马黑黑 于 2024-11-9 07:33 编辑 <br /><br /><style>
        .art > p { margin: 12px 0; font: normal 18px/24px sans-serif; }
        .art mark { padding: 2px 6px; background: lightblue; }
        .art svg { outline: 1px solid silver; }
        .tRed { color: red; }
</style>

<div class="art">
        <h2>defs、g 和 symbol</h2>
        <p><span class="tRed">&lt;defs&gt;</span>、<span class="tRed">&lt;g&gt;</span> 和 <span class="tRed">&lt;symbol&gt;</span> 属于功能性容器标签,此类元素还有 <span class="tRed">&lt;marker&gt;</span>、<span class="tRed">&lt;pattern&gt;</span> 等,它们在别的章节讲解。</p>
        <p><strong>一、defs隔离 和 g分组</strong></p>
        <p>指令:① <mark>defs()</mark> ② <mark>g()</mark></p>
        <p>参数:① <mark>id</mark> ② <mark>id</mark></p>
        <p>语法:① <mark>defs(id)</mark> ② <mark>g(id)</mark></p>
        <p><span class="tRed">defs()</span> 指令的参数 id 为 <span class="tRed">&lt;defs&gt;</span> 标签的id标识符。在SVG中,defs标签一般不需要id属性,svgdr使用id是为了方便操作。在SVG,defs是 definitions(定义)的缩写,defs标签用以定义随后将被引用、复用的分组(g)、图案(pattern)、渐变(*Gradient)、路径(path)等等,defs标签装载这些东西起到隔离(defences)的作用,它们不会被显示出来,直到被其他元素(如use)通过特定方式引用。defs里面所安置的东西各单位拥有自己的id作为被引用的依据(而不是defs的id),同时它们可以被反复引用及复用。</p>
        <p><span class="tRed">g()</span> 指令的参数 id 为 <span class="tRed">&lt;g&gt;</span> 的 id标识符。g源自 group(组)一词,g元素故而用于分组,SVG中可以拥有多个g元素,每个g元素可将一个或多个设计放入其中,便于管理和引用、复用;g元素需要时可以作为defs标签的子元素,也可以独立存在,需要注意的是,当g分组不放入defs标签中,它所包裹的设计是可以渲染的,反之,若放入了defs标签,则只有引用它即将其实例化时方能呈现。</p>
        <p>以下例子展示:① 在 svgdr 中创建defs标签,用于装载待引用、复用的各单元的设计;② 创建一个g分组g1,将其加入到defs标签内,再绘制一个椭圆加入到g分组作为被引用、复用的具体内容;③ 通过两个use标签将g1分组的形状实例化渲染出来并让它们组合成一个美丽的图案;④ 创建另一个分组g2但不加入defs标签,重复步骤三实例化g1并将实例化的图案加入到g2,这两个加入g2的g1实例化得以渲染,因为g2没有加入defs标签;⑤ 将g2实例再实例化三次,让这三个图案展现在svg都右边。</p>
        <svg id="svg1" width="800" height="400"></svg>
        <p>以上图案的 svgdr 绘制代码:</p>
        <div id="div1"><pre id="pre1">
dr.defs('defs'); // ① 创建defs标签
dr.g('g1').addTo('defs'); // ② 创建 id='g1' 的g分组标签并加入 defs
dr.ellipse(100, 100, 90, 35, 'lightblue').addTo('g1'); // ② 画椭圆并加入到g1(椭圆不显示)
// ③ 使用两个user标签在原地组合成图案
dr.use('#g1');
dr.use('#g1').transform('rotate(90 100 100)');
// ④ 使用两个user标签移到(50,200)坐标点组合成图案
dr.g('g2'); //创建 id="g2" 的g分组,不加入defs,装载一下两个use示例组合成图案,该图案显示
dr.use('#g1', 50, 200).addTo('g2');
dr.use('#g1', 50, 200).transform('rotate(90 150 300)').addTo('g2');
//⑤ 实例化 g2 g分组三次(右侧三个图案)
dr.use('#g2', 250, -100).transform('rotate(30, 400, 200)');
dr.use('#g2', 550, -200).transform('rotate(60, 700, 100)');
dr.use('#g2', 550, 0).transform('rotate(120, 700, 300)');
        </pre></div>
        <p>这些绘制代码所生成的SVG代码:</p>
        <div id="div2"><pre id="pre2"></pre></div>

        <p><strong>二、symbol 图形模板</strong></p>
        <p>指令:<mark>symbol()</mark></p>
        <p>参数:<mark>id, viewbox</mark></p>
        <p>语法:<mark>symbol(id, viewbox)</mark></p>
        <p>参数解释:</p>
        <blockquote>
                ① id - <span class="tRed">&lt;symbol&gt;</span> 标签id标识符,字符型<br>
                ② viewBox - <span class="tRed">&lt;symbol&gt;</span> 标签视口数据,字符型,缺省默认与symbol内元素总体占位宽高同
        </blockquote>
        <p><span class="tRed">&lt;symbol&gt;</span> 标签用于定义图形模板,里面可以包含各类图案组成一个有机整体留待后续引用、复用。注意,① 它所组织的图案是一个整体,而且是同一个 <span class="tRed">&lt;symbol&gt;</span> 标签唯一输出的图案,通过use实例化才得以呈现,use引用、复用它的依据是 symbol 自身的 id 标识符。symbol标签和defs是兄弟关系同是svg的儿子,可以放在svg代码流中任何地方;② <span class="tRed">&lt;symbol&gt;</span> 标签可以设置自身体系的 <span class="tRed">viewBox</span> 视口,这意味着 use 实例化 symbol 时可以设置 width(宽)和 height(高)尺寸,这一点与前述的g分组不同:<span class="tRed">g分组的设计被use引用、复用时以其实际尺寸呈现,对use设置宽高无效</span>。</p>
        <p>下面的例子演示:先创建symbol标签,再绘制一个圆加入到symbol标签中,然后使用use标签实例化若干个symbol所定义的图形、渲染出来:</p>
        <svg id="svg2" width="800" height="400"></svg>
        <p>svgdr 绘制代码:</p>
        <div id="div3"><pre id="pre3">
dr.symbol('sb', '0 0 10 10'); //创建 id="sb"的symbol标签,有viewBox
dr.circle(5, 5, 4, 'plum').addTo('sb'); //按照symbol的viewBox的规范画圆
dr.use('#sb'); //默认方式实例化symbol :中间大圆
//下面的实例化均设置位置、尺寸
dr.use('#sb', 0, 0, 200, 200); //左上角 200*200
dr.use('#sb', 0, 300, 100, 100); //左下角 100*100
dr.use('#sb', 560, 0, 240, 240); //右上角 240*240
dr.use('#sb', 700, 310, 80, 80); //右下角 80*80
        </pre></div>
        <p>生成的SVG代码:</p>
        <div id="div4"><pre id="pre4"></pre></div>
        <p>帖子<a href="/forum.php?mod=viewthread&tid=79310" target="_blank">《青春舞曲》</a>是一个实例化 symbol 做小播的应用,里面 symbol 的 viewBox 设置和其内部元素的设计以及动画的加持值得探究。</p>
        <p><a href="/forum.php?mod=viewthread&tid=79137&extra=page%3D1" targete="_blank">返回目录</a></p>
</div>

<script type="module">
import hl from 'https://638183.freep.cn/638183/web/mod/helight.js';
import draw from 'https://638183.freep.cn/638183/web/mod/svgdr.js';

var dr1 = draw.dr('svg1');
dr1.defs('defs');
dr1.g('g1').addTo('defs');
dr1.ellipse(100, 100, 90, 35, 'lightblue').addTo('g1');
dr1.use('#g1');
dr1.use('#g1').transform('rotate(90 100 100)');
dr1.g('g2');
dr1.use('#g1', 50, 200).addTo('g2');
dr1.use('#g1', 50, 200).transform('rotate(90 150 300)').addTo('g2');
dr1.use('#g2', 250, -100).transform('rotate(30, 400, 200)');
dr1.use('#g2', 550, -200).transform('rotate(60, 700, 100)');
dr1.use('#g2', 550, 0).transform('rotate(120, 700, 300)');
pre2.textContent = dr1.code(svg1);

var dr2 = draw.dr('svg2');
dr2.symbol('sb', '0 0 10 10');
dr2.circle(5, 5, 4, 'plum').addTo('sb');

dr2.use('#sb');
dr2.use('#sb', 0, 0, 200, 200);
dr2.use('#sb', 0, 300, 100, 100);
dr2.use('#sb', 560, 0, 240, 240);
dr2.use('#sb', 700, 310, 80, 80);
pre4.textContent = dr2.code(svg2);

hl.hl(div1, pre1);
hl.hl(div2, pre2);
hl.hl(div3, pre3);
hl.hl(div4, pre4);
</script>

梦江南 发表于 2024-11-9 07:43

谢谢老师的代码讲解。早上好!{:4_190:}

冬天的雨 发表于 2024-11-9 09:48

马老师辛苦了,越来越高档了,难度也是越来越大了但必须支持老师,辛苦付出,感谢有你!

冬天的雨 发表于 2024-11-9 09:48

₍˄·͈༝·͈˄*₎◞ ̑̑{:4_178:}{:4_178:}

花飞飞 发表于 2024-11-9 11:14

defs标签这个跟个保险箱似的,放进去的看不到,要看到需要手续领出来。。{:4_173:}
放在外面的可以随便看,且能进行位置和旋转变化。。

花飞飞 发表于 2024-11-9 11:17

dr.circle(5, 5, 4, 'plum').addTo('sb'); //按照symbol的viewBox的规范画圆
dr.use('#sb');
这两行看了挺久,跟上一行的10 10联系起来看
这里的5,5是中心点,4可以理解为80%,所以中间圆位置默认正中且最大。
下面那些就把位置和尺寸全改了。。{:4_173:}

马黑黑 发表于 2024-11-9 12:50

花飞飞 发表于 2024-11-9 11:17
dr.circle(5, 5, 4, 'plum').addTo('sb'); //按照symbol的viewBox的规范画圆
dr.use('#sb');
这两行看了 ...

symbol有自己的 viewBox,引用它的元素,会按svg的 viewBox 和 symbol 的viewBox 的尺寸比例去缩放

马黑黑 发表于 2024-11-9 12:50

花飞飞 发表于 2024-11-9 11:14
defs标签这个跟个保险箱似的,放进去的看不到,要看到需要手续领出来。。
放在外面的可以随便看 ...

这就是 defs 元素的作用

马黑黑 发表于 2024-11-9 12:50

冬天的雨 发表于 2024-11-9 09:48
₍˄·͈༝·͈˄*₎◞ ̑̑

{:4_196:}

马黑黑 发表于 2024-11-9 12:51

梦江南 发表于 2024-11-9 07:43
谢谢老师的代码讲解。早上好!

{:4_190:}

马黑黑 发表于 2024-11-9 12:51

冬天的雨 发表于 2024-11-9 09:48
马老师辛苦了,越来越高档了,难度也是越来越大了但必须支持老师,辛苦付出,感谢有你!

svg是有些难度的,不过学会它受用无穷

冬天的雨 发表于 2024-11-9 13:03

马黑黑 发表于 2024-11-9 12:50


刚才手机回帖

冬天的雨 发表于 2024-11-9 13:03

马黑黑 发表于 2024-11-9 12:51
svg是有些难度的,不过学会它受用无穷

主要还没有接触过

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

冬天的雨 发表于 2024-11-9 13:03
刚才手机回帖

高端手机

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

冬天的雨 发表于 2024-11-9 13:03
主要还没有接触过

是的,需要用心用时

花飞飞 发表于 2024-11-9 18:31

马黑黑 发表于 2024-11-9 12:50
这就是 defs 元素的作用

这个是隐身作用。。神龙等召唤再出来{:4_173:}

花飞飞 发表于 2024-11-9 18:32

马黑黑 发表于 2024-11-9 12:50
symbol有自己的 viewBox,引用它的元素,会按svg的 viewBox 和 symbol 的viewBox 的尺寸比例去缩放

原来真的如此,原来是自动处理,按比例缩 放的。
我按数字理解怎么想不通。。
按百分比理解一下子能看懂了。。{:4_173:}

绿叶清舟 发表于 2024-11-9 20:36

这里数字变化就会出不同图形吗

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

绿叶清舟 发表于 2024-11-9 20:36
这里数字变化就会出不同图形吗

你需要一点一点跟进,如果跟进了,问问题就是另一个档次

马黑黑 发表于 2024-11-9 21:00

花飞飞 发表于 2024-11-9 18:32
原来真的如此,原来是自动处理,按比例缩 放的。
我按数字理解怎么想不通。。
按百分比理解一下子能看 ...

就是酱紫的
页: [1] 2 3
查看完整版本: svgdr教程·容器元素