数据可视化-SVG(一)

776 阅读22分钟

一、邂逅SVG

1.1 认识SVG

  • SVG 全称为(Scalable Vector Graphics),即可缩放矢量图形。(矢量定义:既有大小又有方向的量。在物理学中称作矢量,如一个带箭头线段:长度表示大小,箭头表示方向;在数学中称作向量。在计算机中,矢量图可无限放大而不变形)

  • SVG 是一种基于XML格式的矢量图,主要用于定义二维图形,支持交互和动画。

  • SVG 规范是万维网联盟(W3C) 自 1998 年以来开发的标准。

  • SVG 图像可在不损失质量的情况下按比例缩放,并支持压缩

  • 基于XML的SVG可轻松的用文本编辑器或矢量图形编辑器创建和编辑,并可以直接在浏览器显示。

1.2 SVG发展史

  • SVG 2.0 版本(推荐)

    • SVG 2.0于2016 年 9 月 15 日成为W3C 候选推荐标准,最新草案于2020年5月26日发布。

    • SVG2.x Change From SVG1.x ( www.w3.org/TR/SVG/chan… ),比如:

      • Removed the baseProfile and version attributes from the ‘svg’ element.
      • Added the ability to use 'auto' for the width and height attributes on image.
      • Added ‘lang’ attribute on ‘desc’ and ‘title’ elements.
      • Removed the ‘xlink:type’, ‘xlink:role’, ‘xlink:arcrole’, ‘xlink:show’ and ‘xlink:actuate’ attributes.
      • Deprecated the ‘xlink:href’ attribute in favor of using ‘href’ without a namespace.

1.3 SVG 优缺点

  • 优点
    • 扩展好:矢量图像在浏览器中放大缩小不会失真,可被许多设备和浏览器中使用。而光栅图像(PNG 、JPG)放大缩小会失真。

      • 矢量图像是基于矢量的点、线、形状和数学公式来构建的图形,该图形是没有像素的,放大缩小是不会失真的。

      • 光栅图像是由像素点构建的图像——微小的彩色方块,大量像素点可以形成高清图像,比如照片。图像像素越多,质量越高。

    • 灵活:SVG是W3C开发的标准,可结合其它的语言和技术一起使用,包括 CSS、JavaScript、 HTML 和 SMIL 。SVG图像可以直接使用JS和CSS进行操作,使用时非常方便和灵活,因为SVG也是可集成到 DOM 中的。

    • 可以动画:SVG 图像可以使用 JS 、 CSS 和 SMIL 进行动画处理。对于 Web 开发人员来说非常的友好。

    • 轻量级:与其它格式相比,SVG 图像的尺寸非常小。根据图像的不同,PNG 图像质量可能是 SVG 图像的 50 倍。

    • 可打印:SVG 图像可以以任何分辨率打印,而不会损失图像质量。

    • 利于SEO:SVG 图像被搜索引擎索引。因此,SVG 图像非常适合 SEO(搜索引擎优化)目的。

    • 可压缩:与其它图像格式一样,SVG 文件支持压缩。

    • 易于编辑:只需一个文本编辑器就可以创建 SVG 图像。设计师通常会使用 Adobe Illustrator (AI)等矢量图形工具创建和编辑。

  • 缺点
    • 不适合高清图片制作

      • SVG 格式非常适合用于徽标和图标(ICON)等 2D 图形,但不适用于高清图片,不适合进行像素级操作。

      • SVG 的图像无法显示与标准图像格式一样多的细节,因为它们是使用点和路径而不是像素来渲染的

    • SVG 图像变得复杂时,加载会比较慢

1.4 SVG的应用场景

  • SVG 非常适合显示矢量徽标(Logo)、图标(ICON)和其他几何设计。

  • SVG 适合应用在需适配多种尺寸的屏幕上展示,因为SVG的扩展性更好。

  • 当需要创建简单的动画时,SVG 是一种理想的格式。

  • SVG 可以与 JS 交互来制作线条动画、过渡和其他复杂的动画。

  • SVG 可以与 CSS 动画交互,也可以使用自己内置的 SMIL 动画

  • SVG 也非常适合制作各种图表(条形图、折线图、饼图、散点图等等),以及大屏可视化页面开发。

1.5 SVG 和 Canvas的区别

  • 可扩展性:

    • SVG 是基于矢量的点、线、形状和数学公式来构建的图形,该图形是没有像素的,放大缩小不会失真

    • Canvas 是由一个个像素点构成的图形,放大会使图形变得颗粒状和像素化(模糊)

    • SVG可以在任何分辨率下以高质量的打印。Canvas 不适合在任意分辨率下打印。

  • 渲染能力:

    • 当 SVG 很复杂时,它的渲染就会变得很慢,因为在很大程度上去使用 DOM 时,渲染会变得很慢。

    • Canvas 提供了高性能的渲染和更快的图形处理能力,例如:适合制作H5小游戏。

    • 当图像中具有大量元素时,SVG 文件的大小会增长得更快(导致DOM变得复杂),而Canvas并不会增加太多。

  • 灵活度:

    • SVG 可以通过JavaScript 和 CSS 进行修改,用SVG来创建动画和制作特效非常方便。

    • Canvas只能通过JavaScript进行修改,创建动画得一帧帧重绘。

  • 使用场景:

    • Canvas 主要用于游戏开发、绘制图形、复杂照片的合成,以及对图片进行像素级别的操作,如:取色器、复古照片。

    • SVG 非常适合显示矢量徽标(Logo)、图标(ICON)和其他几何设计。

二、SVG初体验

2.1 XML 和 DTD 声明

  • 由于 SVG 是一个 XML 文件格式。在编写XML文档时,通常是推荐编写XML声明。因为在 XML 1.0 中,XML 声明是可选的,推荐写但不是强制性。然而,在 XML 1.1 中,声明是强制性的,如果没有声明,则自动暗示该文档是 XML 1.0 文档。所以这里建议在编写SVG文件时也编写一个XML 声明。

  • SVG的XML声明格式:<?xml version="1.0" encoding="UTF-8" standalone="no" ?>

    • version 指定版本(必填)

    • encoding 指定XML文档的编码(可选,默认是UTF-8)

    • standalone:指定当前 XML 文档是否依赖于外部标记声明(可选,使用该属性时,需和DTD声明一起用才有意义)。

      • no(默认值):代表依赖外部标记声明

      • yes:代表依赖内部默认的标记声明

  • SVG的文档类型声明(DTD),让解析器验证XML文件是否符合该规范,与HTML5文件的DTD声明类似。

    • XML中内部 DTD 声明(可选)

    • XML中外部 DTD 声明(可选)

      • <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

2.2 如何创建SVG

  • 在一个单独的svg文件中绘制,svg文件可直接在浏览器预览或嵌入到HTML中使用(推荐)

    • 第一步:新建一个 svg 文件,在文件第一行编写XML文件声明
    • 第二步:编写 一个元素,并给该元素添加如下属性:
      • version: 指定使用svg的版本,值为 1.0 和 1.1,并没有 2.0。
      • baseProfile:SVG 2 之前,version 和 baseProfile 属性用来验证和识别 SVG 版本。而SVG2后不推荐使用这两个属性了。
      • width / height :指定svg画布(视口)的宽和高,默认值分别为300和150,默认使用px单位
      • xmlns:给svg元素绑定一个命名空间 意味着这个 <svg> 标签和它的子元素都属于该命名空间下(比如:html中的<title>和svg的<title>可通过命名空间做区分)。
    • 第三步:在<svg>元素中添加 图形(比如:<rect>) 元素
    • 第四步:在浏览器直接预览 或 嵌入到 HTML中预览(嵌入HTML有6种方案)
      • 1.0版本
      <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
      <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
      <!-- 
       version="1.0"
       baseProfile="full" 正确渲染svg内容时所需要最小SVG语言概述(版本); full:正常的svg语言概述  basic:基本SVG语言概述  tiny: 轻量级SVG语言概述
      
       xmlns: 指定svg元素 和 svg内的子元素都是属于 http://www.w3.org/2000/svg 这个命名空间下
       -->
      <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>
        <title>我是svg title</title>
      </svg>
      
      • 2.0版本
      <?xml version="1.0" standalone="no" ?>
      <svg
       width="100"
       height="100"
       xmlns="http://www.w3.org/2000/svg"
      >
        <rect x="0" y="0" width="100" height="100"></rect>
      </svg>
      
  • 直接在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>
    </head>
    <body>
      <!-- 创建svg 1.0 -->
      <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>
    
      <!-- 创建svg 2.0 -->
      <svg
        width="100"
        height="100"
        xmlns="http://www.w3.org/2000/svg"
      >
        <rect x="0" y="0" width="100" height="100"></rect>
      </svg>
    
      <!-- 
        创建svg 2.0  简写
        xmlns="http://www.w3.org/2000/svg" 这个命名空间浏览器的解析器会自动添加
    
        默认w 300px  h: 150px
       -->
      <svg>
        <rect x="0" y="0" width="100" height="100"></rect>
      </svg>
    </body>
    </html>
    
  • 直接使用JavaScript代码来生成svg矢量图

  • 使用AI(Adobe IIIustractor)矢量绘图工具来绘制矢量图,并导出为svg文件(推荐)

2.3 JS创建SVG

  • 使用JS脚本来创建SVG时,创建的元素都是需要添加命名空间

    • 比如:创建或者元素都需要添加命名空间(http://www.w3.org/2000/svg

    • 对于元素上的属性如果不带前缀的,命名空间赋值为null

  • 因为在XML1.1命名空间规范中建议,不带前缀的属性(带前缀xlink:href)命名空间的名称是没有值的,这时命名空间的值必须 使用null值。

  • 创建 SVG 常用的 DOM2 API:

    • createElementNS(ns,elname):创建SVG元素
    • setAttributeNS(ns,attrname,value):给SVG元素添加属性
    • getAttributeNS(ns,attrname):获取SVG元素上的属性
    • hasAttributeNS(ns, attrname): 判断SVG元素上是否存在某个属性
    • removeAttributeNS(ns,attname):删除SVG元素上的某个属性
    • 更多的API
    <!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>
      <!-- 创建svg2.0 -->
      <!-- <svg
        width="100"
        height="100"
        xmlns="http://www.w3.org/2000/svg"
      >
        <rect x="0" y="0" width="100" height="100"></rect>
      </svg> -->
    
      <script>
        // 1.创建 svg 和 rect 元素
        const xmlns = "http://www.w3.org/2000/svg"
        const svgEl = document.createElementNS(xmlns, 'svg')
        const rectEl = document.createElementNS(xmlns, 'rect')
    
        // 2.给 svg 和 rect 元素对象添加属性
        svgEl.setAttributeNS(null, 'version', '1.0')
        svgEl.setAttributeNS(null, 'width', 100)
        svgEl.setAttributeNS(null, 'height', 100)
    
        rectEl.setAttributeNS(null, 'width', 50)
        rectEl.setAttributeNS(null, 'height', 50)
    
        // 3.将svg添加到body上
        svgEl.appendChild(rectEl)
        document.body.appendChild(svgEl)
    
      </script>
    </body>
    </html>
    

2.4 使用SVG的方式

  • img

    <!-- 在img中直接使用svg -->
    <img src="./rect.svg" alt="">
    
  • background-image

    <!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>
        .box{
          width: 200px;
          height: 200px;
          background-image: url(./rect.svg);
          background-repeat: no-repeat;
        }
      </style>
    </head>
    <body>  
    
      <div class="box"></div>
    </body>
    </html>
    
  • 源代码用在html

    • 作为HTML 的DOM元素,支持交互,只兼容ie9以上
    <!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>
    
      <svg
        width="100"
        height="100"
        xmlns="http://www.w3.org/2000/svg"
      >
        <rect x="0" y="0" width="100" height="100"></rect>
      </svg>
    
    </body>
    </html>
    
  • object元素

    • 支持交互式 svg,能拿到object的引用,为 SVG 设置动画、更改其样式表等
  • iframe元素

    • 支持交互式 svg,能拿到iframe的引用,为 SVG 设置动画、更改其样式表等
  • embed元素

    • 支持交互式 svg,能拿到embed的引用,为 SVG 设置动画、更改其样式表等,对旧版浏览器有更好的支持

三、SVG的坐标系统和单位

3.1 坐标系统

  • SVG 使用的坐标系统(网格系统)和 Canvas的差不多。坐标系是以左上角为 (0,0) 坐标原点,坐标以像素为单位,x 轴正方向是向右,y 轴正方向是向下。

  • SVG Grid(坐标系)

    • <svg>元素默认宽为 300px, 高为 150px。

    • 通常来说网格中的一个单元相当于 svg 元素中的一像素。

    • 基本上在 SVG 文档中的 1 个像素对应输出设备(比如显示屏)上的 1 个像素(除非缩放)。

    • <svg>元素和其它元素一样也是有一个坐标空间的,其原点位于元素的左上角,被称为初始视口坐标系

    • <svg>的 transform 属性可以用来移动、旋转、缩放SVG中的某个元素,如<svg>中某个元素用了变形,该元素内部会建立一个新的坐标系统,该元素默认后续所有变化都是基于新创建的坐标系统

3.2 坐标单位

  • SVG坐标系统,在没有明确指定单位时,默认以像素为单位

    • 比如:<rect x="0" y="0" width="100" height="100" />
    • 定义一个矩形,即从左上角开始,向右延展 100px,向下延展 100px,形成一个 100*100 大的矩形。
  • 当然也可以手动指明坐标系的单位

    image.png

四、viewport 和 viewBox

4.1 视口坐标系和用户坐标系

  • 视口(viewport)

    • 视口是 SVG 可见的区域(也可以说是SVG画布大小)。可以将视口视为可看到特定场景的窗口。

    • 可以使用<svg>元素的width和height属性指定视口的大小。

    • 一旦设置了最外层 SVG 元素的宽度和高度,浏览器就会建立初始视口坐标系和初始用户坐标系。

  • 视口坐标系

    • 视口坐标系是在视口上建立的坐标系,原点在视口左上角的点(0, 0),x轴正向向右,y轴正向下

    • 初始视口坐标系中的一个单位等于视口中的一个像素,该坐标系类似于 HTML 元素的坐标系。

  • 用户坐标系( 也称为当前坐标系或正在使用的用户空间,后面绘图都是参照该坐标系 )

    • 用户坐标系是建立在 SVG 视口上的坐标系。该坐标系最初与视口坐标系相同——它的原点位于视口的左上角。

    • 使用viewBox属性,可以修改初始用户坐标系,使其不再与视口坐标系相同

  • 为什么要有两个坐标系?

    • 因为SVG是矢量图,支持任意缩放。在用户坐标系统绘制的图形,最终会参照视口坐标系来进行等比例缩放

4.2 视图框-viewBox

  • 视图框(viewBox)

    • viewport是 SVG 画布的大小,而 viewBox 是用来定义用户坐标系中的位置和尺寸 (该区域通常会被缩放填充视口)

    • viewBox 也可理解为是用来指定用户坐标系大小。因为SVG的图形都是绘制到该区域中。用户坐标系可以比视口坐标系更小或更大,也可以在视口内完全或部分可见

    • 一旦创建了视口坐标系(<svg>使用width和height),浏览器就会创建一个与其相同的默认用户坐标系。

    • 可以使用 viewBox 属性指定用户坐标系的大小。

      • 如果用户坐标系与视口坐标系具有相同的高宽比,它将viewBox区域拉伸以填充视口区域。

      • 如果用户坐标系和视口坐标系没有相同的宽高比,可用 preserveAspectRatio 属性来指定整个用户坐标系统是否在视口内可见

  • viewBox语法

    • viewBox = ,比如:viewBox =' 0 0 100 100'

      • <min-x><min-y> 确定视图框的左上角坐标(不是修改用户坐标系的原点,绘图还是从原来的 0, 0 开始)

      • <width> <height>确定该视图框的宽度和高度。

        • 宽度和高度不必与父元素上设置的宽度和高度相同。

        • 宽度和高度负值无效,为 0 是禁用元素的显示

4.3 视图框-viewBox-相同的宽高比

  • 看一个 viewport 和 viewBox 有相同的宽高比的例子:

    • 在viewBox属性上设置视图框为视口大小的一半
    • 暂时不改变这个视图框左上角,将<min-x><min-y>设置为零
    • 视图框的宽度和高度将是视口宽度和高度的一半
  • viewbox="0 0 100 100" 具体做什么的呢?

    • 指定画布可显示的区域,用户坐标系从 (0, 0) 的左上点到 (100, 100) 的点,默认单位是px。

    • 然后将 SVG 图形绘制到该 viewBox 区域。

    • viewBox区域等比例被放大(放大不会失真)以填充整个视口

    • 用户坐标系映射到视口坐标系,因此——在这种情况下——1个用户单位等于4个视口单位。

    • 在 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>
        body, ul {
          margin: 0;
          padding: 0;
        }
    
        body {
          background-image: url(../images/grid.png);
        }
        svg {
          background-color: rgba(255, 0, 0, 0.1);
        }
      </style>
    
    </head>
    <body>
    
    
      <svg width="400" height="400" viewBox="0 0 100 100" >
        <circle cx="50" cy="50" r="50"></circle>
      </svg>
    
    </body>
    </html>
    
    相同宽高比.png
    <!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>
        body, ul{
          margin: 0;
          padding: 0;
        }
    
        body{
          background-image: url(../images/grid.png);
        }
        svg{
          background-color: rgba(255, 0, 0, 0.1);
        }
      </style>
    
    </head>
    <body>
    
    
      <svg width="400" height="400" viewBox="50 50 100 100" >
        <circle cx="50" cy="50" r="50"></circle>
      </svg>
    
    </body>
    </html>
    
    相同宽高比-改变起点.png

4.4 视图框-viewBox-不同的宽高比

  • 在400*400的视口中,viewbox="0 0 200 100" 具体做什么的呢?

    • 保留视图框viewBox的宽高比,但视图框viewBox不会拉伸以覆盖整个视口区域

    • 视图框viewBox在视口内垂直和水平居中

  • 如何改变视口内的视框位置?

    • <svg>添加preserveAspectRatio属性,该属性允许强制统一缩放视图框viewBox

      • preserveAspectRatio= "none", 强制拉伸图形以填充整个视口
      • preserveAspectRatio= “xMinYMin”, 图形在视口的最小x和y轴上显示
    <!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>
        body, ul{
          margin: 0;
          padding: 0;
        }
    
        body{
          background-image: url(../images/grid.png);
        }
        svg{
          background-color: rgba(255, 0, 0, 0.1);
        }
      </style>
    
    </head>
    <body>
    
    
      <svg width="400" height="400" 
        viewBox="0 0 200 100" 
        preserveAspectRatio="xMinYMin"
      >
        <circle cx="50" cy="50" r="50"></circle>
      </svg>
    
    </body>
    </html>
    
    不同宽高比.png

五、基本图形的绘制

5.1 矩形

  • <rect>元素在屏幕上绘制一个矩形(rect)

  • <rect>元素6 个基本属性

    • x :矩形左上角的 x 轴位置
    • y :矩形左上角的 y轴位置
    • width :矩形的宽度
    • height :矩形的高度
    • rx :圆角的 x 轴方位的半径
    • ry :圆角的 y 轴方位的半径
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" >
    
      <rect x="0" y="0" width="100" height="50"></rect>
      <rect x="100" y="100" width="100" height="50" rx="20" ry="20"></rect>
    </svg>
    
    rect.png

5.2 圆形

  • <circle>元素会在屏幕上绘制一个圆形

  • <circle>元素有 3 个基本属性

    • r :圆的半径
    • cx :圆心的 x轴位置
    • cy :圆心的 y轴位置
    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <circle cx="100" cy="100" r="50" fill="skyblue"></circle>
    </svg>
    
    image.png

5.3 椭圆

  • <ellipse>元素是绘制椭圆

  • <ellipse>元素 4 个基本属性

    • rx :椭圆的 x轴半径,数学上的长轴半径
    • ry :椭圆的 y轴半径,数学上的短轴半径
    • cx :椭圆中心的 x轴位置
    • cy :椭圆中心的 y轴位置
    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <ellipse rx="25" ry="50" cx="100" cy="100" fill="blue"></ellipse>
    </svg>
    
    image.png

5.4 直线

  • <line>元素是绘制直线

    • 它取两个点的位置作为属性,指定这条线的起点和终点位置
    • 需描边才能显示,不支持填充和Canvas线条一样
  • <line>元素4 个基本属性

    • x1 :起点的 x 轴位置
    • y1 :起点的 y轴位置
    • x2 :终点的 x轴位置
    • y2 :终点的 y轴位置
    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <line x1="50" y1="50" x2="150" y2="50" stroke="blue" stroke-width="5"></line>
    </svg>
    
    image.png

5.5 折线

  • <polyline>元素是一组连接在一起的直线。

    • 因为它可以有很多的点,折线的所有点位置都放在一个 points 属性里。
    • 默认会填充黑色
  • <polyline>元素1 个基本属性

    • points : 点集数列。每个数字用空白、逗号、终止命令符或者换行符分隔开
    • 每个点必须包含 2 个数字,一个是 x 坐标,一个是 y 坐标。
    • 所以点列表 (0,0), (1,1) 和 (2,2) 可以写成这样:“0 0, 1 1, 2 2”
      • 支持格式: “0 0, 1 1, 2 2”或 “0 ,0 , 1, 1, 2, 2”或 “0 0 1 1 2 2”
    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <polyline points="20 0, 50 50, 20 100, 80 100" fill = "transparent" stroke="red"></polyline>
    
      <polyline points="80 50 100 90 120 50" fill = "transparent" stroke="blue"></polyline>
    </svg>
    
    image.png

5.6 多边形

  • <polygon>元素是绘制多边形

    • 和折线很像,它们都是由连接一组点集的直线构成。不同的是,< polygon> 的路径在最后一个点处自动回到第一个点。需要注意的是,矩形也是一种多边形,也可以用多边形创建一个矩形
    • 默认会填充黑色
  • 元素1 个基本属性

    • points :点集数列。每个数字用空白符、逗号、终止命令或者换行符分隔开
    • 每个点必须包含 2 个数字,一个是 x 坐标,一个是 y 坐标
    • 点列表 (0,0), (1,1) 和 (2,2) 推荐写成这样:“0 0, 1 1, 2 2”
    • 路径绘制完后闭合图形,所以最终的直线将从位置 (2,2) 连接到位置 (0,0)
    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <!-- 三角形 -->
      <polygon points="20 0, 50 50, 20 100" fill = "green" stroke="blue"></polygon>
    
      <!-- 矩形 -->
      <polygon points="80 20, 160 20, 160 60, 80 60" fill = "transparent" stroke="red"></polygon>
    </svg>
    
    image.png

5.7 路径(path) + 命令

  • <path>元素可能是 SVG 中最常见的形状。可以用 <path>元素绘制矩形(直角矩形或圆角矩形)、圆形、椭圆、折线形、多边形,以及一些其他的形状,例如贝塞尔曲线、2 次曲线等曲线。

    • 默认会填充黑色,默认路径不会闭合
  • <path>元素 1 个基本属性

    • d :一个点集数列,以及其它关于如何绘制路径的信息,必须M命令开头
    • 所以点列表 (0,0), (1,1) 和 (2,2) 推荐写成这样:“M 0 0, 1 1, 2 2”
    • 支持格式: “M 0 0, 1 1, 2 2”“M0 0, 1 1, 2 2”“M 0 ,0 , 1, 1, 2, 2”“M 0 0 1 1 2 2”
  • 命令

    • <path> 元素的形状是通过属性d定义的,属性d的值是一个 “命令 + 参数 ”的序列。

    • 每一个命令都用一个关键字母来表示,比如,字母“M”表示的是“Move to”命令,当解析器读到这个命令时,它就知道是打算移动到某个点。跟在命令字母后面的,是需要移动到的那个点的 x 和 y 轴坐标。比如移动到 (10,10) 这个点的命令,应该写成“M 10 10”命令。这一段字符结束后,解析器就会去读下一段命令。

    • 每一个命令都有两种表示方式,

      • 大写字母,表示采用绝对定位
      • 小写字母,表示采用相对定位(例如:从上一个点开始,向上移动 10px,向左移动 7px)。
    • 属性 d采用的是用户坐标系统,不需标明单位。

    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <!-- 绘制三角形,不闭合 -->
      <path d="M 20 0, 50 50, 20 100" fill = "transparent" stroke="blue"></path>
    
      <!-- 绘制三角形,闭合 -->
      <path d="M 80 0, 110 50, 80 100 Z" fill = "transparent" stroke="blue"></path>
    </svg>
    
    image.png
  • d属性值支持的命令

    • 直线命令

      • M / m:Move To
      • L / l :Line To
      • Z / z:Close Path
      • H / h:horizontal
      • V / v:vertical
    • 曲线命令

      • C :三次贝塞尔曲线
      • S:简写三次贝塞尔曲线
      • Q:二次贝塞尔曲线
      • T:简写二次贝塞尔曲线
    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <!-- l: 相对定位 -->
      <path d="M 20 0,L 80 50,l 20 50 Z" fill="transparent" stroke="red"></path>
    </svg>
    
    image.png

5.8 image

  • <image>元素的 href 属性引入图片URL

  • 注意事项

    • image 元素没设置 x , y 值,它们自动被设置为 0。

    • image 元素没设置 height 、width 时,默认为图片大小。

    • width 、height 等于 0,将不会呈现这个图像。

    • 需在 href 属性上引用外部的图像,不是src属性。

    • href属性兼容性

    <!-- 2.0版本 -->
    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <image 
        x="0" 
        y="0" 
        width="100" 
        height="100" 
        href="../images/avatar.jpeg"
      >
      </image>
    </svg>
    
    <!-- 1.0版本 -->
    <svg 
      version="1.0"
      baseProfile="full"
      width="300" height="300" 
      xmlns="http://www.w3.org/2000/svg" 
      xmlns:xlink="http://www.w3.org/1999/xlink"
    >
      <image 
       x="0"
       y="0"
       xlink:href="../images/avatar.jpeg"
       width="100"
       height="100"
      >
      </image>
    </svg>
    
    <!-- 2.0 + 1.0版本 -->
    <svg 
      version="1.0"
      baseProfile="full"
      width="300" height="300" 
      xmlns="http://www.w3.org/2000/svg" 
      xmlns:xlink="http://www.w3.org/1999/xlink"
    >
      <image 
       x="0"
       y="0"
       xlink:href="../images/avatar.jpeg"
       href="../images/avatar.jpeg"
       width="100"
       height="100"
      >
      </image>
    </svg>
    
    image.png

5.9 text

  • <text>元素是用来在SVG画布中绘制文字

  • <text>元素的基本属性

    • x 和 y 属性决定了文本在用户坐标系中显示的位置
    • text-anchor 文本流方向属性,可以有 start、middle、end 或 inherit 值,默认值 start
    • dominant-baseline 基线对齐属性 : 有 auto 、middle 或 hanging 值, 默认值:auto
  • 元素的字体属性

    • 文本的一个至关重要的部分是它显示的字体。SVG 提供了一些属性,类似于CSS 。下列的属性可以被设置为一个 SVG 属性或一个 CSS 属性:

      • font-family、font-style、font-weight、font-variant、font-stretch、font-size、font-size-adjust、kerning、letter-spacing、word-spacing和text-decoration。
    <svg 
      width="300" 
      height="300" 
      xmlns="http://www.w3.org/2000/svg"
    >
    
      <!-- 1.在svg中绘制一个文字 -->
      <!-- <text x="100" y="100" font-size="50" fill="red">Ay</text> -->
    
      <!-- 2.文本的对齐方式 -->
      <!-- <text x="100" y="100" text-anchor="middle"  font-size="50" fill="red">Ay</text> -->
    
      <!-- 3.基线对齐方式 :
        有 auto 、middle 或 hanging 值, 默认值:auto
      -->
      <text 
        x="100" 
        y="100" 
        dominant-baseline="middle" font-size="50" 
        fill="red"
      >Ay</text>
    
    </svg>
    
    image.png

5.10 tspan

  • <tspan> 元素用来标记大块文本的子部分,它必须是一个text元素或别的tspan元素的子元素。

    • x 和 y 属性决定了文本在视口坐标系中显示的位置
    • alignment-baseline 基线对齐属性:auto 、baseline、middle、hanging、top、bottom ... ,默认是 auto
    <svg 
      width="300" 
      height="300" 
      xmlns="http://www.w3.org/2000/svg" 
    >
    
      <!-- 1.在svg中绘制一个文字 -->
      <text x="40" y="100" font-size="20">
        iPhone14 
        <tspan fill="red">¥100</tspan>
      </text>
    
    </svg>
    
    image.png

六、图形的组合和复用

6.1 组合

  • 元素的组合

    • <g>元素是用来组合元素的容器
    • 添加到g元素上的变换会应用到其所有的子元素上
    • 添加到g元素的属性大部分会被其所有的子元素继承
    • g元素也可以用来定义复杂的对象,之后可以通过<use>元素来引用它们
  • 元素的属性(该元素只包含全局属性

    • 核心属性:id

    • 样式属性:class 、style

    • Presentation Attributes(也可说是 CSS 属性,这些属性可写在CSS中,也可作为元素的属性用):

      • cursor, display, fill, fill-opacity, opacity,…
      • stroke, stroke-dasharray, stroke-dashoffset, stroke-linecap, stroke-linejoin
      • 更多表示属性
    • 事件属性:onchange, onclick, ondblclick, ondrag…

    • 动画属性:transform

    • 更多

    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <!-- <circle cx="50" cy="50" r="30" fill="transparent" stroke="red"></circle>
      <circle cx="90" cy="50" r="30" fill="transparent" stroke="red"></circle>
      <circle cx="130" cy="50" r="30" fill="transparent" stroke="red"></circle>
      <circle cx="170" cy="50" r="30" fill="transparent" stroke="red"></circle> -->
      <g fill="transparent" stroke="red">
        <circle cx="50" cy="50" r="30"></circle>
        <circle cx="90" cy="50" r="30"></circle>
        <circle cx="130" cy="50" r="30"></circle>
        <circle cx="170" cy="50" r="30"></circle>
      </g>
    </svg>
    
    image.png

6.2 复用

  • SVG 是允许定义一些可复用元素

    • 即把可复用的元素定义在<defs>元素里面,然后通过<use>元素来引用和显示

    • 这样可以增加 SVG 内容的易读性、复用性和利于无障碍开发

  • <defs>元素,定义可复用元素

    • 例如:定义基本图形、组合图形、渐变、滤镜、样式等等

    • <defs>元素中定义的图形元素是不会直接显示的

    • 可在视口任意地方用来呈现在defs中定义的元素

    • <defs>元素没有专有属性,使用时通常也不需添加任何属性

    • <defs>定义的元素的坐标系参照 用户坐标系

  • <use>元素,引入复用元素

    • <use>元素从 SVG 文档中获取节点,并将获取到的节点复制到指定的地方

    • <use>等同于深度克隆DOM节点,克隆到use元素所在的位置。

    • 克隆的节点是不可见的,当给<use>元素应用CSS样式时须小心。因为克隆的 DOM 不能保证都会继承<use>元素上的CSS属性,但是CSS可继承的属性是会继承的。

  • <use>元素的属性

    • href: 需要复制元素/片段的 URL 或 ID(支持跨SVG引用)。默认值:无

    • xlink:href:(SVG2.0已弃用) 需要复制的元素/片段的 URL 或 ID 。默认值:无

    • x / y :元素的 x / y 坐标(相对复制元素的位置)。 默认值:0

    • width / height :元素的宽和高(在引入svg或symbol元素才起作用)。 默认值:0

    <svg
      width="300"
      height="300"
      xmlns="http://www.w3.org/2000/svg"  
    >
      <defs>
        <!-- 定义样式 -->
        <style>
          rect {
            fill: blue
          }
        </style>
    
        <!-- 定义矩形 -->
        <rect id="rectangle" x="0" y="0" width="100" height="50" fill="red"></rect>
    
        <!-- 定义组合图形 -->
        <g id="logo" fill="transparent" stroke="red">
          <circle cx="50" cy="200" r="25"></circle>
          <circle cx="90" cy="200" r="25"></circle>
          <circle cx="130" cy="200" r="25"></circle>
          <circle cx="170" cy="200" r="25"></circle>
        </g>
        <!-- 渐变 -->
        <!-- 滤镜 -->
      </defs>
    
      <!-- 引入复用元素 -->
      <use href="#rectangle"></use>
      <!-- 相对于复用元素的位置 -->
      <use href="#rectangle" x="100" y="100"></use>
      <use href="#logo"></use>
      <use href="#logo" x="0" y="60"></use>
    </svg>
    
    image.png
  • <symbol>元素和<defs>元素类似,也是用于定义可复用元素,然后通过<use>元素来引用显示。

    • <symbol>元素中定义的图形元素默认也是不会显示在界面上。

    • <symbol>元素常见的应用场景是用来定义各种小图标,比如:icon、logo、徽章等

  • <symbol>元素的属性

    • viewBox:定义当前 <symbol> 的视图框。

    • x / y :symbol元素的 x / y坐标。 ;默认值:0

    • width / height:symbol元素的宽度。 默认值:0

  • <symbol><defs>的区别

    • <defs>元素没有专有属性,而<symbol>元素提供了更多的属性

      • 比如: viewBox、 preserveAspectRatio 、x、y、width、height等。
    • <symbol>元素有自己用户坐标系,可以用于制作SVG精灵图。

    • <symbol>元素定义的图形增加了结构和语义性,提高文档的可访问性。

    <!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>
        body {
          margin: 0;
          padding: 0;
        }
    
        body {
          background-image: url(../images/grid.png);
        }
        svg {
          background-color: rgba(255, 0, 0, 0.1);
        }
      </style>
    </head>
    <body>
      <svg
        width="300"
        height="300"
        xmlns="http://www.w3.org/2000/svg"  
      >
        <!-- 制作icon -->
        <symbol id="prev" viewBox="0 0 100 100">
          <path d="M 80 0, L 20 50, L 80 100 Z"></path>
        </symbol>
    
        <symbol id="next" viewBox="0 0 100 100">
          <polygon points="20 0, 80 50, 20 100"></polygon>
        </symbol>
    
        <!-- 复用 -->
        <use href="#prev" width="100" height="100"></use>
        <!-- <use href="#next" width="100" height="100"></use> -->
      </svg>
    
      <!-- 外部复用 -->
      <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" >
        <!-- 直接在use上指定icon的 width和 height -->
        <use href="#prev" width="50" height="50"></use>
      </svg>
    
      <!-- 缩小 -->
      <svg width="30" height="30" xmlns="http://www.w3.org/2000/svg" >
        <!-- 直接在use上指定icon的 width和 height -->
        <use href="#prev"></use>
      </svg>
    
      <!-- 放大 -->
      <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" >
        <!-- 直接在use上指定icon的 width和 height -->
        <use href="#prev"></use>
      </svg>
    </body>
    </html>
    
    image.png
  • 制作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>

  <!-- 这就是一张SVG精灵图: App.vue 的template中 -->
  <svg version="1.1"  xmlns="http://www.w3.org/2000/svg" style="display:none;">
    <symbol id="music" viewBox="0 0 1024 1024">
        <path fill="#d81e06" d="M512 1024a512 512 0 1 1 512-512 512 512 0 0 1-512 512zm0-992a480 480 0 1 0 480 480A480 480 0 0 0 512 32zm128 640a80 80 0 1 1 48-143.634V416l-224 64v192h-1.61A80.549 80.549 0 1 1 432 592.366V384a32 32 0 0 1 32-32l224-64a32 32 0 0 1 32 32v288h-1.61A80.018 80.018 0 0 1 640 672zm-256-64a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm304-288l-224 64v64l224-64v-64zm-48 224a48 48 0 1 0 48 48 48 48 0 0 0-48-48z"/>
    </symbol>
    <symbol id="music_1" viewBox="0 0 1024 1024">
        <path fill="#d81e06" d="M512 56.89c251.351 0 455.11 203.759 455.11 455.11S763.352 967.11 512 967.11 56.89 763.352 56.89 512 260.648 56.89 512 56.89zm30.037 170.665h-3.185c-13.767 0-24.576 10.468-26.226 23.666-.057.683-.285 1.195-.341 1.878-.058.455-.285.853-.285 1.308v341.618c-14.962-7.964-31.687-12.914-49.778-12.914h-71.111c-58.88 0-106.666 47.787-106.666 106.667S332.23 796.445 391.11 796.445h71.111c58.88 0 106.667-47.787 106.667-106.667 0-2.447-.569-4.722-.74-7.111h.74V305.265l76.345 44.089a28.327 28.327 0 0 0 14.165 3.811c9.842 0 19.4-5.12 24.633-14.222 7.907-13.597 3.243-31.005-10.354-38.912l-116.451-67.186c-4.38-3.072-9.387-5.29-15.19-5.29zM462.223 640c27.42 0 49.777 22.357 49.777 49.778s-22.357 49.777-49.778 49.777h-71.111c-27.42 0-49.777-22.357-49.777-49.776 0-27.422 22.357-49.779 49.777-49.779h71.111z"/>
    </symbol>
    <symbol id="shouye" viewBox="0 0 1024 1024">
        <path fill="#d81e06" d="M981.638 396.91c-.5-.64-1.057-1.196-1.613-1.78L638.747 62.002C605.173 22.225 560.25.362 512.1.362h-.14c-48.26.027-93.267 22.002-126.842 61.946L43.73 394.824a33.308 33.308 0 0 0-1.67 1.78C-5.504 453.822 2.674 495.046 11.77 514.545c9.123 19.5 35.549 52.211 109.93 52.211h38.47v433.962c0 12.85 10.375 23.254 23.198 23.254h654.684c12.823 0 23.198-10.403 23.198-23.254v-430.15c0-12.824-10.375-23.227-23.198-23.227-12.824 0-23.2 10.403-23.2 23.226v406.924H679.249c.139-1.112.64-2.086.64-3.226V756.88c0-90.069-53.547-152.961-130.236-152.961h-75.744c-71.794 0-130.18 58.47-130.18 130.319v240.027c0 1.14.473 2.114.64 3.226H206.566V543.53c0-12.851-10.376-23.255-23.199-23.255H121.7c-35.049 0-60.445-9.513-67.9-25.452-7.343-15.744 1.307-40.945 23.171-67.565l341.333-332.46c.584-.584 1.14-1.168 1.641-1.808 24.73-29.736 57.413-46.147 92.072-46.175h.084c34.52 0 67.148 16.3 91.821 45.924.5.585 1.057 1.197 1.614 1.753l341.194 333.072c21.891 26.62 30.598 51.766 23.282 67.399-7.427 15.855-32.768 25.312-67.844 25.312-12.823 0-23.199 10.404-23.199 23.255 0 12.823 10.376 23.226 23.2 23.226 74.408 0 100.75-32.628 109.873-52.072 9.068-19.443 17.219-60.584-30.403-117.774zM390.125 974.265V734.238c0-46.23 37.58-83.838 83.783-83.838h75.744c50.152 0 83.838 42.781 83.838 106.48v217.385c0 1.14.5 2.114.667 3.226h-244.7c.168-1.112.668-2.086.668-3.226z"/>
    </symbol>
  </svg>

  <!-- Vue 某个子组件 -->
  <svg width="50" height="50">
    <use href="#music"></use>
  </svg>
  <svg width="30" height="30">
    <use href="#music"></use>
  </svg>

  <svg width="30" height="30">
    <use href="#music_1"></use>
  </svg>

  <svg width="100" height="100">
    <use href="#shouye"></use>
  </svg>

  <svg width="400" height="400">
    <use href="#shouye"></use>
  </svg>

</body>
</html>
image.png

七、填充和描边

  • 要给SVG中的元素上色,一般有两种方案可以实现:

    • 第一种:直接使用元素的属性,比如:填充(fill)属性、描边(stroke)属性等

      • 在SVG中,绝大多数元素的上色都可通过 fill和stroke 两个属性来搞定。

        • fill属性:设置对象填充颜色。支持:颜色名、十六进制值、rgb、 rgba 。

        • stroke属性:设置绘制对象的边框颜色。支持:颜色名、十六进制值、rgb、 rgba 。

    • 第二种:直接编写CSS样式,因为SVG也是HTML中的元素,也支持用CSS的方式来编写样式。

7.1 填充(fill)

  • fill 填充属性,专门用来给SVG中的元素填充颜色

    • fill =“color”。支持:颜色名、十六进制值、rgb、 rgba 、 currentColor (继承自身或父亲字体color)
  • 控制填充色的不透明

    • fill-opacity = ”number ”, 该属性专门用来控制填充色的不透明,值为 0 到 1。
    <!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>
        body {
          margin: 0;
          padding: 0;
        }
    
        body {
          background-image: url(../images/grid.png);
        }
        svg {
          background-color: rgba(255, 0, 0, 0.1);
          color: green;
        }
      </style>
    
    </head>
    <body>
    
      <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" >
        <defs>
          <!-- <style>
            rect{
              color: red;
            }
          </style> -->
        </defs>
    
        <!-- 基本的使用 -->
        <!-- <rect x="10" y="10" width="100" height="100" 
         fill="red"
         fill-opacity="0.4"
        ></rect> -->
    
        <rect x="10" y="10" width="100" height="100" 
          fill="currentColor"
        ></rect>
      </svg>
    
    </body>
    </html>
    
    image.png

7.2 描边(stroke)

  • stroke = “color”: 指定元素边框填充颜色。

  • stroke-opacity = “number”:控制元素边框填充颜色的透明度。

  • stroke-width = “number”:指定边框的宽度。注意,边框是以路径为中心线绘制的。

  • stroke-linecap =“butt | square | round”:控制边框端点的样式。

    image.png
  • stroke-linejoin = “miter | round | bevel”:控制两条线段连接处样式

    image.png
  • stroke-dasharray =“number [, number , ….]”: 将虚线类型应用在边框上。

    • 该值必须是用逗号分割的数字组成的数列,空格会被忽略。比如 3,5 :

      • 第一个表示填色区域长度为 3
      • 第二个表示非填色区域长度为 5
  • stroke-dashoffset:指定在dasharray模式下路径的偏移量(将线条往左移动)

    • 值为number类型,除了可以正值,也可以取负值。
    <!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>
        body {
          margin: 0;
          padding: 0;
        }
        body {
          background-image: url(../images/grid.png);
        }
        svg {
          background-color: rgba(255, 0, 0, 0.1);
        }
      </style>
    
    </head>
    <body>
    
      <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" >
    
        <!-- 
          stroke , 而不是 fill
         -->
        <line x1="100" y1="100"  x2="200" y2="100" 
          stroke="red" 
          stroke-width="5"
          stroke-linecap="round"
        >
        </line>
    
        <polyline points="20 0, 80 50, 20 100" 
          stroke="red" 
          stroke-width="5"
          stroke-linecap="round"
          stroke-linejoin="round"
          fill="transparent"
        >
        </polyline>
    
      </svg>
    
    </body>
    </html>
    
    image.png

八、用CSS编写的方式和优先级别

8.1 编写方式

  • 直接编写CSS样式实现填充和描边

    • 除了定义元素的属性外,可以通过CSS来实现填充和描边(CSS样式可写在defs中,也可写在HTML头部或外部等)。

    • 语法 和 HTML 里使用 CSS 一样,需要注意的是:要把 background-color、border 改成 fill 和 stroke

    • 不是所有的属性都能用 CSS 来设置,上色和填充的部分是可以用 CSS 来设置。

      • fill,stroke,stroke-dasharray 等可以用CSS设置
      • 路径的命令则不能用 CSS 设置
  • 哪些属性可以使用CSS设置,哪些不能呢?

  • CSS给SVG中的元素填充、描边和上色,支持如下4种编写方式:

    • 方式一:内联(行内) CSS 样式,写在元素的style属性上
    • 方式二:内嵌(内部) CSS 样式,写在 中的 标签中
    • 方式三:内嵌(内部) CSS 样式,写在中的标签中
    • 方式四:外部 CSS 样式文件,写在 .css 文件中

8.2 优先级

  • 内联的style > defs中的style > 外部 / head内部 > 属性 fill