持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情
SVG 全称为(Scalable Vector Graphics),即可缩放矢量图形
SVG 是一种基于XML格式的矢量图,主要用于定义二维图形,支持交互和动画
SVG可以直接嵌入到DOM树中,成为DOM树的一部分
SVG 规范是万维网联盟(W3C) 自 1998 年以来开发的标准,存在版本SVG V1.X 和 SVG V2.x
目前最为常用的版本是SVG V2.x
SVG 图像可在不损失质量的情况下按比例缩放,并支持无损压缩
基于XML的SVG可轻松的用文本编辑器或矢量图形编辑器创建和编辑,并可以直接在浏览器显示
特点
优点
优点 | 说明 |
---|---|
扩展性好 | SVG是矢量图,不是光栅图形(位图),所以SVG放大不会失真 矢量图像是基于矢量的点、线、形状和数学公式来构建的图形,该图形是没有像素的,放大缩小是不会失真 光栅图像是由像素点构建的图像——微小的彩色方块,大量像素点可以形成高清图像,比如照片。图像像素越多,质量越高 |
灵活性强 | SVG是基于XML格式的 可结合其它的语言和技术一起使用,包括 CSS、JavaScript、 HTML 和 SMIL |
方便执行动画 | SVG 图像可以使用 JS 、 CSS 和 SMIL 进行动画处理 |
轻量级 | 与其它格式相比,SVG 图像的尺寸非常小 根据图像的不同,PNG 图像质量可能是 SVG 图像的 50 倍 |
适合打印 | SVG是矢量图,所以SVG 图像可以以任何分辨率打印,而不会损失图像质量,且支持压缩 |
易于编辑 | 只需一个文本编辑器就可以创建 SVG 图像。设计师通常会使用 Adobe Illustrator (AI)等矢量图形工具创建和编辑 |
例如SEO | SVG最终会作为DOM的一部分,所以相比图片而言,搜索引擎更容易读取SVG的语义,并进行收录 |
缺点
缺点 | 说明 |
---|---|
不适合操作高清图片 | SVG 格式非常适合用于徽标和图标(ICON)等 2D 图形,但不适用于高清图片,不适合进行像素级操作 SVG 的图像无法显示与标准图像格式一样多的细节,因为它们是使用点和路径而不是像素来渲染的 |
不适合复杂的图片处理 | SVG 图像变得复杂时,生成的DOM也会变多,因此加载会比较慢 |
SVG适用场景
- SVG 非常适合显示矢量徽标(Logo)、图标(ICON)和其他几何设计
- SVG 适合应用在需适配多种尺寸的屏幕上展示,因为SVG的扩展性更好
- SVG 可以与 JS 交互来制作线条动画、过渡和其他复杂的动画, 也可以与 CSS 动画交互,也可以使用自己内置的 SMIL 动画
- SVG 也非常适合制作各种图表(条形图、折线图、饼图、散点图等等),以及大屏可视化⻚面开发
SVG vs Canvas
SVG | Canvas |
---|---|
SVG 是基于矢量的点、线、形状和数学公式来构建的图形,该图形是没有像素的,放大缩小不会失真 | Canvas 是由一个个像素点构成的图形,放大会使图形变得颗粒状和像素化(模糊) |
当 SVG 很复杂时,它的渲染就会变得很慢,因为在很大程度上去使用 DOM 时,渲染会变得很慢 | Canvas 提供了高性能的渲染和更快的图形处理能力 所以当图像中具有大量元素时,SVG 文件的大小会增⻓得更快(导致DOM变得复杂),而Canvas并不会增加太多 |
SVG 可以通过JavaScript 和 CSS 进行修改,用SVG来创建动画和制作特效非常方便 | Canvas只能通过JavaScript进行修改,创建动画得一帧帧重绘 |
SVG 非常适合显示矢量徽标(Logo)、图标(ICON)和其他几何设计 | Canvas 主要用于游戏开发、绘制图形、复杂照片的合成,以及对图片进行像素级别的操作,如:取色器、复古照片 |
初体验
由于 SVG 是一个 XML 文件格式。在编写XML文档时,通常是推荐编写XML声明
虽然这个声明并不是强制性的,但是推荐写上
手动编写svg
v1.x
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!--
<?xml ?> - xml的声明 --- 必须唯一svg文件的第一行
version - xml的版本 可选值为1.0 和 1.1 (2.0的时候 不需要写version)
encoding - xml的编码格式 默认值就是UTF-8
standalone - 一个boolean值,用于指定是否需要外部标记声明(DTD文件)
- 所谓DTD文件就是xml的格式校对文件,xml的标签是可以自定义的
- 而浏览器解析svg中的xml格式是需要被预先约定的
- 所以需要对应的DTD文件 来校对 SVG中对应的xml格式是都正确
- no 默认值 - 依赖外部声明 需要手动指定外部DTD文件
- yes - 不依赖外部声明 对应的标记声明 编写在svg文件内部
-->
<!-- 这是最为常见的SVG对应的DTD格式文件 -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!--
这里是一个SVG 默认svg是行内替换元素 默认的宽高是 300 * 150
version - 版本 - V2.0 已被废弃
baseProfile - 作者认为正确渲染内容所需要的最小的 SVG 语言概述 - V2.0已被废弃
- full - 正常的概述 - 适用于PC
- basic - 轻量级的概述 - 适用于PDA
- tiny - 更轻量的概述 - 适用于mobile
width - 宽
height - 高
xmlns - xml namespace 表示为svg开启一个命名空间(模块)
- 避免svg中的某些属性 和 html中的某些属性冲突
- 如 title属性 在svg 和 html的head中同时存在,且语义不同
- 但是 目前如果不写xmlns 浏览器会自动生成对应的xmlns
- 因为xmlns的值一般是固定的 即为http://www.w3.org/2000/svg
- 所以在多数情况下,我们并不需要去编写对应的xmlns
-->
<svg
version="1.0"
baseProfile="full"
width="100"
height="100"
xmlns="http://www.w3.org/2000/svg"
>
<rect x="0" y="0" width="100" height="100"></rect>
</svg>
v2.x
<svg
width="100"
height="100"
xmlns="http://www.w3.org/2000/svg"
>
<rect x="0" y="0" width="100" height="100"></rect>
</svg>
使用JS编写SVG
使用JS脚本来创建SVG时,创建的元素都是需要添加命名空间的,如果不存在对应的命名空间需要使用null来代替
操作SVG的JS api和操作DOM的api是一致的,唯一的区别是在方法名称后边加上了NS{也就是namespace}
方法 | 说明 |
---|---|
createElementNS(ns,elname) | 创建SVG元素 |
setAttributeNS(ns,attrname,value) | 给SVG元素添加属性 |
getAttributeNS(ns,attrname) | 获取SVG元素上的属性 |
hasAttributeNS(ns, attrname) | 判断SVG元素上是否存在某个属性 |
removeAttributeNS(ns,attname) | 删除SVG元素上的某个属性 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 定义命名空间
const xmlns = 'http://www.w3.org/2000/svg'
// 创建svg元素 --- 使用JS创建svg元素,必须指定命名空间
const svgEl = document.createElementNS(xmlns, 'svg')
const rectEl = document.createElementNS(xmlns, 'rect')
// 属性设置
svgEl.setAttributeNS(null, 'width', 100)
svgEl.setAttributeNS(null, 'height', 100)
rectEl.setAttributeNS(null, 'width', 50)
rectEl.setAttributeNS(null, 'height', 50)
// 添加到dom树中
svgEl.appendChild(rectEl)
document.body.appendChild(svgEl)
</script>
</body>
</html>
简单使用
作为image的src使用
<!-- svg会被识别为普通图片 无法进行任何的交互 -->
<img src="./rect.svg" alt="rect">
作为背景使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* svg会被识别为普通图片 无法进行任何的交互 */
.svg {
width: 300px;
height: 300px;
background-color: red;
background-image: url(./rect.svg);
background-repeat: no-repeat;
}
</style>
</head>
<body>
<div class="svg"></div>
</body>
</html>
直接在html中使用svg源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<!-- 此时svg会作为dom的一部分,所以可以进行相应的交互 -->
<!-- 单独作为svg文件的时候,svg的xmlns属性是不可以省略的 -->
<!-- 但是如果是直接在html中使用svg源代码,对应的xmlns属性是可以省略的 -->
<svg
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100"></rect>
</svg>
</body>
</html>