2

引言

借鉴出处

此基础教程主要来源于w3c school svg,慢慢地发现mdn svg是更好的进阶资料,以后的主要研究围绕它展开.因为忙于工作上的事情, 所以这篇文章前前后后花了很长时间, 一把鼻涕一把泪, 虽然说不是很难.

正文

SVG简介

之前一直久闻SVG大名,但一直没机会,这几天趁有空的时候初体验了几把,尝尝鲜.Scalable Vector Graphics是一门基于XML用来描述二维矢量图形的标记语言,感觉SVG在国外用得较多,国内相对不受欢迎,我在公司用得较少,不过我们老大为了解决一个金字塔设计问题派上了用场,哦对了想起了还有一些之前用上的SVG icons---IcoMoon所以有点痒也想搞搞.
SVG对于Web图像的重要性相当于HTML对于Web文本的重要性.它的主要竞争者是Adobe未开源的Flash技术,和Flash相比SVG采用XML文本格式来定义图像,和CSS,DOM,XSL,SMIL一样都是Web标准,共同协作.

SVG图像优势

  • 在放大或者改变尺寸的情况下图形质量不会损失.

  • 与JPEG,GIF图像比起来,尺寸更小,可压缩性更强.

  • 可伸缩

  • 图像中的文本可选

  • 所有浏览器均支持SVG文件

SVG使用

下面是SVG简单示例:

<?xml version="1.0" standalone="no"?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1/EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
</svg>

第一行是xml声明,standalone属性表明是否有对外部文件的引用,此svg文件是否"独立".standalone="no"是说会引用一个dtd文件.
第二行和第三行引用了这个外部SVG DTD:"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd,该dtd位于w3c,含有所有允许的svg元素.
svg代码从<svg>根元素开始,<circle>用来创建一个圆,cx,cy是圆心坐标(默认(0,0)),r是半径.stroke和sroke-width用来设置形状轮廓,fill用来设置形状内颜色.所有元素都有关闭标签,包括</svg>,/>等等,用来关闭svg元素和文档本身.
svg文件可以通过以下三种不同方法嵌入到html文档:<embed>, <object>, <iframe>标签.

  • 所有主流浏览器都支持<embed>标签,并允许使用脚本.当在html页面中嵌入svg时使用<embed>标签是adobe svg viewer推荐的方法,如果需要创建合法的xhtml,就不能使用<embed>.

<embed src="rect.svg" width="300" height="100" type="image/svg+xml" pluginspage="http://www.adobe.com/svg/viewer/install" />
//pluginspage指向下载插件的url.
  • <object>是html4中的标准标签,较新浏览器支持地较好但是不允许使用脚本.最新adobe svg viewer安装了的话<object>会失效.

<object data="rect.svg" width="300" height="100" type="image/svg+xml" codebase="http://www.adobe.com/svg/viewer/install" />
//codebase指向下载插件的url
  • <iframe>支持地很好

<iframe srv="rect.svg" width="300" heght="100"></iframe>

SVG组成

这里是我写的一个有较多类svg元素的demo,Command+S保存快捷键还有第一次保存之后每隔一分钟自动保存还是很方便的.提示一点,Condepen上面不需要声明DOCTYPE,只需要往html代码块里面写上<body>里的代码,所以

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3c.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<?xml version="1.0" standalone="no"?>

这一部分可以省去.

SVG形状

svg有一些预定义的形状提供使用:矩形<rect>,圆形<circle>,椭圆<ellipse>,线<line>,折线<polyline>,多边形<polygon>,路径<path>.下面逐个介绍:

  • <rect>用来创建矩形及其变形.rect.svg内容如下:

<?xml version"1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3c.org/2000/svg">
    <rect x="20" y="20" width="300" height="100" style="fill:pink;stroke-width:1;stroke:rgb(0, 0, 0);fill-opacity=0.9;stroke-opacity=0.1" />
</svg>
//stroke指矩形边框颜色,fill指矩形中间填充颜色

style里面还可以使用opacity表示所属svg元素的透明度,rx,ry代表椭圆角的a,b取值.

  • <circle>

<circle cx="200" cy="100" r="50" stroke="#123456" stroke-width="2" fill="#654321" opacity=".4" />

demo里面<circle>元素和<rect>元素处于同一个<svg>根元素之下,注意两个元素不要重叠,如果存在重叠将按照元素出现次序进行先后覆盖(当然如果相邻的两个元素均设置了透明度则覆盖还是被覆盖没有意义,如果只有一方设置了透明度那么还是存在覆盖与被覆盖的情况).

  • <ellipse>

<ellipse cx="240" cy="100" rx="220" ry="30" style="fill:yellow"/>

<ellipse cx="220" cy="100" rx="190" ry="20" style="fill:white"/>
  • <line>

<line x1="50" y1="100" x2="750" y2="100" stroke-width="5"  stroke="#987654" />

注意线条<line>元素没有fill属性,设置了定值也毫无意义.

  • <polygon>用于创建不少于三条边的元素--多边形

<polygon points="800,20 890,20 935,100 890,180 800,180 755,100"  style="stroke:#123987;stroke-width:4;fill:#aef492"/>
  • <polyline>

<polyline points="50,300 50,325 75,325 75,400 150,400" style="fill:#afc196;stroke:red;stroke-width:8"/>

注意polyline元素可以给fill属性赋值,针对的是相邻的点,边之间围成的区域.

  • <path>
    由于该元素涉及较多的命令,要想熟练运用好这些命令并不容易,所以<path>是svg里面最复杂的元素,但是复杂的东西往往可以实现很棒的功能,<path>可以绘制出带有复杂路径的图形.

用于路径的常用命令:`M=moveto, L=lineto,
H=horizontal lineto, V=vertical lineto, C=curveto, S=smooth curveto, Q=quadratic bezier curve, T=smooth quadratic bezier curve, A=elliptical Arc, Z=closepath实际上这些命令简写字母可以大写可以小写,大写表示绝对定位,小写表示相对定位.

SVG滤镜

它用来向形状和文字添加特殊的效果.滤镜有:feBlend, feColorMatrix, feComponentTransfer, feComposite, feConvolveMatrix, feDiffuselighting, feDisplacementMap, feFlood, feGaussianBlur, feImage, feMerge, feMorphology, feOffset, feSpecularLighting, feTile, feTurbulence, feDistantLight, fePointLight, feSpotlight.可以在svg元素上使用多个滤镜.

高斯模糊
<defs>
  <filter id="Gaussian_Blur_1">
    <feGaussianBlur in="SourceGraphic" stdDeviation="2">
  </filter>
  <filter id="Gaussian_Blur_2">
    <feGaussianBlur in="SourceGraphic" stdDeviation="20">
  </filter> 
</defs>
<ellipse cx="300" cy="100" rx="100" ry="50" filter="url(#Gaussian_Blur_1)" />
<polygon points="800,20 890,20 935,100 890,180 800,180 755,100"  style="stroke:#123987;stroke-width:4;fill:#aef492; filter:url(#Gaussian_Blur_2)"/>

在<defs>标签内部嵌套<filter>标签,然后在<filter>当中定义滤镜,<filter>的id属性值唯一,和需要采用过滤效果的svg元素的filter属性值相呼应.滤镜效果由<feGaussianBlur>定义,stdDeviation是模糊程度,in="SourceGraphic"表明在整个图像上面创建效果.

SVG渐变

可以在一个元素上面应用多个颜色的过渡,类似于css3,svg渐变有线性渐变<linearGradient>和径向渐变<radialGradient>.

<linearGradient>

和<filter>一样,<linearGradient>嵌套在<defs>内部,definitions缩写成defs,可以嵌套<filter>, <linearGrandient>, <radialGradient>等特殊元素,进行定义.

<defs>
  <filter id="Gaussian_Blur_1">
    <feGaussianBlur in="SourceGraphic" stdDeviation="2">
  </filter>
  <filter id="Gaussian_Blur_2">
    <feGaussianBlur in="SourceGraphic" stdDeviation="20">
  </filter> 
</defs>
<ellipse cx="300" cy="100" rx="100" ry="50" filter="url(#Gaussian_Blur_1)" />
<polygon points="800,20 890,20 935,100 890,180 800,180 755,100"  style="stroke:#123987;stroke-width:4;fill:#aef492; filter:url(#Gaussian_Blur_2)" />

y1 = y2, x1 != x2, 那么是水平渐变;
x1 = x2, y1 != y2, 那么是垂直渐变;
x1 != x2, y1 != y2,那么是角形渐变.

<radialGradient>

与<linearGradient>类似,不过<radialGradient>在参数上的区别是cx, cy, r定义外圈;fx, fy定义内圈.

SVG元素列表

<a>:超链接;<altGlyph>:允许对象性文字进行控制,来呈现特殊的字符数据,<altGlyphDef>定义一系列象性符号的替换,<altGlyphItem>定义一系列候选象形符号的替换;<animate>随时间动态改变属性,<animateColor>规定随时间进行的颜色转换,<animateMotion>使元素沿着动作路径移动,<animateTransform>对元素进行动态地属性转换;<circle>定义圆;<color-profile>颜色配置描述, <cursor>定义独立于平台的光标, <definition-src>定义单独的字体定义源, <defs>被引用元素的容器, <desc>对SVG元素的纯文本描述-并不作为图形的一部分来显示,作用类似于html中的title属性, <ellipse>定义椭圆, <feBlend>, <feColorMatrix>等等...
以上是w3 school的svg elements列表,下面是mdn对svg元素进行的科学分类:

动画类

<animate>, <animateColor>, <animateMotion>, <animateTransform>, <mpath>, <set>

基本形状类

<circle>, <ellipse>, <line>, <polygon>, <polyline>, <rect>

容器类

<a>, <defs>, <glyph>, <g>, <marker>, <mask>, <missing-glyph>, <pattern>, <svg>, <swtich>, <symbol>

描述类

<desc>, <metadata>, <title>

过滤器相关类

<feBlend>, <feColorMatrix>, <feComponentTransfer>, <feComposite>, <feConvolveMatrix>, <feDiffuseLighting>, <feDisplacementMap>, <feFlood>, <feFuncA>, <feFuncB>, <feFuncG>, <feFuncR>, <feGussianBlur>, <feImage>, <feMerge>, <feMergeNode>, <feMorpholopy>, <feOffset>, <feSpecularLighting>, <feTile>, <feTurbulence>

字体类

<font>, <font-face>, <font-face-format>, <font-face-name>, <font-face-src>, <font-face-uri>, <hkern>, <vkern>

渐近类

<linearGradient>, <radialGradient>, <stop>

图形类

它和基本形状类有差别,字面含义上可以看出.包含<circle>, <ellipse>, <image>, <line>, <path>, <polygon>, <polyline>, <rect>, <text>, <use>

光源类

<feDistanLight>, <fePointLight>, <feSpotLight>

形状类

相比于基本形状类,只多出了<path>元素

结构类

<defs>, <g>, <svg>, <symbol>, <use>

文本内容类

<altGlyph>, <altGlyphDef>, <altGlyphItem>, <glyph>, <glyphRef>, <textPath>, <text>, <tref>, <tspan>

文本内容后代类

<altGlyph>, <textPath>, <tref>, <tspan>

其他未分类

<clip-path>, <color-profile>, <cursor>, <filter>, <foreignObject>, <script>, <style>, <view>
以<aniamteMotion>为例,
这是mdn svg elements上面的一个例子:

<?xml version="1.0"?>
<svg width="120" height="120"  viewBox="0 0 120 120"
     xmlns="http://www.w3.org/2000/svg" version="1.1"
     xmlns:xlink="http://www.w3.org/1999/xlink" >
     
    <!-- Draw the outline of the motion path in grey, along
         with 2 small circles at key points -->
    <path d="M10,110 A120,120 -45 0,1 110 10 A120,120 -45 0,1 10,110"
          stroke="lightgrey" stroke-width="2" 
          fill="none" id="theMotionPath"/>
    <circle cx="10" cy="110" r="3" fill="lightgrey"  />
    <circle cx="110" cy="10" r="3" fill="lightgrey"  />

    <!-- Here is a red circle which will be moved along the motion path. -->
    <circle cx="" cy="" r="5" fill="red">

        <!-- Define the motion path animation -->
        <animateMotion dur="6s" repeatCount="indefinite">
           <mpath xlink:href="#theMotionPath"/>
        </animateMotion>
    </circle>
</svg>

最后,给大家推荐一个东西:IcoMoon,svg用于字体图标,大小可伸缩,清晰度高.

Canvas简介

canvas是html5中的一项新技术,它使用js在网页中绘制图像,画布是一个矩形区域,通过canvas技术可以控制其中的每一个像素,有许多方法用来绘制路径,矩形,圆形,字符还可以添加图像.使用步骤如下:

  • 向页面中添加canvas元素,规定元素的id,宽度,高度:

<canvas id="my-canvas" width="200" height="100"></canvas>
  • 通过js来控制绘制流程,因为canvas元素本身没有绘制能力.

<script>
    var c = document.getElementById("my-canvas");
    //js通过id来查找canvas元素
    var cxt = c.getContext("2d");
    //然后创建context对象,getContext("2d")对象是内建的html5对象,拥有多种绘制路径,矩形,圆形,字符以及添加图像的方法.
    cxt.fillStyle="#ff0000";
    cxt.fiiRect(0, 0, 150, 75);
    //fillStyle方法规定填充颜色,fillRect方法规定了形状,位置,尺寸.
</script>

事实上,w3 school表明canvas还有许许多多方法,涉及颜色,演示,阴影;线条样式;矩形,路径,转换,文本,图像绘制,像素操作,合成,其他等等.

SVG, Canvas之间的比较

本来还想和WebGL之间做比较,现在想想WebGL和后两者完全不一样,这是wiki上面的WebGL,访问不了的话可以使用虫部落,SVG和Canvas主要是做2D图形,而WebGL是用js来做3D应用,e.g.游戏等等(threejs),完全不一样,所以作比较没多大意义.

这里我比较两者主要参考的资料来源于:msdn上面.aspx),w3 school html5 canvas vs svg,作出一些归纳:
canvas和svg都是在浏览器当中创建图形,但是本质上完全不一样.

SVG

  • 一种用XML描述2D图形的语言

  • SVG基于XML,意味着SVG DOM中的每个元素都是可用的,可以为每个元素添加js事件处理器

  • 每个被绘制的图形都是对象,如果对象的属性发生变化,那么浏览器能够自动重现图形.

  1. 不依赖分辨率

  2. 支持事件处理器

  3. 最适合带有大型渲染区域的应用程序

  4. 复杂度高减慢渲染速度(过度使用DOM)

  5. 不适合游戏应用

Canvas

  1. 依赖分辨率

  2. 不支持事件处理器

  3. 文本渲染差

  4. 能够右键以.jpg, .png保存结果图像(SVG图形右键保存是svg格式,强制另换格式保存改变不了图形缩放性)

  5. 最适合图像密集型的游戏,其中许多对象会被重绘.

  6. 通过js来绘制2D图形

  7. 逐个逐个像素进行渲染

SVG是保留模式,Canvas是即时模式.矢量图形概念早已出现,复杂性范围从一个文档或插图中的标注,到图表,关系图,地图等插图,再到工程文档.这些场景都是静态的但是矢量图形也支持交互性,
SVG为Web,桌面和设备上的应用程序提供交互和静态格式.这里的探究以Web为主,e.g.在网页中使用矢量图形为背景图像以支持高DPI和缩放功能;作为地图属性用来执行查找线路操作;显示实时图表图形的交互式股票网站;航班,音乐厅,电影院座位图;游戏等等.
SVG是一个保留在内存模型中的保留模式图形模型,而内存中模型可通过重新呈现的代码结果进行操作.SVG可以作为独立文件提供,也可以与HTML集成.类似于HTML,SVG也使用元素,属性,样式来构建文档,类似于<div>,SVG是HTMLDocument的一部分,同时SVGDocument为<svg>元素提供与矢量图形的深入丰富交互的附加接口.<svg>元素适合于html框模型,但是因为丰富的矢量图形不局限于简单的框,所以内部模型从框中分离出来的话要求属性得到扩展.以<rect>元素为例,它保留在HTML文档对象模型DOM当中,类似普通的HTML元素,可以通过不同的方式设置样式:

<!-- No fill(default color is #000) -->
<rect id="myRect0" width="100%" height="100%" />

<!-- using the class "greenrect" -->
<rect id="myRect0" width="100%" height="100%" class="greenrect" />

<!-- using the style="fill:pink" 内联样式-->
<rect id="myRect0" width="100%" height="100%" style="fill:pink" />

<!-- using the attribute fill="red" 使用fill, fill-opacity等内置的有关svg的css属性-->
<rect id="myRect0" width="100%" height="100%" fill="red" /> 

也可以通过SVG DOM方法设置样式:

document.getElementById("myDiv").style.height = "200";
//alternatively
document.getElementById("myDiv").style = "height:200;";

document.getElementById("myDiv").height.baseVal.value= "200";
//alternatively
document.getElementById("myDiv").setAttribute("height", "200px");

Canvas是"触发即忘"模型,将图形直接呈现在屏幕上但是随后对所完成的操作不保留任何上下文,与保留模式相反,不保存呈现的图形;每次需要新框架时需要描述整个场景,开发人员需要重新调用所有的必须的绘图命令,而不考虑实际更改(SVG拥有场景图).这个新框架不好理解的话可以借助于SVG <path>元素d命令的"简洁性"与Canvas ctx对象的beginPath(),lineTo(x1, y1) moveTo(x2, y2)...closePath()等命令"零碎性"之间的区别.和SVG一样,Canvas也有很复杂的几何基元,区别在于这些基元采用函数形式.Canvas的路径API并不局限于moveTo和arc,和SVG一样都包含贝赛尔曲线.Canvas可以捕获鼠标在图像上的位置,由于是"即时模式",所以必须通过单个元素的mouseX,mouseY<canvas>坐标来捕获.Canvas没有任何样式,缩放的话也会导致失真.
下面总结一下,作出一些关键方面的比较

  • Canvas SVG

  • 基于像素,动态,.png 基于形状

  • 单个HTML元素 多个图形元素,这些元素成为DOM的一部分

  • 通过js操作图形 通过css,js

  • 事件模型/用户交互颗粒化(x, y) 事件模型/用户交互抽象化(rect, path)

  • 图面较小,对象数量较多(>10k)性能更好 与前者相反

使用场景的比较

屏幕较大的话,Canvas性能欠佳,因为需要绘制更多的像素;对象数量较多的话,SVG性能欠佳,因为DOM加载较慢.另外还有js引擎速度,浏览器或者其他环境是否完全使用硬件加速等等也会左右着两者的选择.在浏览器,可以说Canvas这项H5新技术更容易为广大的Web开发人员所接受,很重要的一方面是因为它简单且高效.但是除去浏览器,SVG等等可用于CAD建筑,工程等要求高保真度的复杂矢量文档方面,它占有很明显的优势.

实时数据传输

实时两个字已经道出Canvas的优势意味.用户交互是Canvas的短板,非交互的实时数据可视化却是它的强项,因为屏幕上的对象数量相当高.
Canvas vs SVG0.png

剧终


南赐
125 声望4 粉丝

大多数情况下会在segmentfault上面活跃,日后主攻小程序,storybook + vue 组件开发,前端测试,持续集成,node.js,eggjs等等。期待与大家深入交流技术~


引用和评论

0 条评论