未来必热:SVG Sprite技术介绍

标签: SVG相关 css sprites grunt grunt-svgstore illustrator | 发表时间:2014-07-10 18:03 | 作者:张 鑫旭
出处:http://www.zhangxinxu.com/wordpress

by zhangxinxu from http://www.zhangxinxu.com
本文地址: http://www.zhangxinxu.com/wordpress/?p=4264

一、Sprite技术

这里所说的Sprite技术,没错,类似于CSS中的Sprite技术。图标图形整合在一起,实际呈现的时候准确显示特定图标。

另,本文图片甚多,爪机党继续浏览需慎重。

二、SVG Sprite与symbol元素

目前,SVG Sprite最佳实践是使用 symbol元素。 symbol元素是什么呢?单纯翻译的话,是“符号”的意思。然,这个释义并不符合这里的场景。不知大家有没有用过Flash, symbol实际上就类似于Flash中的“影片剪辑”、或者“元件”。

因此,我个人觉得, symbol应该解释为“元件”最为恰当!

那, symbol和SVG Sprite又有什么关系呢?

我们可以把SVG元素看成一个舞台,而 symbol则是舞台上一个一个组装好的元件,这这些一个一个的元件就是我们即将使用的一个一个SVG图标。

于是,对于一个集合了三个SVG图标的SVG元素的代码结构会是这样:

<svg>
    <symbol>
        <!-- 第1个图标路径形状之类代码 -->
    </symbol>
    <symbol>
        <!-- 第2个图标路径形状之类代码 -->
    </symbol>
    <symbol>
        <!-- 第3个图标路径形状之类代码 -->
    </symbol>
</svg>

每一个 symbol就是一个图标元件,但是,只有上面的代码,是无法呈现类似下面的效果的:
SVG Sprite的效果图

为何?

因为,舞台上只是放置了图标,如果你不使用(use),是看不见的。就好比你女朋友买了几箱的衣服放家里,如果不穿出去,谁知道她这么土豪呢?

因此,还差一个“使用”,也就是SVG中的 <use>元素。

三、SVG中的use元素

use元素是SVG中非常强大,非常重要的一个元素,尤其在Web开发中,为何?

两点:

  1. 可重复调用;
  2. 跨SVG调用;

1. 可重复调用
你好不容易,用了几十个坐标值,好不容易绘制了一个图形,如果你想再弄一个同样造型,但位置不同的图形出来,你会怎么办?——再复制一遍代码?别说笑了,(如果真那样)SVG文件的尺寸赶得上二师兄的腰围了。

使用 <use>元素就可以,看下面的板栗:

<svg>
  <defs>
    <g id="shape">
        <rect x="0" y="0" width="50" height="50" />
        <circle cx="0" cy="0" r="50" />
    </g>
  </defs>

  <use xlink:href="#shape" x="50" y="50" />
  <use xlink:href="#shape" x="200" y="50" />
</svg>

结果是(IE9+浏览器可见):

首先,注意到没有, use元素是通过 xlink:href属性,寻找要使用的元素的。 #shape对应的就是 idshape的元素。 use元素可以有自己的坐标,以及支持 transform变换,甚至可以use其他 use元素。

这里,两个 use元素使用的是同一个 g元素(组合),从而实现了图形的重复调用功能。

2. 跨SVG调用
SVG中的 use元素可以调用其他SVG文件的元素,只要在一个文档中。

紧接着上面的板栗:

<svg width="500" height="110"><use xlink:href="#shape" x="50" y="50" /></svg>

结果仍是那个图形:

而这个 跨SVG调用就是“SVG Sprite技术”的核心所在。

试想下,我们只要在页面某处载入一个充满Sprite( symbol)的SVG文件(或直接 include SVG代码),于是,在页面的任何角落,只要想使用这个图标,只要简单这一点代码就可以了:

<svg class="size"><use xlink:href="#target" /></svg>

图标尺寸CSS控制,里面只有一个仅有 xlink:href属性的 use元素,Done! 完成!

也即是说,在HTML层面,图标使用的代码成本,跟传统的CSS Sprite或者流行的 font-face几乎无异,代码简洁,而且很好维护。所有的SVG图标都在一个SVG源上。retina良好,尺寸可任意拉伸,且颜色可控,真乃Web图标的未来之星。

吹的嘴巴都干了,上个简单的demo给大家瞅瞅, 我先去给水排水~~

您可以狠狠地点击这里: SVG Sprite使用示意demo

代码如下截图:
SVG Sprite使用示意

效果为:
SVG使用的图标效果

总结下就是: symbol + use => SVG Sprite

诸位会不会觉得本文的内容快要结束了呢?

嘻嘻嘻嘻,顶多才 1/3,下面的才是重点,打起精神,走起~~

四、SVG Sprite实际应用的阻碍

两大问题:

  1. SVG图标从何而来?
  2. SVG图标如何变成symbol并整合在一起?

1个问题, SVG图标从何而来?
“远在天边近在眼前”,CSS3 font-face的逐渐升温,让很多 font-face工具诞生了。例如以前我介绍过的国外的 icomoon.io,或者国内阿里系的 iconfont.cn, 或者bootsrap 3粉们的 font-awesome

这些图标实际上都是使用SVG作为媒介的,所以,根本就不要担心“SVG图标从何而来”,这图标多的就像牛魔王身上的虱子——一抖一大把啊!

OK,如何获得呢?直接下载。拿 iconfont.cn示意,点击某一图标的下载按钮:
点击下载图标

点击下载SVG:
点击下载SVG按钮

于是,我们就得到了SVG图标啦!如果你还需要其他图标,也按照这个步骤一个一个下载下来,很简单吧~ 然后把它们放在一个文件夹中,以备后用。

下面最关键的是第 2个问题, 如何合并这些SVG到一个SVG上?同时满足使用的是 symbol标签,并可以使用裸露的 use元素(除了 xlink:href没有其他属性)调用呢?

很长很funny, 要专门独立两段,

五、关于合并:偏开发的前端看这里

这里的方法适用于偏开发的前端,一些对指令无感的妹子们,可以看下面偏设计的方法。

Github上,有个名为 svgstoregrunt插件,地址 戳这里。如果您还不了解 grunt, 可以看看这两篇我觉得不错的文章:“ 使用GruntJS构建Web程序 (1)”和“ 使用GruntJS构建Web程序 (2)”.

grunt改装的装好后,执行下面的指令,

npm install grunt-svgstore --save-dev

安装grunt-svgstore

烧个香保佑安装成功,然后你就会看到在 node_modules文件夹中一个名为 grunt-svgstore的子文件夹(如下):
grunt-svgstore文件夹

这个名为 grunt-svgstore的文件夹中有个名为 Gruntfile.js的文件,据我个人理解,这个JS是所有 grunt插件要使用的配置文件。

我在里面做了一件事情,加了这么一行代码:
加了一行代码示意

为什么要加这么行代码呢?因为 grunt-svgstore项目README.md让加的,所以我就加了

你会看到

svgstore: {

}

中有一大堆的配置什么的,这些都是用来独立测试各个API的( options对象中各个键就是API名称),让你知道此插件各个API都是干嘛用的,具体释义参见该Github项目。忍不住提一下,如果你希望SVG图标颜色可以在CSS中通过 fill控制, cleanup设置为 true.

OK, 准备工作完毕,下面来实践下。我把从iconfont.cn上下载下来的3个SVG都放在了一个名为 mytest的文件夹下,我希望这个文件夹下的SVG都整合在一起,并可以方便调用,怎么办?

svgstore: {}内部搞个自定义的配置,见下图:
自定义的配置

意思是: mytest文件夹下的所有SVG合并成一个名为 mytest.svg的大SVG文件,并放在 tmp文件夹下。

我们 cdgrunt-svgstore目录,然后在命令行工具中输入:

grunt

然后走起,再烧第2根香,保佑一切正常……
mytest走起~

然后,就可以在tmp文件夹下看到我们的小结晶—— mytest.svg,以及如何使用示意的HTML demo页面。
SVG合并的文件,以及对应的demo~

此demo页面源代码如下:

<svg xmlns="http://www.w3.org/2000/svg" style="width:0;height:0;visibility:hidden;"><symbol viewBox="0 0 1024 1024" id="iconfont-baobei"><title>iconfont-baobei</title><path fill="#272636" d="M...z" transform="translate(0, 800) scale(1, -1)"/></symbol><symbol viewBox="0 0 1024 1024" id="iconfont-bianji"><title>iconfont-bianji</title><path fill="#272636" d="M...z" transform="translate(0, 800) scale(1, -1)"/></symbol><symbol viewBox="0 0 1024 1024" id="iconfont-shangchuan"><title>iconfont-shangchuan</title><path fill="#272636" d="M...z" transform="translate(0, 800) scale(1, -1)"/></symbol></svg>

<svg>
    <use xlink:href="#iconfont-baobei"></use>
</svg>
<svg>
    <use xlink:href="#iconfont-bianji"></use>
</svg>
<svg>
    <use xlink:href="#iconfont-shangchuan"></use>
</svg>

效果如下截图:
第一次成型的SVG效果图

Oh, no! 怎么有残缺,不完美,感觉不会再爱了!

淡定,小问题,貌似是这些SVG制作的时候,本身有些问题(为了font-face做的调整?),我们在illustrator中打开这些SVG, 一下子就可以看出症结所在,例如,细细的铅笔图标:
铅笔的两个角在舞台之外了

铅笔的两个角在白色的舞台之外了,正好跟上面截图少掉的两个角一致。要修复,超easy, 等比例缩放到白色舞台内就OK了,ctrl+S保存,然后重新执行下 grunt命令就好了。

然后,浏览器刷新下刚刚的demo页面,当当当当,撒花撒花~~

溢出调整后的SVG效果

以上~

六、关于合并:偏设计的前端看这里

注意: 这里的方法,就算是CSS完全不懂的设计师也可以轻松上手!

对于一些妹子,只会写些页面,对于开发、编程的感觉比减肥还难,显然,上面的偏开发需编译的工具插件对她们就很吃力。不急不急,这里有面向设计师的方法。

你需要一个犀利的软件,矢量之王,illustrator!

一步一步跟我来:

  1. 打开软件,新建一个文件,然后另存为SVG格式;
  2. 从标尺中拉出一些参考线,搞些正方形格子,我自己用的尺寸是 160*160, 矢量无尺寸,你随意;
  3. 把下载的SVG图形拖到这些格子中,缩放到合适大小。我是铺满的,这样由于对比明显,各个图标尺寸就都是一致的,CSS控制方便;
    illustrator参考线与图形缩放
  4. 这一步很关键。打开Symbols面板,在Window菜单栏中,或Shift+Ctrl+F11启用。然后,拖动格子中的SVG图形到这个面板中,就会触发新建“元件”的行为,会打开类似下面的面板:
    illustrator中新建元件的面板

    其中, name就是SVG中对应的 symbol元素的 id,因此,最好使用英文,最好易识别。下面的 type你随意,这个只要在SVG导入到Flash中使用时候才有用的,这里,我们不和Flash打交道。然后,OK, 这个图标就“元件”化了,按照同样的步骤,让3个图标都变成元件(以后可重复使用),Symbols面板会类似下面这样:
    Symbols面板截图

  5. Ctrl+S保存,合并好的SVG即出炉。我们直接在浏览器中打开此SVG,效果不错哦~
    SVG Sprite的效果图

是不是就这么结束了,太天真了。人生不如意事十之八九。我们瞅一瞅SVG的源代码,会发现, use元素居然跟小龙女一样,不干净纯洁啦——上面一大推乱七八糟的属性!
use元素上大把乱七八糟属性

难道我们要在网页中使用如此臃肿的 use元素吗?

我以小新的明义告诉你,绝对不会!

小新的名义

因为我昨晚在家折腾出了个工具,可以将illustrator生成SVG转换成web可用SVG Sprite.

您可以狠狠地点击这里: illustrator生成SVG转换成web可用SVG Sprite工具demo

上工具完整地址是:http://www.zhangxinxu.com/sp/svg.html 很好记忆,我站点 域名+sp+svg.html, spspecial的缩写,专门放工具用的。

使用很简单:

  1. 把illustrator生成SVG所有代码拷贝到第一个框框里;
  2. 点击“转换萌萌哒”按钮,适用于SVG Sprite技术的新代码就出来了(左下的框框);同时,右侧显示了如何使用该SVG Sprite在web中真实实践;
  3. 左下角还有个红色的“导出该SVG”,就是字面意思,可以自定义名称,也可使用随机名称,为空即可;

一开始的 SVG Sprite使用示意demo就是使用这个工具生成的哦~ 见下缩略图:
illustrator生成SVG转换工具使用截图

注意:此工具值适用于illustrator生成的SVG, 水平有限,其他SVG转换十有八九会跛掉。没怎么测试,如果发现此工具转换出了问题,欢迎提醒,定会及时修复。另外,生成的SVG文件会不定期清理,请勿外链。

我想想,还有没有什么问题……哦,为什么说此方法与CSS Sprite还要简单。

因为,CSS Sprite还需要在CSS中使用 background-position一个一个地定位,哦,天哪~ 如果没有工具的话,就纯粹搬砖的苦力活啊~

但是,这里的SVG Sprite的定位,你只要在illustrator中把位置放好,illustrator这个软件就自动帮你定位好了。你只要在我的工具中转换下,生成下,然后在需要使用的地方使用:

<svg><use xlink:href="#target" /></svg>

就好了,用到CSS了吗?几乎没有,除了对SVG做尺寸限制以及改变图标的颜色。OK,这点程度的东西,小白设计师也可以轻松上手。

从这一点来看,SVG又一次成为了明日之星!设计师只要在illustrator中做好图就可以了,完全没有从前那种帮重构切图的苦逼经历了,是不是要啤酒炸鸡庆祝下!

七、唯一的制约——兼容性

SVG图标必定是未来的趋势。为何现在国内依然不温不火,不对,应该是还没有开始有温度。我觉得除了技术学习滞后性,浏览器兼容性是最关键的制约,毕竟IE8目前依然是大头(33.23%, 刚在百度流量研究院看到的数据)。

如何破?按照我的心情,鸟它个毛线,我就手机上用用,不也挺好。静下来想想,不能意气用事,提一下IE7/IE8浏览器的处理方法吧~

有些标签,浏览器识别,会忽略里面一些东西。例如SVG的 desc元素,里面的内容一向不显示的。于是,对于IE7/IE8, 我们可以把对应图标的 png图片放在其中,然后IE9+等支持SVG的浏览器就会忽略之,而IE7/IE8这些不识泰山的元素就会显示图片。拿礼物这个SVG举例:

<svg class="webicon">
    <desc><img src="iconfont-baobei.png" width="16" height="16"></desc>
    <use xlink:href="#liwu"/>
</svg>兑换礼物

于是,在IE8下,就会是这样:
IE8浏览器下效果

其他靠谱浏览器依然是这样:
SVG使用的图标效果

于是,完美兼容了。只是活脱脱多了个标签,略败兴。当然,你也可以针对IE7/IE8使用CSS Sprite技术,原理类似,只是 img标签换成其他 i之类标签显示背景图,至少HTML这块会干净很多。

八、结束语

今年4月份的时候刚介绍过“ CSS3图标图形生成技术”,如果说“ font-face图标生成技术”是热门的话,那“CSS3图标生成技术”则属于偏门,受设计制约很大,而本文介绍的“SVG Sprite图标生成”则代表了未来。

font-face在部分win系统下,字体较小的时候,锯齿问题很讨厌,苛刻的设计师无法忍受,甚至出现了响应式 font-face这样的名堂,但是,据我观察,纯正的SVG图标是没有这个问题的,而且,SVG图标具备 font-face几乎所有的优点,尺寸CSS可随意定制,颜色CSS可随意定制;且没有 font-face异步加载延时渲染问题;同时没有某些浏览器下 font-face跨域问题;更关键的是,SVG图标支持渐变,甚至彩色图标的。而 font-face实现彩色图标,要一个一个拼起来,你以为贴马赛克啊!而且,SVG中每个 path元素等可以独立控制,帅气的图标变换动画等的就是你来实现!

因此,各方面看,SVG完胜 font-face,

目前唯一的问题就是兼容成本。但是,随着浏览器的发展,SVG一定会迎来自己Web新舞台!

感谢阅读,欢迎交流,踊跃纠错,多多赞助!

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址: http://www.zhangxinxu.com/wordpress/?p=4264

(本篇完)

有话要说?点击 这里发表评论。

相关 [未来 svg sprite] 推荐:

未来必热:SVG Sprite技术介绍

- - 张鑫旭-鑫空间-鑫生活
本文地址: http://www.zhangxinxu.com/wordpress/?p=4264. 这里所说的Sprite技术,没错,类似于CSS中的Sprite技术. 图标图形整合在一起,实际呈现的时候准确显示特定图标. 另,本文图片甚多,爪机党继续浏览需慎重. 二、SVG Sprite与symbol元素.

了解SVG

- - CSDN博客推荐文章
语言: JavaScript,HTML, SVG.         SVG- 可缩放矢量图形 ,是一个XML风格标记驱动的矢量图形的浏览器渲染引擎. 除了IE 9.0和Android V3之前版本外的所有浏览器都支持SVG. Canvas也有同样的支持情况,所以问题往往表现为:我们应该使用哪种方案.

SVG的用法

- - WebHek
先让大家感受一下用SVG技术制作的简单动画:. 如果你看不到这个演示,说明你的浏览器不支持SVG,请使用最新版的谷歌浏览器或火狐浏览器. 《 如何画出一条会动的线》这篇文章专门介绍了上面这SVG动画是如何简单的实现的. SVG是 Scalable Vector Graphics三个单词的首字母缩写.

SVG使用示例

- - JavaScript - Web前端 - ITeye博客
当用户在圆上点击时,使用js创建一个元素:. // 更高效的计时器,类似于setTimeout,不会发生丢. 已有 0 人发表留言,猛击->> 这里<<-参与讨论. —软件人才免语言低担保 赴美带薪读研.

SVG动画入门

- - Web前端 - ITeye博客
今天我们继续来学习SVG动画方面的知识. 一听到动画效果,你可能就觉的头都打啦. 不要担心,SVG本身提供的动画属性非常容易使用,今天我们就来学习一下基础的知识. SVG中提供了 animate的方法来制作动画属性:. 在上面的代码中,我们在元素里面添加了一个 的标签. 包含了下面的一些属性.

理解SVG的viewport,viewBox,preserveAspectRatio

- - Web前端 - ITeye博客
        一个svg,设置了viewBox之后,viewBox的长宽值如果都小于svg的viewport的长宽值,那么结果一定是放大;但是viewBox的长宽值一旦有一个值大于vewport之后,最后的实际效果就不是放大,而是缩小了.         因为viewBox的目的是要自己设置的长宽范围填满viewport.

【转载】SVG是什么?SVG有什么用途?

- - HTML5研究小组
随着网络上信息数据的大量涌现,如何正确显示和出版是有效传输、接收和利用它们的基础. 图形、图像是信息数据可视化的主要方式. 但现有的图形、图像格式存在着缺陷:非开放式,显示和印刷质量及适应性差,难以创建Web上图文信息的个性化定制、交互式以及实时动态方面的应用等. SVG正是在这样的背景下诞生的. SVG(Scalable Vector Graphics,可伸缩性矢量图形)是由万维网联盟(W3C)推出的基于XML编码的开放式图形、图像标准.

Google sprite 图片更新,音乐、电影、航班搜索上线在即?

- applelen - 谷奥——探寻谷歌的奥秘
François Beaufort发现Google.com sprite图片更新了,上图右侧是老sprite图片,左侧是新sprite图片,可以看到灰色和红色图标增加了航班搜索,而在右下角则多出了音乐图标和电影图标. 于2009年10月上线的Google Music Search开始只是一个OneBox而已,一直没有发展成一个独立的搜索产品,即便是这样,这个OneBox还是在今年4月初关闭了,当时Google称要对其进行改进.

【转载】比较html5、GML、SVG、VML

- - HTML5研究小组
web图形方案比较 html5、 GML、 SVG、 VML. GML、SVG和VML都是基于XML的可用来描述矢量图形的标记语言,都是XML词表,它们的语法并不难理解,但它们都有各自不同的用途和特点,下面简单介绍一下. 是基于XML的空间信息编码标准,由OpenGIS Consortium (OGC)提出,得到了许多公司的大力支持,如Oracle、Galdos、MapInfo、CubeWerx等.

jQuery矢量SVG地图插件JVectorMap

- - HTML5资源教程
JVectorMap是一款基于jQuery的矢量地图插件,它是基于SVG结构的,和其他jQuery地图插件不同的是,jVectorMap是矢量地图,但是它同样支持地图缩放和地图平面移动等相应的功能. 由于JVectorMap是基于jQuery的,所以支持大部分主流的浏览器,应用也相当广泛.