代码改变世界

SVG 入门及实践

2019-08-23 10:31  king0222  阅读(267)  评论(0编辑  收藏  举报

SVN基本结构

<html>
<body>

<h1>My first SVG</h1>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="black"
stroke-width="2" fill="red" style="fill:blue;stroke:pink;stroke-width:5;fill-opacity:0.1;stroke-opacity:0.9;" />
</svg>

</body>
</html> 

SVG 路径 -

元素应该是 SVG 中最常见的形状。你可以通过 path 元素绘制矩形(直角矩形或者圆角矩形)、圆形、椭圆、折线形、多边形,以及一些其他的形状。

元素用于定义一个路径。

下面的命令可用于路径数据:

- M = moveto
- L = lineto
- H = horizontal lineto
- V = vertical lineto
- C = curveto
- S = smooth curveto
- Q = quadratic Bézier curve
- T = smooth quadratic Bézier curveto
- A = elliptical Arc
- Z = closepath

注意:以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。

下面是一个path的实例:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> 
  <path d="M150 0 L75 200 L225 200 Z" /> 
</svg>

旋转的文字:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> 
  <text x="0" y="15" fill="red" transform="rotate(30 20,40)">I love SVG</text> 
</svg>

路径上的文字:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" 
xmlns:xlink="http://www.w3.org/1999/xlink"> 
   <defs> 
    <path id="path1" d="M75,20 a1,1 0 0,0 100,0" /> 
  </defs> 
  <text x="10" y="100" style="fill:red;"> 
    <textPath xlink:href="#path1">I love SVG I love SVG</textPath> 
  </text> 
</svg>

文字分组换行:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> 
  <text x="10" y="20" style="fill:red;">Several lines: 
    <tspan x="10" y="45">First line</tspan> 
    <tspan x="10" y="70">Second line</tspan> 
  </text> 
</svg>

文字作为链接:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" 
xmlns:xlink="http://www.w3.org/1999/xlink"> 
  <a xlink:href="//www.w3cschool.cn/svg/" target="_blank"> 
    <text x="0" y="15" fill="red">I love SVG</text> 
  </a> 
</svg>

SVG Stroke 属性

SVG提供了一个范围广泛stroke 属性。在本章中,我们将看看下面:

- stroke
- stroke-width
- stroke-linecap
- stroke-dasharray

所有stroke属性,可应用于任何种类的线条,文字和元素就像一个圆的轮廓。

SVG 滤镜

在本教程中,我们将仅展示一个可能采用的特殊效果。基础知识展示后,你已经学会使用特殊效果,你应该能够适用于其他地方。这里的关键是给你一个怎样做SVG的想法,而不是重复整个规范。

SVG可用的滤镜是:

- feBlend - 与图像相结合的滤镜
- feColorMatrix - 用于彩色滤光片转换
- feComponentTransfer
- feComposite
- feConvolveMatrix
- feDiffuseLighting
- feDisplacementMap
- feFlood
- feGaussianBlur
- feImage
- feMerge
- feMorphology
- feOffset - 过滤阴影
- feSpecularLighting
- feTile
- feTurbulence
- feDistantLight - 用于照明过滤
- fePointLight - 用于照明过滤
- feSpotLight - 用于照明过滤

Remark 除此之外,您可以在每个 SVG 元素上使用多个滤镜!

使用滤镜的实例:

1.模糊效果

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <filter id="f1" x="0" y="0">
      <feGaussianBlur in="SourceGraphic" stdDeviation="15" />
    </filter>
  </defs>
  <rect width="90" height="90" stroke="green" stroke-width="3"
  fill="yellow" filter="url(#f1)" />
</svg> 

代码解析:

  • 元素id属性定义一个滤镜的唯一名称
  • 元素定义模糊效果
  • in="SourceGraphic"这个部分定义了由整个图像创建效果
  • stdDeviation属性定义模糊量
  • 元素的滤镜属性用来把元素链接到"f1"滤镜

2.阴影效果

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <filter id="f1" x="0" y="0" width="200%" height="200%">
      <feOffset result="offOut" in="SourceGraphic" dx="20" dy="20" />
      <feColorMatrix result="matrixOut" in="offOut" type="matrix"
      values="0.2 0 0 0 0 0 0.2 0 0 0 0 0 0.2 0 0 0 0 0 1 0" />
      <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="10" />
      <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
    </filter>
  </defs>
  <rect width="90" height="90" stroke="green" stroke-width="3"
  fill="yellow" filter="url(#f1)" />
</svg> 

实现阴影效果分为四个步骤:

1首先通过feoffset滤镜实现图形的复制偏离;

2.通过feBlend滤镜对源图形以及复制的偏离图形做图像混合处理;

3.通过feColorMatrix滤镜对阴影颜色做矩阵计算;

4.通过feGaussianBlur滤镜实现模糊效果;

SVG动画

实例1:(重复用 5 秒时间淡出的矩形

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rect x="20" y="20" width="250" height="250" style="fill:blue">
    <animate attributeType="CSS" attributeName="opacity" from="1" to="0" dur="5s" repeatCount="indefinite" />
  </rect>
</svg>

实例2:(矩形会变大并改变颜色

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rect id="rec" x="300" y="100" width="300" height="100" style="fill:lime"> 
    <animate attributeName="x" attributeType="XML" begin="0s" dur="6s" fill="freeze" from="300" to="0" /> 
    <animate attributeName="y" attributeType="XML" begin="0s" dur="6s" fill="freeze" from="100" to="0" /> 
    <animate attributeName="width" attributeType="XML" begin="0s" dur="6s" fill="freeze" from="300" to="800" /> 
    <animate attributeName="height" attributeType="XML" begin="0s" dur="6s" fill="freeze" from="100" to="300" /> 
    <animateColor attributeName="fill" attributeType="CSS" from="lime" to="red" begin="2s" dur="4s" fill="freeze" />
  </rect>
</svg>

实例3:(沿一个运动路径移动、旋转并缩放的文本 + 逐步放大并改变颜色的矩形

<!DOCTYPE html>
<html>
<body>

<p><b>Note:</b> This example only works in Firefox and Google Chrome.</p>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rect id="rec" x="300" y="100" width="300" height="100" style="fill:lime"> 
    <animate attributeName="x" attributeType="XML" begin="0s" dur="6s" fill="freeze" from="300" to="0" /> 
    <animate attributeName="y" attributeType="XML" begin="0s" dur="6s" fill="freeze" from="100" to="0" /> 
    <animate attributeName="width" attributeType="XML" begin="0s" dur="6s" fill="freeze" from="300" to="800" /> 
    <animate attributeName="height" attributeType="XML" begin="0s" dur="6s" fill="freeze" from="100" to="300" /> 
    <animateColor attributeName="fill" attributeType="CSS" from="lime" to="red" begin="2s" dur="4s" fill="freeze" />
  </rect>
  <g transform="translate(100,100)"> 
    <text id="TextElement" x="0" y="0" style="font-family:Verdana;font-size:24; visibility:hidden"> It's SVG!
      <set attributeName="visibility" attributeType="CSS" to="visible" begin="1s" dur="5s" fill="freeze" />
      <animateMotion path="M 0 0 L 100 100" begin="1s" dur="5s" fill="freeze" />
      <animateColor attributeName="fill" attributeType="CSS" from="red" to="blue" begin="1s" dur="5s" fill="freeze" /> 
      <animateTransform attributeName="transform" attributeType="XML" type="rotate" from="-30" to="0" begin="1s" dur="5s" fill="freeze" /> 
      <animateTransform attributeName="transform" attributeType="XML" type="scale" from="1" to="3" additive="sum" begin="1s" dur="5s" fill="freeze" /> 
    </text> 
  </g>
</svg>

</body>
</html>

与javascript交互

通过getSVGDocument()获取svgDocument

function setup (document) {
// do something with svg docuemnt
}
 
setup(document.getElementById('svg-embed').getSVGDocument());

获取了SVG的document之后,就可以像往常那样获取内部元素属性、绑定事件等等。还可以定义一个document为参数的方法形成局部变量,要对某个引入SVG文档进行操作时就获取该文档的document对象传入,想获取主文档的对象时就使用window.document即可

需要注意的是,要操作SVN就需要满足同源策略;

一般在javascript中动态创建DOM元素可以通过createElement方法来创建,但是用这个API来创建SVN元素是不会生效并展示的;

这是因为创建SVG元素需要指定命名空间,就像需要在svg标签上设定xmlns为http://www.w3.org/2000/svg。正确的构造方式是调用createElentNS()方法,并将”http://www.w3.org/2000/svg”作为第一参数传入。

此外,不同于HTML元素对象可以直接对一些属性赋值,SVG元素对象都需要通过调用setAttribute()方法来设定属性值。因为大部分属性都是SVGAnimatedLength类型,即使要通过属性赋值也要写成类似c.r.baseVal.value
= 7,多层访问其下属性。不过像fill、stroke等默认都是undefined,所以使用setAttribute()是更好的选择。

<svg xmlns="http://www.w3.org/2000/svg"    
xmlns:xlink="http://www.w3.org/1999/xlink"    
version="1.1" width="20" height="20">    
   <script type="text/javascript">         
       var c = document.createElementNS('http://www.w3.org/2000/svg','circle');        		c.setAttribute('cx', 10);        
       c.setAttribute('cy', 10);        
       c.r.baseVal.value = 7;        
       c.setAttribute('fill', 'green');         
       document.rootElement.appendChild(c);    
   </script>
</svg>

通过setAttributeNs()设置属性

除了元素有命名空间,有些属性也有其特定的命名空间。比如在HTML极为常用的a标签的,在SVG中又有存在,但是对于其href属性,在SVG之中就必须加上xmlns:前缀来指定其命名空间了。对于设置这些属性也需要用setAttributeNS()方法并将”http://www.w3.org/1999/xlink“作为第一参数传入。

var a = document.createElementNS('http://www.w3.org/2000/svg','a');        a.setAttributeNS('http://www.w3.org/1999/xlink',
	'xlink:href', 
	'http://blog.iderzheng.com/');

SVG与窗口坐标系的转换

这个内容要测试加深理解

function click(e) {    
	// rootElement is specific to SVG document    
	// documentElemnt is to any XML document include HTML    
	// they both can retrieve the root element of a document     
	var r = document.rootElement || document.documentElement,    
	pt = r.createSVGPoint(),    
	im = r.getScreenCTM().inverse(); 
	// inverse of tranforma matrix     
	// set point with window coordination    
	pt.x = e.clientX;    
	pt.y = e.clientY;     
	// convert point to SVG coordination    
	var p = pt.matrixTransform(im);
}

动画开发

辅助性的脚本库:TweenMax.min.js

参考网站:https://tympanus.net/codrops/?s=svg&search-type=posts