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>

相关推荐
zhougl9961 小时前
html处理Base文件流
linux·前端·html
花花鱼1 小时前
node-modules-inspector 可视化node_modules
前端·javascript·vue.js
HBR666_2 小时前
marked库(高效将 Markdown 转换为 HTML 的利器)
前端·markdown
careybobo3 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
杉之4 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端4 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡5 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木6 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!6 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
難釋懷7 小时前
JavaScript基础-移动端常见特效
开发语言·前端·javascript