第五章涉及知识点有点多,要慢慢消化一会儿。。。

样式

svg的样式之间的关系像极了html和css之间的关系,但还是有细微的差别。
前一篇说到的svg的样式主要就是strock和fill的相关属性。这些属性可以用四种不同方式被作用到svg元素上,比css作用到html元素多一种。
比如stroke="red"要作用到<line x1="0" y1="50" x2="100" y1="50">上

  • 第一种方式:
    <line x1="0" y1="50" x2="100" y1="50" style="stroke:red">

  • 第二种方式:
    <style>line {stroke: red;}</style>
    <svg><line x1="0" y1="50" x2="100" y1="50"></svg>
    或者
    <svg>
    <style type="text/css"><![CDATA[line {stroke: red;}]]></style>
    <line x1="0" y1="50" x2="100" y1="50">
    </svg>

  • 第三种方式:
    外部应用css文件

以上三种简直和在html里用css一模一样。

  • 第四种方式:
    <line x1="0" y1="50" x2="100" y1="50" stroke="red">

svg允许元素内部单独一个个声明属性和对应参数值。但这种方式定义的样式优先级别是最低的,除了比继承样式高,和所有直接作用于该元素上的样式相比,这种方式总是会被其他样式覆盖。

g元素

<g>元素用来将多个svg元素打包成一个组(Group),然后给这个组一个id属性。
比如画一只猫需要很多个svg元素,这些元素用<g>包起来,把id设置为cat

<g id="cat">
    /**
    画猫的svg代码
    */
</g>

单独使用<g>去包裹一堆svg元素,可能的场景就是统一设置fill或者stroke属性。
在<g>上设置的fill和stroke相关属性会作用到其内部所有未设置对应属性的元素上,已经设置的对应属性的元素不会被g设置的属性覆盖掉。比如

<g id="redBox" fill="red" stroke="red">
    <rect x=10 y=10 width=100 height=100 stroke="black"/>
</g>

clipboard.png

rect的fill被设置成了red,但是stroke还是black

use元素

单独使用<g>元素好像除了可以省掉点重复属性就没啥用了。但是有了<use>以后就完全不一样啦。

比如,想画一堆猫。

傻办法就是ctrl-C ctrl-V。
但有了use以后可以这样使用

<g id="cat">
    /**
    画猫的svg代码
    */
</g>
<use xlink:href="#cat" x=100>
<use xlink:href="#cat" x=200>
<use xlink:href="#cat" x=300>
...

<use>和xlink:href是配合一起用的,意思就是把指定的代码块在指定的位置再画一遍。
xlink:href的参数值就代表指定的代码块。和css选择器一样,选择id用#。
当<use>中定义了fill或者stroke属性时,如果指定的代码块<g>上没有相应的属性被定义,那么复制出来的代码块将带着<use>中定义的属性被渲染。
比如

<g id="redBox" fill="red">
    <rect x="0" y="0" width="100" height="100"/>
</g>
<use xlink:href="#redBox" x="150" fill="black" stroke="blue">

clipboard.png

如果指定的代码块是一个外部的svg文件中的某个id="outerG"的<g>标签,可以这样

<use xlink:href="outer.svg#outerG">

使用这种方式有个限制,不能跨域,而且不支持IE

defs元素

<use>搭配<g>虽然强大,但还不够强大。
类似template模板,实际应用的时候,我希望能用现成的模板去生成一段段代码,而作为模板的代码在界面上并不会被展示出来。这样,这个模板生成的内容我想在哪儿放就在哪儿放。并且模板的属性可以在使用的时候自行设置。
仅使用<use>和<g>,是无法完成的。(个人理解,只有一种情况可以实现以上功能。<g>设置fill="none",不设置stroke。但我觉得绝对不会有人这么干)

所以这就有了<defs>元素。被<defs>包裹的所有元素都不会被展现在画布上。
这样一来,把<g>用<defs>一包,啥属性都不用定义,剩下的统统交给<use>标签,这样就完全能作为模板来使用啦~

symbol元素

<defs>搭配<g>搭配<use>虽然很强大,但还是不够强大。
<symbol>作为模板,同<defs>一样,内部的所有元素都不会展现在画布上,但我还希望能用模板生成的图放置到指定大小的容器中,由我自己来设置图的缩放规则和对齐规则。
想到了啥?没错,就是上一篇中的viewBox属性。而<symbol>是可以设置这个属性的,相应的也能设置preserveAspectRatio属性。关于这俩属性这里就不说了,详见SVG之viewBox

用例子说明一下

    <symbol id="circle" viewBox="0 0 100 100" preserveAspectRatio="xMinYMin meet">
        <circle cx="50" cy="50" r="50"></circle>
    </symbol>
    <symbol id="triangle" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax slice">
        <polygon points="0 0, 100 0, 50 100"></polygon>
    </symbol>
    
    <g stroke="grey" fill="none">
        <rect x="0" y="0" width="50" height="100"></rect>
        <rect x="100" y="0" width="50" height="100"></rect>
    </g>
    
    <use xlink:href="#circle" width="50" height="100" fill="red"></use>
    <use xlink:href="#triangle" width="50" height="100" fill="red" x="100"></use>

clipboard.png

左边因为是xMinYMin meet,所有完全展示并且紧靠顶部。
右边因为是xMaxYMax slice,所以三角形高度撑满整个长方形区域且紧靠右侧。

image元素

<image>顾名思义里面放图片的,至于说是矢量图(vector)还是位图(raster),都成。
用起来也方便

<image xlink:href="img.png" x="0" y="0" width="500" heigh="500"/>

有一点要注意的是,<image>可以定义宽度和高度,但可能并不是原始比例。默认情况下<image>有个属性preserveAspectRatio="xMidYMid meet",没想到这个属性除了和viewBox有亲密关系外,和<image>还有一腿,都这么说了,想必这属性能干嘛也不用多解释了。


梦梦她爹
1.8k 声望122 粉丝

« 上一篇
SVG之Basic Shape
下一篇 »
SVG之transform