svg 的创建和使用

svg 是 Scalable Vector Graphics(可缩放矢量图形)的简称,它是一种基于 XML 格式(XML 是区分大小写的)的矢量图。创建 svg 图形的方法有很多,可以直接创建一个 svg 文件,也可以在 html 文件中使用 svg 元素来绘制,还可以使用 js 来生成,或者使用 Adobe Illustrators 等软件直接绘制好图形后导出 svg 文件。

直接创建 svg 文件

我们可以从阿里的图标库选择一个图标,然后点击 "SVG下载" 去获取一个 svg 文件,看看别人怎么写的:

它可能长成下面这样子:

文件的第一行 <?xml version="1.0" standalone="no"?> 为 XML 声明,version 用于指定版本,standalone="no" 表示当前文档不是独立的,而是有依赖外部文件,这个外部文件会在下一行的 DTD 中定义。其实还有个指定编码格式encoding 属性被省略了,其默认为 encoding="UTF-8"

第二行的 <!DOCTYPE svg ... 是 DTD(Document Type Definition),即文档类型声明,用于让解析器验证 XML 是否符合相应规范。!DOCTYPE 后的 svg 代表文件的内容部分的根元素为 svg"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" 为依赖的外部 DTD 文件的文件名。当我们新建 html 文件时,第一行的 <!DOCTYPE html> 也就是 DTD,表明文件的根元素为 html

事实上,XML 声明和 DTD,都可以省略不写,浏览器解析器会帮我们自动加上。

第三行 svg 元素的属性中定义了多个属性:

  • viewBox:用于修改 svg 的用户坐标系,之后会单独写一篇文章详细介绍;
  • version:它的值可以是 1.01.1,用于指定 SVG 的版本。大体上,svg 可以划分为 2 个版本:1.x 和 2.x,它们的写法有些不同。比如 SVG 2 中,svg 元素上的 versionbaseProfile 属性,就被删除了,也就是说如果不写 version,即代表是 SVG 2;
  • xmlns: 用于指定命名空间,它的值看起来像个链接,但其本意只是一个具有唯一性的字符串。有了命名空间,则该 <svg> 和它的子元素就都位于这个命名空间下,避免出现某个标签(比如 XHTML 和 SVG 都有一个 <title> 标签)不知道是属于谁的问题;
  • xmlns:xlink:是一个 XML 命名空间声明,它定义了 xlink 为前缀的元素和属性在XML文档中的命名空间,比如在 SVG1.x 版本中使用图片, <image xlink:href="./前进.svg"></image> 中的 href 属性,就有个 xlink 前缀,表明 href 属性属于 W3C xlink 命名空间,它的值要遵循相应规范。在 SVG2 中,建议直接使用 href 即可,不需要带上 xlink 前缀;
  • width/height:用于指定 svg 的视口坐标系的宽高,默认值为 300150,不用写单位,默认为 px

综上所述,我们自己直接通过创建一个 svg 文件来生成 SVG2,最简单的写法如下:

svg 复制代码
<svg xmlns="http://www.w3.org/2000/svg">
  <rect width="100" height="100"></rect>
</svg>

在浏览器打开效果如下:

在 html 中引用

在 html 中引用外部的 svg 文件,可以像使用图片那样使用,比如比较常见的 2 种方式是:

  • 通过 <img> 标签引入:<img src="./前进.svg" alt="" />
  • 通过背景图片引入:
html 复制代码
<style>
  .bg {
    width: 100px;
    height: 100px;
    background-image: url('./前进.svg');
    background-size: cover;
  }
</style>

<div class="bg"></div>

在 html 文件中使用 svg 元素

我们也可以直接在 html 文件中通过 <svg> 元素来绘制图形:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>探究svg</title>
    <style>
      svg {
        border: 1px solid red;
      }
    </style>
  </head>
  <body>
    <svg width="300" height="150" xmlns="http://www.w3.org/2000/svg">
      <rect width="100" height="100"></rect>
    </svg>
  </body>
</html>

因为没有给 <svg> 添加 version 属性,所以使用的版本是 SVG2,我还在 <style> 中直接给 <svg> 本身添加上了红色边框样式,效果如下:

<svg> 里的 widthheight 如果为默认值,可以省略不写,xmlns 也可以省略不写,浏览器解析器会自动添加:

html 复制代码
<body>
  <svg>
    <rect width="100" height="100"></rect>
  </svg>
</body>

通过 js 创建 svg

原生 js 创建

前面介绍的创建 svg 的方法中,我们通过 <svg>xmlns 来指定了命名空间,在用 js 创建 svg 时,所有的元素也都需要添加命名空间,其方式是使用为解决原本的 DOM1 API 无法定义命名空间这一问题而推出的 DOM2 API

所谓的 DOM2 API,其作用和去掉 NS 后的同名的 DOM1 API 是等效的,比如createElementNS 的作用和 createElement 一样都是用来创建元素的,只不过 DOM2 API 的第一个参数为命名空间,对于像 width 这样不带前缀的属性,命名空间就赋值为 null。代码如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>探究svg</title>
    <style>
      svg {
        border: 1px solid red;
      }
    </style>
  </head>
  <body>
    <script>
      window.onload = function () {
        // 命名空间
        const xmlns = 'http://www.w3.org/2000/svg'

        // 定义 svg
        const svg = document.createElementNS(xmlns, 'svg')

        // 定义 rect
        const rect = document.createElementNS(xmlns, 'rect')
        rect.setAttributeNS(null, 'width', 200)
        rect.setAttributeNS(null, 'height', 100)

        // 添加到 dom 中
        svg.appendChild(rect)
        document.body.appendChild(svg)
      }
    </script>
  </body>
</html>

创建后效果如下:

使用 Snap.svg 创建

直接使用原生 js 处理 svg 比较麻烦,如果真想通过 js 来创建或处理 svg,可以使用 Snap.svg(类似于 jQuery )这个库:

html 复制代码
<script src="../js/snap.svg-min.js"></script>
<script>
  window.onload = function () {
     // 定义 svg
    const svg = Snap(300, 300)
    
    // 定义 rect
    const rect = svg.rect(0, 0, 200, 200)
    // 给 rect 添加属性
    rect.attr({
      fill: 'red'
    })
    
    // 添加到 dom 中
    document.body.appendChild(svg.node)
  }
</script>

直接通过 Snap() 创建 svg,可以传入宽高值指定 svg 的大小,如果不传则默认大小为 300px * 150px。Snap() 还可以传入其它类型的参数,例如传入选择器以获取已经创建的 svg:Snap('#my-canvas')

创建基本形状有着对应的方法,比如也是创建矩形,就直接使用 svg.rect(),传入的参数为矩形的 xy 和宽高值。如果想给矩形添加属性可以通过 rect.attr() 传入对象。 最后将 svg.node 添加到 dom 中,因为得到的 svg 本身是个对象而不是直接就是 <svg> 元素:

效果如下:

通过 Adobe Illustrators 绘制

可以使用绘图软件 AI 直接绘制好图形,然后选择"文件 - 导出 - 导出为..." (也可以选择"导出为多种屏幕所用格式")

然后在保存文件时选择类型为 SVG:

这样导出得到的 svg 文件,代码示例如下:

html 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 161 103">
  <rect x=".5" y=".5" width="160" height="102"/>
  <path d="M160,1V102H1V1H160m1-1H0V103H161V0h0Z"/>
</svg>

相关推荐
Myli_ing27 分钟前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风30 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
软件小伟39 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾1 小时前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧1 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep7012 小时前
第8章利用CSS制作导航菜单
前端·css
hummhumm2 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
幼儿园的小霸王2 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue
疯狂的沙粒2 小时前
对 TypeScript 中高级类型的理解?应该在哪些方面可以更好的使用!
前端·javascript·typescript