Skip to content

Latest commit

 

History

History
1197 lines (959 loc) · 41.5 KB

03_SVG.md

File metadata and controls

1197 lines (959 loc) · 41.5 KB

邂逅SVG

  • 维基百科
    • 可缩放矢量图形(矢量定义: 既有大小又有方向的量 在物理学中称作为矢量, 如一个带箭头的线段 长度表示大小 箭头表示方向 在数学中称之为向量 在计算机中 矢量图可无限放大而不变形)
    • SVG是一种基于XML格式的矢量图 主要用于定义二维图形 支持交互和动画
    • SVG规范是万维网联盟自1998年以来开发的标准
    • SVG图像可在不损失质量的情况下按比例缩放 并支持压缩
    • 基于XML的SVG可轻松的用文本编辑器或矢量图形编辑器创建和编辑 可以直接在浏览器中显示

SVG历史

image-20240605180850764

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缺点

  • 不适合高清图片
    • SVG格式非常适合用于徽标和图标等2D图形 但不适用于高清图片 不适合进行像素级操作
    • SVG的图像无法显示与标准图像格式一样多的细节 因为他们是使用点和路径而不是像素渲染的
  • SVG图像变得复杂的时候 加载会比较慢
  • 不完全扩平台
    • IE8以下不支持

SVG的应用场景

  • 矢量徽标 图标
  • 多种尺寸屏幕适配
  • 简单动画
    • SVG可以与JS交互来制作线条动画 过渡和其他复杂动画
    • CSS动画交互 SIML
  • 图表 大屏可视化开发

SVG和Canvas的区别

image-20240605182649602

初体验SVG

  • 如何绘制一个SVG矢量图
    • 在一个单独的svg文件
    • 在html中使用svg元素
    • 在JavaScript代码中生成svg
    • 使用AI
  • SVG初体验
    • 新建一个svg文件 在文件第一行编辑XML文件生命
    • 编写一个svg元素 给该严肃添加如下属性
      • version 1.0 1.1 2.0中不需要书写
      • baseProfile 2.0不需要写
      • width / height
      • xmlns: 给svg元素绑定一个命名空间
        • 意味着在这个svg和它的子元素都属于该命名空间下
    • 在svg元素上添加图形(<rect>)元素
    • 在浏览器中直接预览 或者嵌入到HTML中预览

XML和DTD声明

  • 由于SVG是一个XML文件格式 在编写XML文档的时候 通常推荐编写XML生命 因为在XML1.0中 XML声明式可选的 推荐写但不是强制性的 然而在XML1.1中 声明式强制性的 如何没有生命 则自动暗示该文档是XML.1.0文档 建议写

  • 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">
      

    image-20240605183846810

SVG为文档结构

  • SVG1.1文档结构: https://www.w3.org/TR/SVG11/struct.html

    • 第一行: 包含一个XML声明 由于SVG文件时一个XML格式的 它应该包含一个XML声明

    • 第二行: 定义文档声明(DTD) 这里依赖外部的SVG1.1文档类型 让解析器验证XML文件是否符合规范

      <!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN” "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
      
  • SVG2.0文档结构: https://www.w3.org/TR/SVG2/struct.html#Namespace

    • SVG2.0 version和baseProfile属性已删除 也不推荐写文档类型DTD 其中desc元素是用来描述该文件的

      image-20240605190334830

JS创建SVG

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

    • 比如: 创建svg元素或者rect元素的时候都需要添加命名空间(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:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Namespaces_Crash_Course

    image-20240605190722583

          const xmlns = "http://www.w3.org/2000/svg";
          const svgEl = document.createElementNS(xmlns, "svg");
          const rectEl = document.createElementNS(xmlns, "rect");
          svgEl.setAttributeNS(null, "version", "1.0");
          svgEl.setAttributeNS(null, "baseProfile", "full");
          svgEl.setAttributeNS(null, "width", "500");
          svgEl.setAttributeNS(null, "height", "500");
          rectEl.setAttributeNS(null, "x", "10");
          rectEl.setAttributeNS(null, "y", "10");
          rectEl.setAttributeNS(null, "width", "100");
          rectEl.setAttributeNS(null, "height", "100");
          rectEl.setAttributeNS(null, "fill", "red");
          svgEl.appendChild(rectEl);
          document.body.appendChild(svgEl);
    

HTML引入SVG

  • img元素
  • CSS背景
  • 在HTML中直接书写SVG代码
  • object元素
    • 支持交互式svg 能拿到object的引用 为SVG设置动画 更改样式等
  • iframe
    • 交互SVG 能拿到iframe引用 为SVG设置动画 更改其样式
  • embed
    • 支持交互SVG 能拿到embed的引用 设置动画 更该样式 对旧版浏览器有更好的支持

SVG Grid和坐标系

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

  • SVG Grid(坐标系)

    • svg元素默认宽300px 高150px svg元素默认被网格所覆盖

      image-20240605200943959

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

    • 基本上再SVG文档中的一个像素对应输出设备上的一个像素(除非缩放)

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

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

SVG的坐标系单位

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

  • 我们也可以手动指明坐标系的单位

    image-20240605201626493

视口 - viewport

  • 视口 viewport
    • 视口是SVG的课件区域 可以将视口看做可以看到特定场景的窗口
    • 可以使用svg元素的width和height属性指定视口的带下
    • 一旦设置了最外层SVG元素的宽度和高度 浏览器就会创建视口坐标系和初始用户坐标系
  • 视口坐标系
    • 视口坐标系是在视口上建立的坐标系 远点在视口左上角的点(0,0)
    • 初始视口坐标系中的一个单位等于视口中的一个像素 该坐标类似于HTML元素的坐标系
  • 用户坐标系(也被称之为当前坐标系正在使用的用户控件 后面绘图也是参照该坐标系)
    • 用户坐标系是建立在SVG视口上的坐标系 该坐标系最初于视口相同 它的原点位于视口的左上角
    • 使用viewBox属性 可以修改初始用户坐标系 使其不在与视口坐标系相同
  • 为什么要有两个坐标系?
    • 因为SVG是矢量图 支持任意缩放 在用户坐标系统绘制的图形 最终会参照视口坐标系来进行等比例缩放

视图框 - viewBox

  • 视图框 - viewBox
    • viewBox是SVG画布的大小 而viewBox是用来定义用户坐标系中的位置和尺寸(该区域通常会被缩放填充视口)
    • viewbox也可以理解为是用来指定用户用户坐标系大小 因为SVG图形都是绘制该区域中 用户坐标系可以比视口坐标系更小或更大 也可以在视口内完全或部分可见
    • 一旦创建了视口坐标系(svg使用width和height) 浏览器就会创建一个与其相同的默认用户坐标系
    • 我们可以使用viewBox属性指定用户坐标系的大小
      • 如果用户坐标系与视口坐标系具有相同的高宽比 它将viewBox区域拉伸以填充视口区域
      • 如果用户坐标系和视口坐标系没有相同的宽高比 可以用perserveAs[ectRatio属性来指定用户坐标系统是否在视口内可见
  • viewBox语法
    • viewBox = min-x min-y width height
    • min-x min-y 确定视图框的左上角坐标(不是修改用户坐标的原点 绘图还是从原来的0,0开始)
    • width height确定该视图框的宽度和高度
      • 宽度和高度不必与父svg元素上设置的宽度和高度相同
      • 负数无效 0为隐藏

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

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

    • 看viewBox属性上设置了视图框为视口大小的一半
    • 暂时不改变这个视图框左上角 将min-x min-y设置为零
    • 视图框的宽度和高度将是视口宽度和高度的一半

    image-20240605204604166

  • 那么 veiwbox='0 0 100 100'具体做什么的呢?

    • 指定画布可显示的区域 用户坐标系从(0,0)的左上点到(100,100)的点 默认单位是px
    • 然后将SVG图形绘制到该viewBox区域
    • viewBox区域等比例被放大 放大不会失真 以填充整个视口
    • 用户坐标系映射到视口坐标系 因为 在这种情况下 1个用户单位等于四个视口单位
    • 在SVG画布上绘制的任何内容豆浆相对于该用户坐标系进行绘制

视图框 - viewBox - 不同宽高比

  • 在400 * 4-00 的视口中 viewbox='0 0 200 100'具体做什么
    • 保留视图框viewBox的宽高比 但视图框viewBox不会拉伸以覆盖整个视口区域
    • 视图框viewBox在视口内垂直和水平居中
  • 相改变视口内视框位置怎么办
    • 给svg添加preserveAspectRatio属性 该属性允许强制同一缩放视图框viewBox
      • none 强制拉伸图形可以填充整个视口
      • xMinYMin 图形在视口的最小x和y轴上显示

绘制 - 矩形 rect

  • SVG的基本形状

    • 在SVG画布中 如果要想插入一个形状 可以在文档中创建一个对应的元素
    • 不同的元素对应着不同的形状 并且可以使用不同的属性来定义图形的大小和位置
    • SVG所支持的基本形状有: 矩形 原型 椭圆 线条 折线 多边形 路径
  • 绘制矩形

    • rect

      • x
      • y
      • width
      • height
      • rx 圆角
      • ry
          <svg width="400" height="400">
            <rect x="0" y="0" width="100" height="100" />
            <!-- 圆角矩形 -->
            <rect x="200" y="200" width="100" height="100" rx="20" ry="20" />
          </svg>
      

绘制 - 圆形 circle

  • circle
    • r 半径
    • cx 圆心x轴位置
    • cy 圆心y轴位置

image-20240605213820153

绘制 - 椭圆 ellipse

  • ellipse
    • rx x轴半径
    • ry y轴半径
    • cx 椭圆心位置
    • cy

image-20240605213942857

绘制 - 线条 line

  • line
    • x1 起点的x轴位置
    • y1 起点的y轴位置
    • x2 终点的x轴位置
    • y2 终点的y轴位置

image-20240605214042132

绘制 - 折线 polyline

  • polyline
    • points 点集数列 每个数字用空白 逗号 终止命令符或者换行符分隔开
    • 每个点 必须包含两个数字 一个x 一个y

image-20240605214202410

绘制 - 多边形 polygon

  • polygon
    • points

image-20240605214255777

绘制 - 路径 path

  • path
    • path元素可能是SVG中最常见的形状 你可以用path元素绘制矩形 圆形椭圆形折线 多边形 以及一些其他的东西 贝塞尔曲线 2次曲线等曲线
    • 默认会填充黑色 默认路径不会闭合
    • path元素有一个基本属性用来设置路径点位置
      • d 一个点集数列 以及其他关于如何绘制路径的信息 必须M命令开头

image-20240605214454076

SVG路径和命令

  • SVG路径path和命令
    • path元素是SVG基本形状中最强大的 你可以用来创建曲线 线条 弧形
    • path元素的形状必须通过属性d定义 属性d的值是一个命令加参数的序列
    • 每一个命令都用一个关键字来表示 比如 字母M表示的是MoveTo命令 当解析器读到这个命令时 它就知道你是打算移动到某个点 跟在命令自足后面的 是你需要移动到那个点的x轴和y轴坐标 比如移动到(10, 10)这个点的命令 应该写成M 10 10 这一段字符结束后 解析器就会读下一段命令 每一个命令都有两种表示方式 一种是大写字母 表示决定定位 小写字母 表示相对定位
    • 属性d采用的是用户坐标系统 不需要单位

image-20240605214851384

绘制 - 图片

  • 在SVG中绘制图片
    • 在image元素的href属性引入图片的URL
  • 注意事项
    • image元素没有设置xy的时候 他们自动设置为0
    • image元素没有设置height width 默认为图片的大小
    • width height 设置为0 将不会呈现这个图像
    • 需要再href属性引入外部图像 不是src属性

绘制 - 文字

  • text元素

    • x y 属性决定了文本在用户坐标系中显示的位置
    • text-anchor文本流方向属性 start moddle end 或inherit 默认start
    • dominant-baseline 基本对齐属性 auto middle hanging 默认auto

    image-20240605215932968

  • 字体属性

    • image-20240605215950522
  • 其他文本相关元素

    • tspan 元素用来标记大块文本的子部分 它必须是一个text元素或别的tspan的子元素
    • x和y属性决定了文本在视口坐标系中显示的位置
    • alignment-baseline基线对齐属性: auto baseline middle hanging top bottom 默认是auto

元素的组合 (g)

  • 元素的组合

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

    • 核心属性 id

    • 样式属性 class style

    • CSS属性

      image-20240605221658767

    • 事件属性

      • onchange onclick ondbclick ondrag...
    • 动画属性

      • transform
    • ....

      <g fill="none" 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>

图形元素的复用 defs

  • SVG是允许我们定义一些可复用的额元素的
    • 即把可复用的元素定义在defs元素里面 然后通过use来引用和显示
    • 这样可以增加SVG内容的易读性 复用性和利于无障碍开发
  • defs元素 定义可复用元素
    • 定义基本图形组合图形 渐变 滤镜 样式等等
    • 在defs元素汇总定义的图形元素是不是直接显示出来的
    • 可在视口任意地方用use来呈现子啊defs中定义的元素
    • defs元素没有专有属性 使用时通常也不需要添加任何的属性
  • defs定义元素的坐标参照那个?
    • 用户坐标系

引入元素 use

  • use元素从SVG文档中获取节点 并将获取到节点复制到指定的地方
    • use等同于深度克隆DOM节点 克隆到use元素所在的位置
    • 克隆节点是不可见的 当给use元素应用CSS样式的时候必须小心 因为克隆DOM不能保证东辉继承use元素上的CSS属性 但是CSS可继承的属性是会继承的
  • use元素的属性
    • href 需要复制元素/片段的URL和ID(支持跨SVG引用) 默认值无
    • x y 元素的xy坐标(相对复制元素的位置) 默认值0
    • width height 元素的宽和高(在引入svg或symbol元素才作用) 默认值0

图形元素复用 symbols

  • 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元素定义的图形正价结构和语义性 提高文档的可访问性

image-20240605224224658

填充和描边

  • 如果想要给SVG中的元素上色 一般有两种方案可以实现
    • 第一种 直接使用元素的属性 填充 描边属性等
    • 第二种 直接编写CSS样式 因为SVG也是HTML标签 也支持使用CSS的方式来编写样式
  • 直接使用元素的属性(填充和描边)
    • 在SVG中 绝大多数的元素的上色都可以通过fill和stroke两个属性搞定

填充 - fill

image-20240605225827033

描边 - stroke

image-20240605230631680

CSS样式

image-20240605231857714

线性渐变

  • SVG除了可以简单的填充和描边 还支持在填充和描边上应用渐变色 渐变有两种类型: 线性渐变和径向渐变
    • 编写渐变时候 必须给渐变内容指定一个id属性 use引用
    • 建议渐变内容定义在defs元素内 渐变通常是可复用的
  • 线性渐变 是沿着直线改变颜色
    • 在SVG中defs内部 创建一个linearGradient节点 并添加id属性
    • 在linearGradient内编写几个stop节点
      • 给stop节点指定位置offset属性和颜色stop-color属性 用来指定渐变在特定的位置上应用什么颜色
        • offset和stop-color这两个属性值 也可以通过CSS来指定
      • 也可以通过stop-opacity来设置某个位置的半透明度
    • 在一个元素的fill属性或者stroke属性中通过id来引用linearGradient节点
      • 比如: 属性fill属性设置为url(#id)即可
    • 控制渐变方向 通过(x1,y1)和(x2,y2)两个点控制

SVG毛玻璃效果

  • 在前端开发中 毛玻璃中有几种方案来实现
  • 方案一: 使用CSS的backdrop-filter或者filter属性
    • backdrop-filter: 可以给一个元素后面区域添加模糊效果 适用于元素背后的所有元素 为了看到效果 必须使元素或背景至少透明
    • filter 直接将模糊或颜色偏移等模糊效果 应用于特定的元素
  • 方案二: 使用SVG的filter和feGaussianBlur元素(建议少用)
    • filter元素作为滤镜操作的容器 该元素定义的滤镜效果 需要在SVG元素上的filter属性引用
      • x y width height定义了画布上应用过此过滤器的矩形区域 x y 默认值为-10%(相对自身) width height 默认值为120%
    • feGaussianBlur: 该滤镜专门对输入图像进行高斯模糊
      • stdDeviation熟悉指定模糊的程度

image-20240606185708436

形变 - transform

  • transform属性用来定义元素及其子元素的形变的列表
    • 此属性可以与任何一个SVG中的元素一起使用 如果使用了变形 会在该元素内部建立了一个新的坐标系统
    • 从SVG2开始 transform它是一个Persendtation Attribute 意味着可以用作CSS属性
    • 但是transform作为CSS属性和元素属性之间会存在一些差异
      • 比如作为元素属性的时候 支持2D变换 不需要单位 rotate可以孩子定旋转原点
  • transform属性支持的函数
    • translate(x,y)平移
    • rotate(z) / rotate(z, cx, cy)旋转
    • scale(x,y)缩放
    • skew(x,y)倾斜
    • matrix(a,b,c,d,e) 2*3的变形矩阵
  • 注意:
    • 形变会不会修改坐标系?
      • 会 形变元素内部会建立一个新的坐标系 后续的绘图或者形变都会参照新的坐标系

形变 - 平移

  • 平移: 把元素移动一段距离 使用transform属性的translate函数励平移元素
    • 与CSS的translate相似但有区别 这里只支持2D变换 不需要单位
  • translate(x,y)
    • 一个值: 设置x轴平移 第二个值默认为0
    • 两个值: x和y

形变 - 旋转

  • 旋转: 把元素旋转指定的角度 使用transform属性的rotate(deg, cx, cy)来旋转元素
    • 与CSC的rotate相似但有区别 区别是: 支持2D变换 不需单位 可指定旋转原点
  • rotate(deg, cx, cy)
    • 一个值 设置z轴上的旋转角度

形变 - 缩放

  • 缩放: 改变尺寸 使用transform的scale函数来缩放元素

    • 与CSS的sclae值类似但是有区别 这里只支持2D变换 不需要单位
  • scale(x,y)函数

    • 两个值的时候: 它需要两个数字 作为比例计算如何缩放 0.5表示缩放到50%
    • 一个值的时候: 第二个数字被忽略;了 它默认等于第一个值

    image-20240606194412669

  • 注意:

    • 缩放坐标轴会缩放吗
      • 会 缩放之后 坐标轴也会缩放

stroke描边动画

  • stroke是描边属性 专门给图形描边 如果想给描边添加动画 需要用到下面两个属性
    • stroke-dasharray="number[, number...]": 将虚线类型应用到描边上
      • 该值必须是用逗号分隔成数字组成的数列 空格会被忽略 比如3,5
        • 第一个表示填色区域的长度为3
        • 第二个表示非填色区域长度为5
    • stroke-dashoffset: 指定在dasharray模式下路径的偏移量
      • 值为number类型 除了可以正值 也可以取负值
  • 描边动画实现步骤
    • 先将描边设置为虚线
    • 接着将描边移动到不可见处
    • 通过动画让描边变位可见 这样就产生了动画效果了
<!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,
      ul {
        margin: 0;
        padding: 0;
      }

      body {
        background: url(./images/grid.png);
      }

      svg {
        background: rgba(255, 0, 0, 0.1);
      }

      #line1 {
        stroke-dasharray: 100px;
        stroke-dashoffset: 100px;

        animation: lineMove 3s linear forwards;
      }

      @keyframes lineMove {
        100% {
          stroke-dashoffset: 0px;
        }
      }
    </style>
  </head>
  <body>
    <svg width="300" height="300">
      <line
        id="line1"
        x1="100"
        y1="70"
        x2="200"
        y2="70"
        stroke="red"
        stroke-width="10"
      />
    </svg>
  </body>
</html>

什么是SMIL

  • SMI(同步多媒体集成语言) 是W3C推荐的可拓展标记语言 用于描述多媒体演示
    • SMIL标记是用XML编写的 与XML有相似之处
    • SMIL允许开发多媒体项目例如: 文本 图像 视频 音频等等
    • SMIL定义了事件 布局 动画 视觉转换和媒体嵌入等标记 比如 head body seq par excl等元素
  • SMIL的应用
    • 目前最常用的Web浏览器基本都支持SMIL语言
    • SVG动画元素是基于SMIL实现(SVG中使用SMIL实现的元素有 set animate animateMotion)
    • image-20240606214652355

SVG动画实现方式

  • SVG是一种基于XML的开放标准矢量图形格式 动画可以通过多种方式实现
    • JS脚本实现
    • 用CSS样式实现
    • 用SMIL实现

SMIL动画的优势

  • SVG用SMIL方式实现动画 SMIL允许你做下面的事情
    • 变动一个元素的数字属性(x y)
    • 变动变形属性(transition或rotation)
    • 变动颜色属性
    • 物体方向与运动路径方向同步等等
  • SMIL方式实现动画的优势
    • 只需要在页面放几个animate元素就可以实现强大的动画效果 无需任何的CSS和JS代码
    • SMIL支持声明式动画 声明式动画不需指定如何丛某事的细节 而是指定最终结果应该是什么 将实现细节留给客户端软件
    • 在JavaScript中 动画通常使用setTimeout或者setInterval等方法很粗昂见 这些方法需要手动管理东海的事件 而SMIL声明式动画可以让浏览器自动处理 比如: 动画轨迹直接与动画对象关联 物体和运动路径方向 管理动画事件等等
    • SMIL东海还有一个令人愉快的特点是 动画与对象本身是紧密集成的 对于代码的编写和阅读性都非常好

SMIL动画的元素

  • SVG中支持SMIL动画的元素
    • set animate animateColor animateMotion
    • image-20240606215647858

Set元素

  • set元素提供了一种简单的方法 可以在指定的时间内设置属性的值
    • set元素是最简单的SVG动画元素 它是经过特定时间间隔后 将属性设计为某个值(不是过渡动画效果) 因此 图像不是连续动画 而是改变一次属性值
    • 它支持所有的属性类型 包括那些无法合理插值的属性类型 例如 字符串和布尔值 而对于可以合理的插值的属性通常首选animate元素
  • set元素常用属性
    • attributeName: 指示将在动画期间更改的目标的CSS属性(property)或属性(attribute)的名称
    • to: 定义在特定时间设置目标属性的值 该值必须与目标属性要求相匹配 值类型<anything> 默认值: 无
    • begin: 定义何时开始动画或何时丢弃元素 默认是0s(begin支持多种类型的值)
<!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,
      ul {
        margin: 0;
        padding: 0;
      }

      body {
        background: url(./images/grid.png);
      }

      svg {
        background: rgba(255, 0, 0, 0.1);
      }
    </style>
  </head>
  <body>
    <svg width="300" height="300">
      <rect x="0" y="0" width="100" height="50">
        <set attributeName="x" to="200" begin="3s"></set>
      </rect>
    </svg>

    <svg width="300" height="300">
      <rect id="rectangle" x="0" y="0" width="100" height="50">
        <set attributeName="x" to="200" begin="rectangle.click"></set>
      </rect>
    </svg>
  </body>
</html>

Animate元素

  • animate元素给某个属性创建过渡动画效果 需将animate元素嵌套要应用动画的元素内
  • animate元素常用属性
    • attributeName: 指将在动画期间更改目标元素的property(CSS属性)或attribute的名称
    • 动画值属性
      • form: 在动画执行期间将被修改的属性的初始值 没有默认值
      • to: 在动画期间将被修改的属性的最终值 没有默认值
      • values: 该属性具有不同的含义 具体取决于使用它的上下文(没有默认值)
        • 它定义了在动画过渡中使用的一系列值 值需要用分号隔开 比如:values='2;3;4;5'
        • 当values属性定义时 from to属性会被忽略
    • 动画时间属性
      • begin 定义何时开始动画或何时丢弃元素 默认是0s
      • dur 动画的持续时间 该值必须 并要求大于0 单位可以用小时h 分钟m 秒s 毫秒ms
      • fill 定义动画的最终状态 freeze(保持最后一个动画帧的状态) | remove(保持第一个动画帧的状态)
      • repeatCount: 指示动画将发生的次数: number | indefinite 没有默认值
<!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,
      ul {
        margin: 0;
        padding: 0;
      }

      body {
        background: url(./images/grid.png);
      }

      svg {
        background: rgba(255, 0, 0, 0.1);
      }
    </style>
  </head>
  <body>
    <svg width="300" height="300">
      <rect x="0" y="0" width="100" height="50">
        <animate
          attributeName="x"
          form="0"
          to="200"
          dur="2s"
          begin="2s"
          fill="freeze"
          repeatCount="indefinite"
        ></animate>
      </rect>
    </svg>

    <svg width="300" height="300">
      <rect id="rectangle" x="0" y="0" width="100" height="50">
        <animate
          attributeName="x"
          values="0; 20; 80; 200"
          dur="2s"
          begin="rectangle.click"
          fill="freeze"
          repeatCount="indefinite"
        ></animate>
      </rect>
    </svg>

    <svg width="300" height="300">
      <rect x="0" y="0" width="100" height="50">
        <animate
          id="animation1"
          attributeName="x"
          values="0; 200"
          dur="2s"
          begin="1s"
          fill="freeze"
        ></animate>
        <animate
          attributeName="y"
          values="0; 200"
          dur="2s"
          begin="animation1.end"
          fill="freeze"
        ></animate>
      </rect>
    </svg>
  </body>
</html>

animateTransform元素

  • animateTransform元素

    • 指定目标元素的形变(Transform)属性 从而控制允许控制元素的平移 旋转 倾斜动画(类似于CSS的形变)
    • 在一个动画元素中 只能用一个animateTransform元素创建动画 当存在多个的时候 后面会覆盖前面的动画
  • animateTransform元素常用属性

    • attributeName: 指示将在动画期间更改的目标元素的CSS属性或属性的名称

    • type: 一个指定类型的属性 在不同的使用场景下 有不同的意思

      • 在animateTransform元素 只支持translate | rotate | scale | skewX | skewY

        image-20240607182632112

      • 在HTML中的style和script元素 它定义了元素内容的类型

    • 动画值属性: form to values

    • 动画时间属性: begin dur fill repeatCount

<!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,
      ul {
        margin: 0;
        padding: 0;
      }

      body {
        background: url(./images/grid.png);
      }

      svg {
        background: rgba(255, 0, 0, 0.1);
      }
    </style>
  </head>
  <body>
    <svg width="300" height="300">
      <rect x="0" y="0" width="100" height="50">
        <animateTransform
          attributeName="transform"
          type="translate"
          from="0 0"
          to=" 100 100"
          dur="2s"
          fill="freeze"
          repeatCount="indefinite"
        />
      </rect>
    </svg>

    <svg width="300" height="300">
      <rect x="0" y="0" width="100" height="50">
        <animateTransform
          attributeName="transform"
          type="rotate"
          from="0 50 25"
          to="360 50 25"
          dur="2s"
          fill="freeze"
          repeatCount="indefinite"
        />
      </rect>
    </svg>

    <svg width="300" height="300">
      <rect x="0" y="0" width="100" height="50">
        <animateTransform
          attributeName="transform"
          type="scale"
          from="1 1"
          to="2 2"
          dur="2s"
          fill="freeze"
          repeatCount="indefinite"
        />
      </rect>
    </svg>

    <svg width="300" height="300">
      <rect x="0" y="0" width="100" height="50">
        <animateTransform
          attributeName="transform"
          type="skewX"
          from="0"
          to="30"
          dur="2s"
          fill="freeze"
          repeatCount="indefinite"
        />
      </rect>
    </svg>

    <svg width="300" height="300">
      <rect x="0" y="0" width="100" height="50">
        <animateTransform
          attributeName="transform"
          type="skewY"
          from="0"
          to="30"
          dur="2s"
          fill="freeze"
          repeatCount="indefinite"
        />
      </rect>
    </svg>
  </body>
</html>

animateMotion元素

  • animateMotion 定义了一个元素如何沿着运动路径进行移动
    • 动画元素的坐标原点 会影响元素运动路径 建议从(0,0)开始
    • 要复用现有路径 可在animateMotion元素中使用mpath元素
  • animateMotion元素常用属性
    • path: 定义运动的路径 值和path元素的d属性一样 也可以用href引用一个path
    • rotate: 动画元素自动跟随者路径旋转 使元素动画方向和路径方向想通过 值类型: 数字 | auto | auto-reverse 默认值为0
    • 动画值属性: form to values
    • 动画时间属性 begin dur fill repeatCount
<!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,
      ul {
        margin: 0;
        padding: 0;
      }

      body {
        background: url(./images/grid.png);
      }

      svg {
        background: rgba(255, 0, 0, 0.1);
      }
    </style>
  </head>
  <body>
    <svg width="300" height="300">
      <path
        id="path1"
        d="M 0 100, 100 30, 200 100 300 30"
        fill="none"
        stroke="red"
        stroke-width=""
      />
      <rect x="-10" y="-5" width="20" height="10" fill="red" rx="4" ry="4">
        <animateMotion dur="2s" rotate="auto" repeatCount="indefinite">
          <mpath href="#path1" />
        </animateMotion>
      </rect>
    </svg>
  </body>
</html>

Snap.svg

  • 什么是Snap.svg
    • Snap.svg是一个专门用于处理SVG的JavaScript库(类似于JQuery)
    • Snap为Web开发人员提供了干净的 直观 功能强大的API 这些API专门用来操作SVG
    • SNap可用于创建动画 曹组哦现有的SVG内容 以及生成SVG内容
  • 为什么选择Snap.svg
    • image-20240607195040809

Snap.svg初体验

  • Snap.svg常用API
    • Snap: 工厂函数 创建或获取SVG
      • Snap(w,h) Snap(selector)
    • Paper: 纸张 | SVG画布
      • circle....
    • Element: 元素
      • animate attr selector...
      • mina: 通常用到的事件哈数
        • mina.linear mina.easeIn ...
    • 更多API: http://snapsvg.io/docs/
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script src="./libs/snap.svg-min.js"></script>

    <script>
      window.onload = (e) => {
        // 创建一个svg
        let svg = Snap(300, 300);
        console.log(svg === svg.paper);

        let c = svg.circle(100, 100, 50);

        c.attr({
          fill: "red",
        });

        // svg.node 是svg节点对象
        document.body.appendChild(svg.node);
      };
    </script>
  </body>
</html>
<!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,
      ul {
        margin: 0;
        padding: 0;
      }

      body {
        background: url(./images/grid.png);
      }

      svg {
        background: rgba(255, 0, 0, 0.1);
      }
    </style>
  </head>
  <body>
    <script src="./libs/snap.svg-min.js"></script>
    <svg id="svg" width="300" height="300">
      <rect id="rect" x="0" y="0" width="100" height="50"></rect>
    </svg>

    <script>
      window.onload = (e) => {
        const svg = Snap("#svg");
        const paper = svg.paper;

        let rect = paper.rect(100, 100, 100, 50);
        rect.attr({
          fill: "red",
        });

        let rectangle = svg.select("#rect");
        rectangle.attr({
          fill: "blue",
        });

        Snap.animate(
          [0, 0],
          [200, 200],
          function (val) {
            console.log("val", val);
            rectangle.attr({
              x: val[0],
              y: val[1],
            });
          },
          3000,
          mina.linear,
          function () {
            console.log("结束了");
          }
        );
      };
    </script>
  </body>
</html>

GSAP动画库

  • 什么是GSAP
    • 动画平台
    • GSAP是一个强大的JavaScript动画库 可让开发人员轻松的制作各种复杂的动画
  • GSAP动画库的特点
    • 与Snap.svg不一样 GSAP无论会死HTML元素 还是SVG 或者Vue React组件的动画 都可以满足你的需求
    • GSAP还提供了一些插件 可以用最少的代码创建令人震惊的动画 比如ScrollTrigger插件和MorphSVG插件
    • GSAP的核心是一个高速的属性操纵器 随着时间的推移 它可以极高的准确性更新值 它比JQuery块20倍
    • GSAP使用起来非常灵活 在你想要动画的地方基本都可以使用 并且是零依赖

GSAP初体验

  • GSAP初体验: 移动SVG中的一个矩形
    • 引入gasp.js动画库(CDN 本地 npm)
    • 调用gsap.to方法来执行一tween(补件间/过渡哦)动画
<!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,
      ul {
        margin: 0;
        padding: 0;
      }

      body {
        background: url(./images/grid.png);
      }

      svg {
        background: rgba(255, 0, 0, 0.1);
      }
    </style>
  </head>
  <body>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
    <svg width="300" height="300">
      <rect
        id="rectangle"
        x="0"
        y="0"
        width="100"
        height="100"
        onclick="clickRectangle()"
      />
    </svg>

    <script>
      function clickRectangle() {
        // gsap.to("#rectangle", {
        //   duration: 1,
        //   x: 200,
        //   y: 200,
        // });

        // gsap.to(["#rectangle"], {
        //   duration: 1,
        //   x: 200,
        //   y: 200,
        // });

        // gsap.from("#rectangle", {
        //   duration: 1,
        //   scale: 2,
        // });

        gsap.fromTo(
          "#rectangle",
          {
            x: 0,
            y: 0,
            scale: 1,
          },
          {
            duration: 1,
            x: 200,
            y: 200,
            scale: 2,
          }
        );
      }
      window.onload = (e) => {};
    </script>
  </body>
</html>

GSAP补间动画(Tween)

  • GSAP的Tween动画由四种类型

    • gsap.from(targets|selector|vars) 元素从from定义的状态过渡到当前的状态
      • targets | selector 需动画的元素对象 支持字符串的选择器
      • vars 需过渡的属性和GSAP拓展的duration ease transformOrigin repeat delay yoyo stagger onComplete
    • gasp.to 元素从当前状态过渡到to状态
    • gasp.fromTo 元素从from定义状态过渡到to定义的状态
    • gasp.set 立即设置属性(没有过渡效果)
  • 那些属性可以设置动画

    • GSAP几乎可以为任何属性制作动画

      • 包括CSS属性 元素属性 自定义对象属性
      • 设置CSS变量和复杂字符串
      • 最常见的动画属性 兴百年和opacity
    • GSAP还专门为CSS形变 相关属性提供了简写

      image-20240611184612633

GSAP时间线(TimeLine)

  • 什么是动画时间线(TimeLine)
    • 时间线 是用啦已创建易于调整 有弹性的动画序列
    • 当我们将补间添加到时间线时 在默认情况下 它们会按照添加到时间轴的顺序一个接一个的播放