HTML 中加载 SVG 有很多种方式,但如果需要在 HTML 中通过 CSS 样式自由控制 SVG 样式就必须将 svg 标签插入网页找那个成为 DOM 的一部分,本文借助 SVGInject 插件可以快速完成这一操作
SVG 是一种图像文件格式,全称为 Scalable Vector Graphics,意思为可缩放的矢量图形。
SVG 采用 XML 定义语言,通过代码描述矢量/栅格/图形,很大程度上相同表现的 SVG 往往比其他格式图片更小。
SVG 图形是可以动态化与交互的,在 SVG 中嵌入动画元素或通过脚本来定义动画,比 gif 动态图片更加自由与灵活。
在 Web 应用中,可以通过操作 DOM 的方式去操作 SVG 元素,包括放大/缩小/偏移/改变颜色等。
由于 SVG 本身通过代码定义的矢量集,在任何分辨率下渲染方法或缩小都不会失真。
HTML 中加载 svg 有如下几种方案:
svg
标签直接写入 HTML 的 DOM 结构中。img
标签的 src 属性指向 svg 文件。css
背景图片 url 属性指向 svg 文件。object embed iframe
等标签嵌入 svg 文件。在 HTML 中想通过 CSS 控制 SVG 的样式,则 SVG 必须通过 svg
标签内联至 HTML 的 DOM 结构中。
因此,只有方式 1 和方式 5 可以满足要求。
方式 1 如果服务端直接存放的是静态 HTML 文件,就需要提前写入 SVG 节点,这非常不利于维护。
如果使用服务端组装 HTML,则需要执行预渲染操作,由服务端提前将 SVG 结构内容从数据库或者文件中读取出来写到 HTML 中再返回到客户端。
整体来看方式 1 将 SVG 直接耦合到 HTML 中可以实现,但是有不少缺点。
方式 5 中 SVG 资源还是保留在对应的 .svg 文件中,以静态图片资源的形式存在。
HTML 中可以通过 img
或者其他标签直接引入 SVG 文件,和正常加载图片的形式完全一致。
在引入 SVG 后可以通过 JS 去读取 SVG 文件的内容,通过操作 DOM 的方式将 SVG 节点插入到 DOM 中,继而可以通过 CSS 控制 SVG 样式。
整体来看方案 5 依旧保留了常规的 HTML 书写习惯,SVG 文件也可以按照标准放到静态资源目录下,后期修改 SVG 无需修改代码,更加利于维护和处理。
当确认采用 JS 加载 SVG 方案后,需要考虑以下问题:
就当我准备造轮子的时候,发现这个轮子已经有人造好了...
下图为 SVGInject 的 GitHub 页的简介。
首先 HTML 网页中可以正常通过 img
标签指向 SVG 文件进行常规的 SVG 图像显示,这时无法通过样式控制 SVG 的样式。
通过 SVGInject 插件去加载 SVG 文件的源节点,并通过 svg
标签替换原本的 img
标签。
先定义好 img svg
元素的控制 CSS:
/* 因为 svg 标签后期会替换 img 因此可以一起定义 */
.itm img,.itm svg{
width: 60px;
height: 60px;
display:block;
padding:5px;
}
/* 我加载的 SVG 文件中默认 fill:#fff */
.itm svg path{
fill:#444;
}
/* 增加 hover 效果 缩小 */
.itm a:hover img,.itm a:hover svg{
padding:8px;
}
/* SVG 节点变色 */
.itm a:hover svg path{
fill:#539bf5;
}
HTML 中引入 JS 正常书写 img
加载 SVG:
<div class="box itm">
<a href="/quck/team_java_1.html">
<!-- onload 图片加载完成 启用 SVGInject 传入当前节点 -->
<img src="/static/img/team/java.svg" onload="SVGInject(this)"/>
<h2>JAVA</h2>
</a>
</div>
<script src="/static/lib/svg/svg-inject.min.js?v=1.0"></script>
页面加载后的的效果如下图:
正常情况下,为了保证网页打开效率,我们往往会把 JS 文件放在最后引入。
由于 img
标签中直接绑定了 onload="SVGInject(this)",浏览器在解析网页元素时,由于位于底部的 JS 资源文件尚未加载完成,会出现找不到 SVGInject 方法有部分 SVG 元素报错而不被加载。
<!-- 指向我们自己定义的JS方法 -->
<img src="/static/java.svg" onload="initSvg(this)"/>
// WaitForSVGInjectInit
// 将该小段方法放在顶部,或者写一个公共的JS最先引入
function initSvg(obj) {
try{
SVGInject(obj);
}catch(e){
// 方法尚未实例化,执行递归
setTimeout(function(){
initSvg(obj);
},200)
}
}
下载一个最新的 TAG 即可:
温馨提示:系统将通过浏览器临时记忆您曾经填写的个人信息且支持修改,评论提交后仅自己可见,内容需要经过审核后方可全面展示。