📖SVGInject插件动态加载SVG并自定义样式

发布: 2022-11-11
热度: 38
趋势: 38
权重: 6
🎯

HTML 中加载 SVG 有很多种方式,但如果需要在 HTML 中通过 CSS 样式自由控制 SVG 样式就必须将 svg 标签插入网页找那个成为 DOM 的一部分,本文借助 SVGInject 插件可以快速完成这一操作

SVG 特性

SVG 是一种图像文件格式,全称为 Scalable Vector Graphics,意思为可缩放的矢量图形。

SVG 采用 XML 定义语言,通过代码描述矢量/栅格/图形,很大程度上相同表现的 SVG 往往比其他格式图片更小。

SVG 图形是可以动态化与交互的,在 SVG 中嵌入动画元素或通过脚本来定义动画,比 gif 动态图片更加自由与灵活。

在 Web 应用中,可以通过操作 DOM 的方式去操作 SVG 元素,包括放大/缩小/偏移/改变颜色等。

由于 SVG 本身通过代码定义的矢量集,在任何分辨率下渲染方法或缩小都不会失真。

HTML 加载 SVG

HTML 中加载 svg 有如下几种方案:

  1. svg 标签直接写入 HTML 的 DOM 结构中。
  2. 通过 img 标签的 src 属性指向 svg 文件。
  3. 通过 css 背景图片 url 属性指向 svg 文件。
  4. 通过 object embed iframe 等标签嵌入 svg 文件。
  5. 通过 JS 读取 svg 文件后写入 DOM 结构中。

CSS 控制 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 要点

当确认采用 JS 加载 SVG 方案后,需要考虑以下问题:

  1. 在 SVG 源节点尚未写入 HTML 之前,界面应当能够正常展示图像(原始 SVG 的样式)。
  2. 最好能将 SVG 节点插入到一开始展示的位置。
  3. 通过预先写好的 CSS 样式控制 SVG 节点样式。

就当我准备造轮子的时候,发现这个轮子已经有人造好了...

SVGInject 插件

下图为 SVGInject 的 GitHub 页的简介。

SC-307-svginject1.jpg

首先 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>

页面加载后的的效果如下图:

SC-308-svginject2.jpg

方法优化

正常情况下,为了保证网页打开效率,我们往往会把 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 即可:

https://github.com/iconfu/svg-inject/tags

当前文章暂无讨论,留下脚印吧!
大纲
  • SVG 特性
  • HTML 加载 SVG
  • CSS 控制 SVG
    • JS 加载 SVG 要点
  • SVGInject 插件
    • 开发实例
    • 方法优化
    • 下载地址
提交成功,请等待审核通过后全面展示!

发表评论

昵称
邮箱
链接
签名
评论

温馨提示:系统将通过浏览器临时记忆您曾经填写的个人信息且支持修改,评论提交后仅自己可见,内容需要经过审核后方可全面展示。

选择头像