2018-07-23 svg装饰

上次介绍了svg的“建筑材料”,这次来介绍“装饰材料”

svg可以通过自己本身的属性或者css样式来改变样子。

目录

  1. 基本属性 fill stroke
  2. 渐变
  3. 图案
  4. Texts
  5. 变形

属性

对象内部设置属性:fill

fill 属性设置对象内部的颜色,即使对象不是闭合的。 就如下图,树不是闭合曲线,但是fill属性依然有效。

<svg version="1.1" width='500' height='500' xmlns='http://www.w3.org/2000/svg'>
  <ellipse cx="241" cy="25" rx="38" ry="9" stroke="black" fill="transparent" stroke-width="5"/>
  <ellipse cx="156" cy="61" rx="30" ry="12" stroke="black" fill="transparent" stroke-width="5"/>
  <ellipse cx="90" cy="103" rx="30" ry="16" stroke="black" fill="transparent" stroke-width="5"/> 
  <line x1="4"  y1="360" x2="310" y2="360" stroke="black" stroke-width="5" />
  <path id="tree" d="M302 162 Q 200 300, 300 300 M 294 345 Q 300 340,300 220 M 300 275 Q 300 255, 280 230 M 300 275, Q 300 275, 324 242" stroke="black" fill="#ee8943" stroke-width="5" />
  
  <line x1="250"  y1="345" x2="407" y2="345" stroke="black" stroke-width="5" />
  <polyline points="60 213, 10 260, 190 267, 230 186, 93 186, 10 260, 30, 261, 35 360, 70 360, 70 300, 100 300, 100 360, 180 360, 180 267, 180 360, 250 345, 250 250, 250 270, 270 250, 232 186," fill="#fff" stroke="black" stroke-width="5"   />
  <rect x="60" y="155" rx="5" ry="5" width="33" height="81" stroke="black" fill="#fff" stroke-width="5"/>
  <polygon points="203 273, 203 314, 237 304, 237 265"  fill="none" stroke="black" stroke-width="5"/>
  
  
</svg>
半棵树
属性 作用
fill 设置 对象内部的颜色
fill-opacity 控制填充色的不透明度

对象线条设置属性: stroke

属性 作用 value
stroke 设置对象线条的颜色
stroke-opacity 控制填充色的不透明度
stroke-width 线条宽度
stroke-linecap 绘制描边的方式 1.butt ,直边结束线段 2. square, 以线段端点为中心画正方形,stroke-width为半径 3. round, 以线段端点为中心画圆, stroke-width为半径
stroke-linejoin 两条线段间连接的方式 1.miter,连接处是尖角 2.round,连接处是圆角 3.bevel, 连接处是斜接
stroke-dasharray 将虚线类型应用在描边上 (a,b) 一组以逗号分割的数据,a是填色区域长度,b是非填色区域,(a,b,c)=》(a,b,c,a,b,c)a长度填色,b长度非填色,c长度填色,a长度非填色,b长度填色,c长度非填色
stroke-dashoffset 定义虚线开始的位置 如果dashoffset等于dasharray一个组合的长度,那么从实现来看,没有变化

以上属性都可以用css设置。svg中可以加入defs标签,放入style属性。

!注意
放在defs内的style也会影响到其他同名的元素,但是因为svg常用的fill,stroke对其他非svg标签的没有作用,所以还好,但是设置一些transform等都会影响的样式,则需要注意了。


<svg version="1.1" width='500' height='500' xmlns='http://www.w3.org/2000/svg'>
  <defs>
    <style type="text/css"> <![CDATA[
       .MyRect:hover {
         stroke: black;
         fill: red;
         transform: translateX(183px);
       }
     ]]></style>
    
  </defs>
  <ellipse cx="241" cy="25" rx="38" ry="9" stroke="black" fill="transparent" stroke-width="5" class="MyRect"/>
  <ellipse cx="156" cy="61" rx="30" ry="12" stroke="black" fill="transparent" stroke-width="5"/>
  <ellipse cx="90" cy="103" rx="30" ry="16" stroke="black" fill="transparent" stroke-width="5"/> 
  <line x1="4"  y1="360" x2="310" y2="360" stroke="black" stroke-width="15" stroke-dasharray="5,20" stroke-dashoffset="25"  />
  <path id="tree" d="M302 162 Q 200 300, 300 300 Q 400 300,300 162 M 294 345 Q 300 340,300 220 M 300 275 Q 300 255, 280 230 M 300 275, Q 300 275, 324 242" stroke="black" fill="#fff" stroke-width="5" />
  
  <line x1="250"  y1="345" x2="407" y2="345" stroke="black" stroke-width="5" />
  <polyline points="60 213, 10 260, 190 267, 230 186, 93 186, 10 260, 30, 261, 35 360, 70 360, 70 300, 100 300, 100 360, 180 360, 180 267, 180 360, 250 345, 250 250, 250 270, 270 250, 232 186," fill="#fff" stroke="black" stroke-width="5"   />
  <rect x="60" y="155" rx="5" ry="5" width="33" height="81" stroke="black" stroke-dasharray="5,20" stroke-dashoffset="15" fill="#fff" stroke-width="5"/>
  <polygon points="203 273, 203 314, 237 304, 237 265"  fill="none" stroke="black" stroke-width="5"/>
  
  
</svg>


<div class="MyRect">abc</div>

注意
在上面这个代码片段中,出现了CDATA。CDATA包括的代码片段会被按照字符(character data)编译,而不是标记(markup)。
在xhtml中,<![CDATA[xxxx]]>xxx仍会显示在页面上,而在html中,会将这部分当作注释来解读,并且注释部分是从第一个'<'到第一个出现的'>'。

defs 标签

defs标签类似于隐形斗篷,在defs内定义的元素,像之前介绍的react,ellipse等,不会显示出来,但是svg其他元素可以调用他们。后面的一些效果会用到这个标签的特性。


渐变

渐变使得svg像彩虹七色一样过度自然。渐变分为线性和径向。
渐变节点需要id,这样翻边其他元素调用。渐变一般放在上面提到的defs中。

线性渐变

+渐变的烟圈

<svg version="1.1" width='500' height='500' xmlns='http://www.w3.org/2000/svg'>
  <defs>
    <linearGradient id="Gradient1">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="50%"/>
        <stop class="stop3" offset="100%"/>
      </linearGradient>
      <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
        <stop offset="0%" stop-color="red"/>
        <stop offset="50%" stop-color="black" stop-opacity="0"/>
        <stop offset="100%" stop-color="blue"/>
      </linearGradient>
      <style type="text/css"><![CDATA[
        #rect1 { fill: url(#Gradient1); }
        .stop1 { stop-color: red; }
        .stop2 { stop-color: black; stop-opacity: 0; }
        .stop3 { stop-color: blue; }
      ]]></style>
    
  </defs>
  <ellipse cx="241" cy="25" rx="38" ry="9" stroke="black" fill="transparent" stroke-width="5" id="rect1"/>
  <ellipse cx="156" cy="61" rx="30" ry="12" stroke="black" fill="transparent" stroke-width="5"/>
  <ellipse cx="90" cy="103" rx="30" ry="16" stroke="black" fill="transparent" stroke-width="5"/> 
  
  <path id="tree" d="M302 162 Q 200 300, 300 300 Q 400 300,300 162 M 294 345 Q 300 340,300 220 M 300 275 Q 300 255, 280 230 M 300 275, Q 300 275, 324 242" stroke="black" fill="#fff" stroke-width="5" />
  
  <line x1="250"  y1="345" x2="407" y2="345" stroke="black" stroke-width="5" />
  <polyline points="60 213, 10 260, 190 267, 230 186, 93 186, 10 260, 30, 261, 35 360, 70 360, 70 300, 100 300, 100 360, 180 360, 180 267, 180 360, 250 345, 250 250, 250 270, 270 250, 232 186," fill="#fff" stroke="black" stroke-width="5"   />
  <rect x="60" y="155" rx="5" ry="5" width="33" height="81" stroke="black" stroke-dasharray="5,5" stroke-dashoffset="15" fill="#fff" stroke-width="5"/>
  <polygon points="203 273, 203 314, 237 304, 237 265"  fill="none" stroke="black" stroke-width="5"/>
  
  <line x1="4"  y1="360" x2="310" y2="360" stroke="gray" stroke-width="25" stroke-dasharray="5,20" stroke-dashoffset="25"  />
</svg>


<div class="MyRect">abc</div>
  1. linearGradient默认是水平方向的,通过设置x1, x2, y1, y2 来改变渐变方向。这些属性的用法和line的属性是一致的。
  2. xlink:href属性。可以通过这个属性调用另外一个渐变样式。
stop标签的属性 意义
offset 偏移量
stop-color 颜色中值
stop-opacity 半透明度

径向渐变

+太阳+毒烟

<svg version="1.1" width='500' height='500' xmlns='http://www.w3.org/2000/svg'>
  <defs>
    <linearGradient id="Gradient1">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="50%"/>
        <stop class="stop3" offset="100%"/>
      </linearGradient>
      <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
        <stop offset="0%" stop-color="red"/>
        <stop offset="50%" stop-color="black" stop-opacity="0"/>
        <stop offset="100%" stop-color="blue"/>
      </linearGradient>
    <radialGradient id="RadialGradient1">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="#fff"/>
      </radialGradient>
    <radialGradient id="RadialGradient2" cx="0.5" cy="0.5" r="1" fx="0.5" fy="0">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
      <style type="text/css"><![CDATA[
        #rect1 { fill: url(#Gradient1); }
        .stop1 { stop-color: red; }
        .stop2 { stop-color: black; stop-opacity: 0; }
        .stop3 { stop-color: blue; }
      ]]></style>
    
  </defs>
  <ellipse cx="241" cy="25" rx="38" ry="9" stroke="black" fill="url(#RadialGradient2)" stroke-width="5" id="rect1"/>
  <ellipse cx="156" cy="61" rx="30" ry="30" stroke="black" fill="url(#RadialGradient2)" stroke-width="5"/>
  <ellipse cx="90" cy="103" rx="30" ry="16" stroke="black" fill="transparent" stroke-width="5"/> 
  <ellipse cx="500" cy="0" rx="50" ry="50" stroke="pink" fill="url(#RadialGradient1)" stroke-width="25" stroke-dasharray="5,5"/> 
  
  <path id="tree" d="M302 162 Q 200 300, 300 300 Q 400 300,300 162 M 294 345 Q 300 340,300 220 M 300 275 Q 300 255, 280 230 M 300 275, Q 300 275, 324 242" stroke="black" fill="#fff" stroke-width="5" />
  
  <line x1="250"  y1="345" x2="407" y2="345" stroke="black" stroke-width="5" />
  <polyline points="60 213, 10 260, 190 267, 230 186, 93 186, 10 260, 30, 261, 35 360, 70 360, 70 300, 100 300, 100 360, 180 360, 180 267, 180 360, 250 345, 250 250, 250 270, 270 250, 232 186," fill="#fff" stroke="black" stroke-width="5"   />
  <rect x="60" y="155" rx="5" ry="5" width="33" height="81" stroke="black" stroke-dasharray="5,5" stroke-dashoffset="15" fill="#fff" stroke-width="5"/>
  <polygon points="203 273, 203 314, 237 304, 237 265"  fill="none" stroke="black" stroke-width="5"/>
  
  <line x1="4"  y1="360" x2="310" y2="360" stroke="gray" stroke-width="35" stroke-dasharray="5,20" stroke-dashoffset="25"  />
</svg>


<div class="MyRect">abc</div>

radialGradient 的属性可以控制位置和方向。径向渐变有两个重要的点,中心和焦点。还有一个控制渐变的方法

  1. 中心,类似于circle,设置cx,cy和r确定渐变效果的范围。
  2. 焦点,通过设置fx和fy,描述了渐变的中心。

通用属性

1. spreadMethod

当渐变没有充满对象时,剩下的区域如何填充颜色可以由spreadMethod控制,值为pad时表明,剩下的区域就由100%时的填充颜色填充,reflect 时是从100%-0%,再0%-100%的颜色填充,而repeat时则是像stroke-dasharray的填充规则,0-100%的颜色,重复。

2. gradientUnits

在设置cx等属性值,不得不提到gradientUnits的属性,这个是用来描述渐变的大小和方向的单元系统,有两个值,userSpaceOnUse,objectBoundingBox。默认值是第二个。所以只需要指定0到1的坐标,渐变会自动缩放。userSpaceOnUse使用绝对单元,也就是当前svg的坐标轴。

  1. style中设置的渐变高于属性设置的渐变

图案

之前所有介绍的元素和属性,他们可以任意组合形成一个图案,而这个图案可以作为新的一个模版。这就是图案(pattern)的魅力。
pattern元素也是需要放在defs元素内。

属性

  1. pattern定义的是一个单元系统,是不是很耳熟,是不是想起了gradientUnits。是的,pattern有个patternUnits属性,默认值和objectBoundingBox类似。所以width和height的取值是按照比例来定的。(x,y)可以控制pattern元素在对象中渲染时的便宜,例如(0,0.1),图案向下偏移0.1的单元单位,当然,pattern会补齐上半部分。(x,y)的单位也是按照比例来的。
  2. pattern的第二个属性是patternContentUnits,控制的是pattern内部元素绘制时的坐标系统。默认值是和patterUnits相反的,是userSpaceOnUse。
    总结来说,默认pattern本身的坐标系统是按照比例缩放的,而内部元素的绘制是按照绝对值来绘制的。

所以根据不同的需求和目的,要分别设置这两个值。

  1. 如果随着应用pattern的对象的变化,pattern内的图案大小要保持不变的话,两个元素都可以设置成默认值。
  2. 如果随着对象的变化,图案也要等比例缩放,那么patternContentUnits要设置成objectBoundingBox,而patternUnits默认。
  3. 如果随着对象的变化,图案保持不变而只是填充更多的图形,那么patternContentUnits要设置成userSpaceOnUse,而patternUnits也设置成userSpaceOnUse。

过去文人喜欢在画旁边题字,以文字来辅助表达画里的意境。svg也给了我们这样的选择。
下面来介绍Texts。

Texts

+文字

<svg version="1.1" width='500' height='1000' xmlns='http://www.w3.org/2000/svg'>
  <text x="0" y="500" text-anchor="end">welcome to my house</text>
</svg>


 

(x,y)控制文字出现的位置,text-anchor控制这一点的时应该展现文字的那一部分。如果设置成end,那么文字的最后部分就在这一点。就像上面那个文字,如果想让他消失,那么就设置text-anchor=“end”,文字disappear了。无需display:none,无需删除,就是这么神奇。It's amazing。

红绿搭配,世界我有
<text x="0" y="500" fill="red" stroke="green" stroke-width="1" font-size="20" font-weight="900">welcome to my house</text>

忆往昔,有种文字叫做艺术字,可以设置不同填充颜色,不同颜色的描边。svg can do, too。上面用到了font-size,还可以设定font-family、font-style、font-weight、font-variant、font-stretch、font-size-adjust、kerning、letter-spacing、word-spacing和text-decoration。这点和css的设置文字属性很类似。

相关的三个元素

tspan

属性 意义
x 设置一个新的而且是绝对值的x坐标。覆盖了默认的当前的文本位置。这个可以是一个数列。可以通过这种方式控制文字间的空隙大小。
dx 相对值。
y 设置一个新的而且是绝对值的y坐标。覆盖了默认的当前的文本位置。这个可以是一个数列。可以通过这种方式控制文字间的空隙大小。
dy 相对值。
rotate 把所有的字符旋转一个角度。如果是一个数列,则使每个字符旋转分别旋转到那个值,剩下的字符根据最后一个值旋转。
textLength 字符串的长度。如果它自己的度量文字和长度不满足这个提供的值,则允许渲染引擎精细调整字型的位置。

tref(已废弃)

textPath

利用它的xlink:href属性取得一个任意路径,把字符对齐到路径,于是字体会环绕路径、顺着路径走。text上设置(x,y)也不起作用了。内部的textPath优先性更高。

变形

“月光女神,赐给我力量,变身!”

元素g

就像js里,会将重复使用的函数部分抽离出来。svg也会,他将共同的属性放置在g元素上,g元素内部的元素都可以应用这个属性。

平移,旋转,斜切,缩放

css中有个transform属性。svg中同样适用。可以通过translate,rotate,skew,scale设置。和css中用法一致。

svg嵌套

svg可以嵌入别的svg元素。因此你可以利用内部svg元素的属性x、y、viewBox、width和height简单创建一个新的坐标系统。


不同的坐标
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="1000">
  <svg width="100" height="100"  >
    <rect width="50" height="50" />
  </svg>
  <svg width="100" height="100"  x="0" y="100">
    <rect width="50" height="50" fill="red" />
  </svg> 
</svg>

剪切

就像我们常用的截图工具一样,剪切就好比那个选择框。
在defs里创建一个clipPath的标签,在使用的地方可以用clip-path属性调用。

格格的黑旗头
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <clipPath id="cut-off-bottom">
      <rect x="10" y="29" width="178" height="100" />
    </clipPath>
  </defs>

  <circle cx="100" cy="100" r="100" clip-path="url(#cut-off-bottom)" />
</svg>

遮罩

遮罩有时候的表现特别像渐变,其实就是白色蒙版,并且可以调渐变效果。
这里用到的元素也是定义在defs,是mask。

<svg version="1.1" width="500" height="500"xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="Gradient">
      <stop offset="0" stop-color="white" stop-opacity="0" />
      <stop offset="1" stop-color="white" stop-opacity="1" />
    </linearGradient>
    <linearGradient id="Gradient2">
      <stop offset="0" stop-color="green"   />
      <stop offset="1" stop-color="red"   />
    </linearGradient>
    <mask id="Mask">
      <rect x="0" y="0" width="200" height="200" fill="url(#Gradient)"  />
    </mask>
  </defs>

  <rect x="0" y="0" width="200" height="200" fill="green" />
  <rect x="0" y="0" width="200" height="200" fill="red" mask="url(#Mask)" />
  <rect x="0" y="250" width="200" height="200" fill="url(#Gradient2)" />
</svg>
同种效果,不同实现

关于viewbox,有个小秘密,可以设置viewbox为画图区域,然后调整width和height,就可以等比例缩放了。就像画图工具里的放大和缩小,并且是按比例的。


装饰的材料和技术介绍到这里。下一章讲下svg的动画。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335