假装异步加载中...
20 May 2015

使用 SVG

为什么使用 SVG

  • 体积小
  • 缩放不失真(除非非常小)
  • 在 retina 屏显示良好
  • 交互性以及滤镜

制作 SVG

  • Adobe illustrator
  • Inkscape

在网页中使用 SVG

有几种不同的方式可以将 SVG 插入到网页中,结果看起来几乎相同,但是各有优缺点。

  • 将 SVG 作为图像
  • 将 SVG 作为应用程序
  • 混合文档中的 SVG 标记

将 SVG 作为图像

SVG 是一种图像格式,因此可以使用和其它图像类型相同的方式包含在 HTML 页面中。具体的有两种方法:

  • <img> 元素内包含 SVG,适合当图像是页面的基本组成部分时
  • 在 CSS 中包含 SVG,适合当图像主要用来装饰时

<img> 元素内包含 SVG

例如:

<img src="kiwi.svg" alt="Kiwi standing on oval">
浏览器支持

参见:http://caniuse.com/#feat=svg-img

基本上除了 IE8 及其以下,和 Android 2.3 及其以下都支持。

兼容方案一:

if (!Modernizr.svg) {
  $(".logo img").attr("src", "images/logo.png");
}

兼容方案二:

<img src="image.svg" onerror="this.onerror=null; this.src='image.png'">

在 CSS 中包含 SVG

例如:

<a href="/" class="logo">
  Kiwi Corp
</a>

css:

.logo {
  display: block;
  text-indent: -9999px;
  width: 100px;
  height: 82px;
  background: url(kiwi.svg);
  background-size: 100px 82px;
}
浏览器支持

参见:http://caniuse.com/#feat=svg-css

基本上和使用 img 标签一致:除了 IE8 及其以下,和 Android 2.3 及其以下都支持。

兼容方案一:Modernizr

.main-header {
  background: url(logo.svg) no-repeat top left;
  background-size: contain;
}

.no-svg .main-header {
  background-image: url(logo.png);
}

这样会比使用 img 标签少一次 HTTP 请求。

兼容方案二:

body {
  background: url(fallback.png);
  background-image: url(image.svg), none;
}

可以这么做是因为浏览器对 SVG 的支持程度和对多背景的支持程度类似。所以如果浏览器支持多背景图,基本上就支持 SVG,第二条 CSS 规则就生效,从而覆盖第一条。

局限性

将 SVG 作为图像包含进来时,不论使用哪种方法,都有一定的局限性。图像渲染(即“绘制”,也就是 SVG 代码被转换为栅格图像以用于显示)时与主页面是分离的,而且无法在两者之间进行通信。也就不能用 CSS 控制 SVG 的样式。

将 SVG 作为应用程序

<object> 标签可以用来嵌入任意类型的文件,只要浏览器有解析该文件类型的应用程序(浏览器插件或者扩展)即可。

<object type="image/svg+xml" data="kiwi.svg" class="logo">
  Kiwi Logo <!-- fallback image in CSS -->
</object>

其中 type 属性表示要嵌入的文件类型,它的值应该是一个有效的网络媒体类型(通常被称为 MIME),对于 SVG,使用 image/svg+xml。浏览器使用文件类型来确定如何(以及是否)显示该文件。

文件的位置通过 data 属性来指定。

<object> 起始标签和结束标签之间的内容只会在对象数据本身不能渲染时显示。利用这一点,可以将备用图像或是警告文本放进去。有时候还会用来包含一些定义插件参数的元素。

兼容方案,还是使用 Modernizr:

.no-svg .logo {
  width: 200px;
  height: 164px;
  background-image: url(kiwi.png);
}

如果要使用 CSS,则不能直接在 HTML 中应用外部样式表,或是内联样式表。需要将 <style> 写到 SVG 文件中。

<svg ...>
  <style>
    /* SVG specific fancy CSS styling here */
  </style>
  ...
</svg>

如果需要引用外部样式表,则需要在 SVG 文件中,<svg> 标签之上加入下面代码:

<?xml-stylesheet type="text/css" href="svg.css" ?>

以这种方式引入的样式对于用 <img> 或是 CSS 方式引入的 SVG 文件不起作用。

在引入 <object> 标签之前,有些老版本浏览器使用非标准的 <embed> 标签。不过 <embed> 标签已被 HTML5 纳入规范。为了更广泛的支持,可将 <embed> 作为 <object> 标签内部的备用元素。

<embed><object> 的区别在于,它使用 src 属性而不是 data 属性来指定源数据文件;其次,<embed> 标签不能包含任何子内容,因此如果嵌入失败就没有备用选项。

与将 SVG 作为图像包含不同的是,将 SVG 作为应用程序时,嵌入的 SVG 可以包含外部文件,同时脚本可以在该对象和父页面之间进行通信。

混合文档中的 SVG 标记

我们可以在一个文档中同时包含 SVG 代码、HTML 代码或者 XML 代码,称为混合文档。

将标记混合到一个文件有个好处就是,浏览器无需单独下载图像文件。更重要的是,混合文档中的所有元素都会被视为包含在一个文档对象中,可以用 CSS 和 JavaScript 进行控制。

混合文档的几种形式:

  • 在 SVG 内插入 HTML (或其它)内容:利用 <foreignObject> 标签
  • 在 HTML 中内联 SVG(inline SVG)
  • 其它 XML 应用程序中的 SVG

这里,我们只重点介绍第二种

在 HTML 中内联 SVG

<body>

   <!-- paste in SVG code, image shows up!  -->

</body>

还可以利用后端语言进行插入:

<?php echo file_get_contents("kiwi.svg"); ?>

注意:使用 PHP 时,要使用 file_get_contents() ,而不能用 include()include_once()。因为有时候,导出的 SVG 以 <?xml version="1.0" encoding="UTF-8"?> 开头,而这会导致 PHP 解析器卡住。

用 CSS 进行控制

可以像编辑 HTML 标签那样编辑 SVG 标签,例如:

<svg ...>
  <ellipse class="ground" .../>
  <path class="kiwi" .../>
</svg>

SVG 元素有独立的 CSS 属性集。例如:不是 background-color 而是 fill

.kiwi {
  fill: #94d31b; 
}
.kiwi:hover {
  fill: #ace63c; 
}

SVG 可以使用滤镜

<svg ...>
  ...
  <filter id="pictureFilter" >
    <feGaussianBlur stdDeviation="5" />
  </filter> 
</svg>
.ground:hover {
  filter: url(#pictureFilter);
}
浏览器支持

参见http://caniuse.com/#feat=svg-html5

基本上也是:除了 IE8 及其以下,和 Android 2.3 及其以下都支持。

兼容方案:利用 Modernizr

<svg> ... </svg>
<div class="fallback"></div>
.fallback { 
  display: none;
  /* Make sure it's the same size as the SVG takes up */
}
.no-svg .fallback { 
  background-image: url(logo.png); 
}

除了上面介绍的三种方式之外,还可以先将 SVG 转换为 Data URI 形式,再使用。

以 Data URI 形式使用 SVG

在线转换工具:http://www.mobilefish.com/services/base64/base64.php

可以用转换后的结果替换下面的[data]

<img> 标签:

<img src="data:image/svg+xml;base64,[data]">

在 CSS 中:

.logo {
  background: url("data:image/svg+xml;base64,[data]");
}

<object> 标签:

<object type="image/svg+xml" data="data:image/svg+xml;base64,[data]">
  fallback
</object>

如果在转换之前,在 SVG 中引入了 <style>,那么如果使用 <object> 方式使用 base64 结果,同样会起作用。

Data URI 的格式

Data URI 不一定是 base64 格式。对于 SVG 来说,可能最好不要用 base64 格式

Primarily because the native format of SVG is much more repetitive than base64 ends up, it gzips better.

<!-- base64 -->
data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL...

<!-- UTF-8, not encoded -->
data:image/svg+xml;charset=UTF-8,<svg ...> ... </svg>

<!-- UTF-8, optimized encoding for compatibility -->
data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://...'

<!-- Fully URL encoded ASCII -->
data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A//...

通过命令行进行base64编码

优化 SVG 文件

参考资料:

发现文章有错误或是有疑问,欢迎骚扰:395217502@qq.com
上一篇: Meteor 模板
上一篇: SVG 动画 -- 线绘
comments powered by Disqus