数据可视化-SVG

48 阅读11分钟

一、邂逅SVG

1. 什么是SVG

  • SVG,可缩放矢量图形。(矢量:既有大小又有方向的量。在物理学中称作矢量;在数学中称作向量。)
  • SVG是一种基于XML格式的矢量图,主要用于定义二维图形,支持交互和动画。
  • SVG图像可在不损失质量的情况下按比例缩放,并支持压缩。
  • 基于XML的SVG可轻松的用文本编辑器或矢量图形编辑器创建和编辑,可以直接在浏览器显示。

2. SVG应用场景

  • 非常适合显示矢量徽标(logo)、图标(Icon)和其他几何设计;
  • 适合应用在需适配多种尺寸的屏幕上显示,因为SVG的扩展性更好;
  • 简单的动画;
  • 适合制作各种图表,以及大屏可视化页面开发。

3. SVG优缺点

  • 优点
    • 扩展好:矢量图像在浏览器中放大缩小不会失真,可被许多设备和浏览器使用;而光栅图像(PNG、JPG)放大缩小会失真。
      • 矢量图像是基于矢量的点、线、形状和数学公式来构建的图形,该图形是没有像素的,放大缩小是不会失真的。
      • 光栅图像是由像素点构成的图像——微小的彩色方块,大量像素点可以构成高清图像。图像像素越多,质量越高。
    • 灵活:SVG图像可以直接使用JS和CSS进行操作,使用时非常方便和灵活,因为是SVG也是可集成到DOM中的。
    • 可以动画:SVG图像可以使用JS、CSS和SMIL进行动画处理。
    • 轻量级:与其他格式相比,SVG图像的尺寸非常小。
    • 可打印:SVG图像可以以任何分辨率打印,而不会损失图像质量。
    • 利于SEO:SVG图像被搜索引擎索引。因此,SVG图像非常适合SEO目的。
    • 可压缩:与其他图像格式一样,SVG文件支持压缩。
    • 易于编辑:只需一个文本编辑器就可以创建SVG图像。
  • 缺点
    • 不适用于高清图片制作;
    • SVG图像变得复杂时,加载会比较慢;
    • 不完全扩平台。

4. SVG和Canvas的区别

  • 可扩展性
    • SVG是基于矢量的点、线、形状和数学公式来构建的图形,该图形是没有像素的,放大缩小不会失真。
    • Canvas是由一个个像素点构成的图形,放大会使图形变得颗粒化和像素化(模糊)。
    • SVG可以在任何分辨率下以高质量的打印;Canvas不适合在任意分辨率下打印。
  • 渲染能力
    • 当SVG很复杂时,它的渲染就会变得很慢,因为在很大程度上去使用DOM时,渲染会变得很慢。
    • Canvas提供了高性能的渲染和更快的图形处理能力。
    • 当图像中具有大量元素时,SVG文件的大小会增长得更快,而Canvas并不会增加太多。
  • 灵活度
    • SVG可以通过JavaScript和CSS进行修改,用SVG来创建动画和制作特效非常方便。
    • Canvas只能通过JavaScript进行修改,创建动画得一帧帧重绘。
  • 使用场景
    • Canvas主要用于游戏开发、绘制图形、复杂照片的合成,以及对图片进行像素级别的操作。
    • SVG非常适合显示矢量徽标(logo)、图标(Icon)和其他几何设计。

5. 初体验SVG

  • 绘制SVG矢量图的方式
    • 在单独的svg文件中绘制,svg文件可直接在浏览器预览或嵌入到HTML中使用;
    • 直接在HTmL文件中使用svg元素来绘制;
      • width/height —— svg画布的宽和高,默认值分别为300和150;
      • xmlns —— 给svg元素绑定一个命名空间(www.w3.org/2000/svg)
    • 直接使用JavaScript代码来生成svg矢量图;
      • createElementNs(ns, elname)
      • setAttributeNs(ns, attrname, value)
      • getAttributeNs(ns, attrname)
      • hasAttributeNs(ns, attrname)
      • removeAttributeNs(ns, attrname)
    • 使用AI矢量绘图工具来绘制矢量图,并导出为svg文件。
  • XML和DTD声明
    • SML声明格式:<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
      • version —— 指定版本
      • encoding —— 指定XML文档的编码
      • standalone —— 指定XML文档是否依赖于外部标记声明
    • DTD声明:<!DOCTYPE svg PUBLIC "-//W3C/DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
  • SVG使用方式
    • img元素
    • CSS背景
    • 直接在HTML文件作为HTML的DOM元素引用
    • object元素
    • iframe元素
    • embed元素

6. 认识SVG网络和坐标系统

  • 坐标系是以左上角(0, 0)为坐标原点,坐标以像素为单位,x轴正方向是向右,y轴正方向是向下。

7. 视口 - viewport

  • 什么是视口
    • 视口是SVG可见的区域(也可以说是SVG画布的大小)。可以将视口视为可看到特定场景的窗口。
    • 可以使用svg元素的width和height属性指定视口的大小。
    • 一旦设置了最外层SVG元素的宽度和高度,浏览器就会建立初始视口坐标系和初始用户坐标系。
  • 视口坐标系
    • 视口坐标系是在视口上建立的坐标系,原点在视口左上角的点(0, 0),x轴正向向右,y轴正向向下。
  • 用户坐标系
    • 用户坐标系是建立在SVG视口上的坐标系。该坐标系最初与视口坐标系相同——它的原点位于视口的左上角。
    • 使用viewBox属性,可以修改初始用户坐标系,使其不再与视口坐标系相同。 SVG是矢量图,支持任意缩放。在用户坐标系统绘制的图形,最终会参照视口坐标系来进行等比例缩放。

7. 视图框 - viewBox

  • viewport是SVG画布的大小,而viewBox是用来定义用户坐标系统的位置和尺寸。
  • viewBox = "x y width height"
    • 如果用户坐标系与视口坐标系具有相同的宽高比,它将viewBox区域拉伸以填充视口区域。
    • 如果用户坐标系和视口坐标系没有相同的宽高比,可用preserveAspectRatio属性来指定整个用户坐标系统是否在视口内可见。

二、绘制基本形状

1. 绘制矩形(rect)

  • rect元素的基本属性
    • x:矩形左上角的x轴位置
    • y:矩形左上角的y轴位置
    • width:矩形的宽度
    • height:矩形的高度
    • rx:圆角的x轴方位的半径
    • ry:圆角的y轴方位的半径
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <rect x="10" y="10" width="100" height="50"></rect>
      <rect x="100" y="100" width="100" height="50" rx="20" ry="10"></rect>
    </svg>
    

2. 绘制圆形(circle)

  • circle元素的基本属性
    • r:圆的半径
    • cx:圆心的x轴位置
    • cy:圆心的y轴位置
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <circle cx="100" cy="100" r="50"></circle>
    </svg>
    

3. 绘制椭圆(ellipse)

  • ellipse元素的基本属性
    • rx:椭圆的x轴半径
    • ry:椭圆的y轴半径
    • cx:椭圆中心的x轴位置
    • cy:椭圆中心的y轴位置
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <ellipse cx="100" cy="100" rx="25" ry="50" fill="green"></ellipse>
    </svg>
    

4. 绘制线条(line)

  • line元素的基本属性
    • x1:起点的x轴位置
    • y1:起点的y轴位置
    • x2:终点的x轴位置
    • y2:终点的y轴位置
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <line x1="100" y1="100" x2="200" y2="100" stroke="red" stroke-width="5"></line>
    </svg>
    

5. 绘制折线(polyline)

  • polyline元素的基本属性
    • points:点集数列
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
    <!-- 1. 第一种写法(推荐) -->
    <!-- <polyline points="20 0, 80 50, 20 100"></polyline> -->
    <polyline points="20 0, 80 50, 20 100" fill="transparent" stroke="red"></polyline>
    
    <!-- 2. 第二种写法 -->
    <!-- <polyline points="20 0 80 50 20 100"></polyline> -->
    
    <!-- 3. 第三种写法 -->
    <!-- <polyline points="20, 0, 80, 50, 20, 100"></polyline> -->
    </svg>
    

6. 绘制多边形(polygon)

  • polyline元素的基本属性
    • points:点集数列
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
    <polygon points="20 0, 80 50, 20 100" fill="transparent" stroke="red"></polygon>
    </svg>
    

7. 绘制路径(path)

  • path元素的基本属性
    • d:一个点集数列,必须以M命令开头
  • d属性支持的命令
    • M/m: Move To
    • L/l: Line To
    • Z/z: Close Path
    • H/h: horizontal
    • V/v: vertical
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <path d="M 20 0,L 80 50,l 20 100 Z" fill="transparent" stroke="red"></path>
    </svg>
    

三、绘制文本和图片

1. 绘制文本(text)

  • text元素的基本属性
    • x和y属性决定了文本在用户坐标系中显示的位置
    • text-anchor文本流方向属性,可以有start、middle、end和inherit值,默认值start
    • dominant-baseline基线对齐属性,有auto、middle或hanging值,默认值auto
  • tspan元素
    • 用来标记大块文本的子部分,它必须是一个text元素或别的tspan元素的子元素
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <text x="100" y="100" text-anchor="middle" dominant-baseline="middle" font-size="50" fill="red">Ay</text>
    </svg>
    

2. 绘制图片(image)

  • image元素的基本属性
    • x, y
    • width,height
    • href
  • 基本使用
    <!-- svg 2.0版本的语法 -->
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <image 
        x="10"
        y="10"
        href="xxxxxx"
        width="100"
        height="100"
      >
      </image>
    </svg>
    <!-- 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="10"
        y="10"
        xlink:href="xxxxxx"
        width="100"
        height="100"
      >
      </image>
    </svg>
    

四、SVG图形对象组合和引用

1. 元素的组合(g)

  • 什么是元素的组合
    • g元素是用来组合元素的容器。
    • 添加到g元素上的变换会应用到其所有的子元素上。
    • 添加到g元素的属性大部分会被所有的子元素继承。
    • g元素也可以用来定义复杂的对象,之后通过use元素来引用他们。
  • g元素的属性(该元素只包括全局属性)
    • 核心属性:id
    • 样式属性:class、style
    • CSS属性:cursor、display、fill、stroke……
    • 事件属性:onchange、onclick、ondrag……
    • 动画属性:transform
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <g fill="transparent" stroke="red">
        <circle cx="50" cy="50" r="25"></circle>
        <circle cx="80" cy="50" r="25"></circle>
        <circle cx="110" cy="50" r="25"></circle>
        <circle cx="140" cy="50" r="25"></circle>
      </g>
    </svg>
    

2. 图形元素的复用(defs)

  • defs元素,定义可复用元素
    • SVG可以把可复用的元素定义在defs元素里面,然后通过use元素来引用和显示
    • defs元素定义的图形元素不会直接显示
    • defs元素没有专有属性,使用时也不需要添加任何属性

3. 引用元素(use)

  • use元素从SVG文档中获取节点,并将获取到的节点复制到指定的地方。
  • use元素的属性
    • href
    • x/y
    • width/height
  • 基本使用
     <svg style="display: none" width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <!-- 样式 -->
        <style>
          rect {
            fill: green;
          }
        </style>
        <!-- 定义了一个矩形 -->
        <rect id="rectangle" x="0" y="0" width="100" height="50" fill="red"></rect>
      </defs>
    
      <!-- 图形的复用 -->
      <use x="100" y="100" href="#rectangle"></use>
    </svg>
    
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
        <!-- 图形的复用 -->
      <use href="#rectangle"></use>
    </svg>
    

4. 图形元素复用(symbol)

  • symbol和defs元素类似,也是用于定义可复用元素,然后通过use元素来引用显示。
  • symbol元素的属性
    • viewBox:定义当前symbol的视图框
    • x/y
    • width/height
  • symbol和defs的区别
    • defs元素没有专有属性,而symbol元素提供了更多的属性。
    • symbol元素有自己的用户坐标系,可以用于制作SVG精灵图。
    • symbol元素定义的图形增加了结构和语义性,提高文档的可访问性。
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
    <!-- ICON previous -->
    <symbol id="previous" viewBox="0 0 100 100">
      <path d="M 80 0,L 20 50,L 80 100 Z"></path>
    </symbol>
    
    <!-- 复用 -->
    <!-- <use href="#previous" width="100" hight="100"></use> -->
    </svg>
    

五、样式和属性

1. 填充和描边

  • SVG元素上色的方案
    • 直接使用元素的属性
    • 直接编写CSS样式
  • 填充属性(fill)
    • fill = "color"
    • fill-opacity = "number"
  • 描边属性(stroke)
    • stroke = "color"
    • stroke-opacity = "number"
    • stroke-width = "number"
    • stroke-linecap = "butt|square|round"
    • stroke-linejoin = "miter|round|bevel"
    • stroke-dasharray = "number [, number, ……]"
    • stroke-dashoffset = "number"
  • CSS样式
    • 内联(行内)CSS样式,写在元素的style属性上
    • 内嵌(内部)CSS样式,写在defs中的style标签中
    • 内嵌(内部)CSS样式,写在head的style标签中
    • 外部CSS样式,写在.css文件中

2. 渐变

  • 线性渐变的使用步骤
    • 在SVG文件的defs元素内部,创建一个linearGradient节点,并添加id属性;
    • 在linearGradient内编写几个stop节点;
      • 给stop节点指定位置offset属性和颜色stop-color属性,用来指定渐变在特定的位置上应用什么颜色;
      • 也可以通过stop-opacity来设置某个位置的半透明度。
    • 在一个元素的fill属性或stroke属性中通过ID来引用linearGradient节点。url(#ID)。
    • 控制渐变方向。也可以通过gradientTransform属性设置渐变形变。
  • 基本使用
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <!-- 定义可以复用的元素:样式、渐变、图形、滤镜…… -->
      <defs>
        <!-- 默认的渐变色 -->
        <linearGradient id="gradient1">
          <stop offset="0%" stop-color="red"></stop>
          <stop offset="50%" stop-color="green"></stop>
          <stop offset="100%" stop-color="blue"></stop>
        </linearGradient>
        <!-- 这个是制定渐变的方向 -->
        <linearGradient id="gradient2" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="red"></stop>
          <stop offset="50%" stop-color="green"></stop>
          <stop offset="100%" stop-color="blue"></stop>
        </linearGradient>
        <!-- 通过形变渐变色 -->
        <linearGradient id="gradient3" gradientTransform="rotate(10)">
          <stop offset="0%" stop-color="red"></stop>
          <stop offset="50%" stop-color="green"></stop>
          <stop offset="100%" stop-color="blue"></stop>
        </linearGradient>
      </defs>
      <rect x="10" y="10" width="100" height="50" fill="url(#gradient1)"></rect>
      <rect x="10" y="70" width="100" height="50" fill="url(#gradient2)"></rect>
      <rect x="10" y="130" width="100" height="50" fill="url(#gradient3)"></rect>
    </svg>
    

3. 毛玻璃效果

  • backdrop-filter
    • 给指定元素后面区域增加模糊效果
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        body {
          margin: 0;
          padding: 0;
        }
        .box {
          position: relative;
          width: 200px;
          height: 200px;
        }
        .bg-cover {
          position: absolute;
          left: 0;
          top: 0;
          width: 100%;
          height: 100%;
    
          /* 做毛玻璃效果 高斯模糊 */
          background-color: transparent;
          backdrop-filter: blur(5px);
        }
      </style>
    </head>
    <body>
      <div class="box">
        <img src="xxxxxx" alt="">
        <div class="bg-cover"></div>
      </div>
    </body>
    </html>
    
  • filter
    • 应用于指定元素
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        body {
          margin: 0;
          padding: 0;
        }
        .box {
          position: relative;
          width: 200px;
          height: 200px;
          overflow: hidden;
        }
        img {
          /* 毛玻璃效果 */
          filter: blur(5px);
        }
      </style>
    </head>
    <body>
      <div class="box">
        <img src="xxxxxx" alt="">
      </div>
    </body>
    </html>
    
  • SVG毛玻璃效果
    • filter:元素作为滤镜操作的容器,该元素定义的滤镜效果需要在SVG元素上的filter属性引用。
    • feGaussianBlur:该滤镜专门对输入图像进行高斯模糊。
    • feOffset:该滤镜可以对输入图像指定它的偏移量。
    <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
    <defs>
      <!-- 高斯模糊的效果 -->
      <filter id="blurFilter">
        <feGaussianBlur stdDeviation="5"></feGaussianBlur>
      </filter>
    </defs>
    <image href="xxxxxx" filter="url(#blurFilter)"></image>
    </svg>
    

六、SVG形变

1. 平移(translate)

  • translate(x, y)

2. 旋转(rotate)

  • rotate(deg, cx, cy)

3. 缩放(scale)

  • scale(x, y)

7、SVG动画

1. 路径描边

  • stroke-dasharray
  • stroke-dashoffset
  • CSS3 animation

2. SMIL动画

  • 认识SMIL动画
    • SMIL是W3C推荐的可扩展标记语言,用于描述多媒体演示。
    • SMIL标记是用XML编写的,与HTML有相似之处。
    • SMIL允许开发多媒体项目,例如:文本、图像、视频、音频等。
    • SMIL 定义了时间、布局、动画、视觉转换和媒体嵌入等标记。
    • SVG动画元素是基于SMIL实现。
  • SVG中SMIL动画的基本使用
    • set:可以在指定的时间内设置属性的值。
      • attributeName:指示将在动画期间更改的目标元素的属性的名称。
      • to:定义在特定时间设置目标属性的值。
      • begin:定义何时开始动画或何时丢弃元素。
      <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <rect x="10" y="10" width="100" height="50" fill="red">
        <set
          attributeName="x"
          to="200"
          begin="1s"
        ></set>
      </rect>
      </svg>
      
    • animate
      • attributeName
      • values/from-to
      • begin
      • dur:动画的持续时间,该值必须,并要求大于0.
      • fill:定义动画的最终状态。freeze(保持最后一个动画帧的状态)|remove(保持第一个动画帧的状态)。
      • repeatCount:指示动画将发生的次数。number|indefinite。
      <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <rect x="10" y="10" width="100" height="50" fill="red">
        <animate
          attributeName="x"
          form="0"
          to="200"
          dur="3s"
          begin="2s"
          fill="freeze"
        ></animate>
      </rect>
      </svg>
      <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
      <rect x="10" y="10" width="100" height="50" fill="green">
        <animate
          attributeName="fill"
          values="green; red"
          dur="3s"
          repeatCount="indefinite"
        ></animate>
      </rect>
      </svg>
      
    • animateTransform
      <svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
      <rect x="0" y="0" width="100" height="50"fill="red">
        <animateTransform
          attributeName="transform"
          type="translate"
          from="0, 0"
          to="100, 0"
          dur="2s"
          begin="1s"
          repeatCount="indefinite"
        ></animateTransform>
      </rect>
      </svg>
      <svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
      <rect x="0" y="0" width="100" height="50"fill="red">
        <animateTransform
          attributeName="transform"
          type="translate"
          values="0 0; 200 0"
          dur="2s"
          begin="1s"
          repeatCount="indefinite"
        ></animateTransform>
      </rect>
      </svg>
      
    • animationMotion
      • path:定义运动的路径,值和path元素的d属性一样,也可用href引用一个path。
      • rotate:动画元素自动跟随路径旋转,使元素动画方向和路径方向相同。
      <svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
      
      <!-- 图形 -->
      <path id="linePath" d="M 0 100, L 100 30, L 200 100, L 300 30" fill="transparent" stroke="red"></path>
      <rect id="rectangle" x="-10" y="-5" width="20" height="10" rx="4" ry="5" fill="red">
      </rect>
      
      <!-- 动画 -->
      <animateMotion
        href="#rectangle"
        dur="5s"
        rotate="auto"
        fill="freeze"
      >
        <mpath href="#linePath"></mpath>
      </animateMotion>
      
      </svg>
      

3. 第三方动画库

  • Snap给SVG中的标签添加动画