canvas 与 svg 标签

628 阅读12分钟

canvas 和 svg

canvas 和 svg 的一些东西有相同的名字和作用, 比如 stroke 和 fill 区别在于

  • canvas 是做位图的, svg 是做矢量图的
  • canvas 用 js 来画, svg 在标签里面写 (当然也能用 js 写)

==canvas 和 svg 都非常多而且比较难, 以下内容了解即可, 工作中都是利用框架==

canvas

简介

什么是Canvas?
  • Canvas 是 H5 新增的一个标签, 我们可以通过 JS 在这个标签上绘制各种图案
  • Canvas 拥有多种绘制==路径==, ==矩形==, ==圆形==, ==字符==以及==图片==的方法
canvas 注意点
  1. canvas有默认的宽度和高度
    • 默认宽300px
    • 高150px
  2. canvas 的坐标的原点在==左上角==, 向右是 x 轴正方向, 向下是 y 轴正方向
  3. ==不能==通过CSS设置画布的宽高
    • 通过CSS设置画布宽高会在默认宽高的基础上拉伸
    • 如果需要设置 canvas 宽高请通过元素行内属性 width 和 height 设置
  4. 线条默认宽度和颜色
    • 通过 canvas 绘制的线条默认宽度是 1px, 颜色是纯黑色
    • 但是由于默认情况下canvas会将==线条的中心点和像素的底部==对齐 (数值后面加 .5 就能解决问题)
    • 所以会导致显示效果是 2px 和非纯黑色问题 (实际的 1px 由于显示方式问题看起来像 2px 可还行)
  5. 给工具指定要的各种属性,
  6. 画图以==左上==角为参考点, 画文字以==左下==角为参考点
  7. ==canvas 中所有的形变属性操作的都是坐标系== (svg 的形变也是)
    • .translate(x, y)
    • .rotate(x, y)
    • .scale(x, y)

极简使用

  1. 通过 js 代码拿到 canvas 标签
  2. 从 canvas 标签中获取到绘图工具 (平面图有参数 “2d”)
  3. 通过绘图工具调方法在 canvas 标签上绘制图形
  4. 方法
    • .getContext(“2d”)
    • .moveTo(x, y)
    • .lineTo(x, y)
    • .stroke() 绘制已定义的路径
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Canvas开篇</title>
		<style>
			* {
				margin: 0;
				padding: 0;
			}
			canvas {
				background: red;
			}
		</style>
	</head>
	<body>
		<canvas></canvas>
		<script>
			let oCanvas = document.querySelector("canvas");
			let oCtx = oCanvas.getContext("2d");
            // 画条水平线
			oCtx.moveTo(50, 50); // 移动到指定的点
			oCtx.lineTo(200, 50); // 从所在位置连条直线到指定的点
			oCtx.stroke();
		</script>
	</body>
</html>

分门别类

线条
单根线条
  • lineWidth: 线条宽度
  • strokeStyle: 线条颜色
  • lineCap: 线末端类型
    • (butt默认)
    • round
    • square
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Canvas线条属性</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        canvas{
            background: yellowgreen;
        }
    </style>
</head>
<body>
<canvas></canvas>
<script>
    let oCanvas = document.querySelector("canvas");
    let oCtx = oCanvas.getContext("2d");
    oCtx.lineWidth = 50;
    oCtx.strokeStyle = "blue";
    oCtx.lineCap = "round";
    oCtx.moveTo(50, 50);
    oCtx.lineTo(200, 50);
    oCtx.stroke();
</script>
</body>
</html>
多根线条
  1. 多根线条注意点
    • 如果是同一个路径, 那么路径样式会被重(chong)用
    • 如果是同一个路径, 那么后设置的路径样式会覆盖先设置的路径样式
  2. 如何给每根线条单独设置路径样式?
    • 每根线条都开启一个新的路径: 绘图工具.beginPath();
    • 只要不开启新的路径, 后面做的样式设置 stoke 后都会体现在前面的图里
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Canvas多根线条</title>
		<style>
			* {
				margin: 0;
				padding: 0;
			}
			canvas {
				background: yellowgreen;
			}
		</style>
	</head>
	<body>
		<canvas></canvas>
		<script>
			let oCanvas = document.querySelector("canvas");
			let oCtx = oCanvas.getContext("2d");
			oCtx.moveTo(50, 50);
			oCtx.lineTo(200, 50);
			oCtx.lineWidth = 20;
			oCtx.strokeStyle = "blue";
			oCtx.stroke();

			// 重新开启一个路径但没有 .beginPath(), 这条会盖在上面的蓝条里, 也就是影响了已有的
			oCtx.moveTo(50, 100);
			oCtx.lineTo(200, 100);
			oCtx.lineWidth = 10; // 重新设置当前路径样式
			oCtx.strokeStyle = "red";
			oCtx.stroke();

            // 重新开启一个路径, 这个就不影响已有的
			oCtx.beginPath(); 
			oCtx.moveTo(50, 150);
			oCtx.lineTo(200, 150);
			oCtx.lineWidth = 15; // 重新设置当前路径样式
			oCtx.strokeStyle = "green";
			oCtx.stroke();
		</script>
	</body>
</html>
虚线

方法

  • .setLineDash([width, padding]) (画虚线)
  • .setLineDash([width1, width2, width3]) (画虚线) 这里三个参数先是有无有, 再无有无, 然后重复
  • .getDashLine() (拿到不重复的一端虚线, 值是一个数组)

属性

lineDashOffset(设置虚衔偏移位)

图形
简单图形
  • .lineTo 闭合图形有闭合处不美观的问题, 应通过 ==.closePath== 来做闭合
  • .closePath()
  • lineJoin: 设置相交线的拐点样式
    • miter (默认)
    • round
    • bevel (平切掉尖角)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>05-Canvas简单图形</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        canvas{
            display: block;
            margin: 0 auto;
            background: red;
        }
    </style>
</head>
<body>
<canvas width="500" height="500"></canvas>
<script>
    let oCanvas = document.querySelector("canvas");
    let oCtx = oCanvas.getContext("2d");
    oCtx.moveTo(50, 50);
    oCtx.lineTo(200, 50);
    oCtx.lineTo(200, 200);
    oCtx.closePath();
    oCtx.lineWidth = 20;
    oCtx.lineJoin = "bevel";
    oCtx.stroke();
</script>
</body>
</html>
填充图形
  • 不用 .stroke 而是用 .fill
  • .fill()
  • fillStyle
填充图形的非零环绕
  • 对于同一路径,在填充的时候回遵循非零环绕规则
  • 从当前的区域拉出一条直线, 遇到顺时针相交的线就 +1, 遇到逆时针相交的线就 -1 (嚯! 有向!但 canvas 输出的时标量图哈)
  • 最终计算的结果如何是 0 就不填充, 如果==不是 0 就填充==
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>06-Canvas填充图形</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        canvas{
            display: block;
            margin: 0 auto;
            background: red;
        }
    </style>
</head>
<body>
<canvas width="500" height="500"></canvas>
<script>
    let oCanvas = document.querySelector("canvas");
    let oCtx = oCanvas.getContext("2d");

    oCtx.moveTo(100, 100);
    oCtx.lineTo(300, 100);
    oCtx.lineTo(300, 300);
    oCtx.lineTo(100, 300);
    oCtx.closePath();

    
	// 这样就不填充, 因为是逆时针, -1
	oCtx.moveTo(250, 150);
	oCtx.lineTo(150, 150);
	oCtx.lineTo(150, 250);
	oCtx.lineTo(250, 250);
	oCtx.closePath();
    
    
    oCtx.fill();
</script>
</body>
</html>
获取 canvas 宽高

方法一 通过元素都有的 offsetWidth 和 offsetHeight 属性来获取

console.log(oCanvas.offsetWidth);
console.log(oCanvas.offsetHeight);

方法二 通过 canvas 对象特有的 canvas 属性的 width 和 height 属性来获取 (害, 还好现在拎得清了)


console.log(oCtx.canvas.width);
console.log(oCtx.canvas.height);

svg

简介

SVG vs Bitmap
  1. 什么是 SVG?
    • SVG 英文全称为 Scalable Vector Graphics,意思为可缩放的矢量图
    • 使用中 svg 是与 table 和 form 拥有多个子标签的标签组
  2. 位图和矢量图 在计算机中有两种图形, 一种是位图, 一种是矢量图
    1. 位图 传统的 jpg / png / gif图都是位图 位图是一个个很小的颜色小方块组合在一起的图片。一个小方块代表 1px
    2. 位图的优点和缺点 优点: 色彩丰富逼真 缺点: 放大后会失真, 体积大
    3. 矢量图 矢量图是==用 XML 格式==定义, 通过各种「==路径==」和「==填充颜色==」来描述渲染的的图片
    4. 矢量图优点和缺点: 优点: 放大后不会失真, 体积小 缺点: 不易制作色彩变化太多的图象
svg vs canvas
  • 区别一
    • svg绘制出来的每一个图形的元素都是独立的 DOM 节点, 能够方便的绑定事件或用来修改
    • canvas输出的是一整幅画布;
  • 区别二
    • svg输出的图形是矢量图形,后期可以修改参数来自由放大缩小,不会是真和锯齿
    • canvas 输出标量画布,就像一张图片一样,放大会失真或者锯齿。
svg 注意点
  1. 和 canvas 一样, svg 也有默认的宽高, 并且默认的宽高和 canvas 都是一样的 默认的宽度是 300px, 默认的高度是 150px

  2. 和 canvas 不一样的是, ==svg 可以通过 css 设置宽高==, 也可以通过行内的属性来设置宽高

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>01-SVG开篇</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            svg{
                background: red;
                /*width: 500px;*/
                /*height: 500px;*/
            }
        </style>
    </head>
    <body>
    
    <svg width="500" height="500">
        <circle cx="100" cy="100" r="50" fill="transparent" stroke="#000"></circle>
    </svg>
    </body>
    </html>
    

svg 的使用

SVG常见的四种使用方式

  1. 内嵌到HTML中(直接在 HTML 的 svg 标签中绘制)

  2. 通过浏览器直接打开SVG文件

    • 注意点

      如果需要将svg保存到一个单独的文件中, 并且需要通过浏览器直接打开, 那么就必须给svg添加一个属性

      xmlns="www.w3.org/2000/svg"

    <svg width="500" height="500" xmlns="http://www.w3.org/2000/svg">
    	<circle cx="100" cy="100" r="50" fill="transparent" stroke="#000"></circle>
    </svg>
    <!-- 
    	svg 文件是 xml 格式的,
    	html 是一种特殊的 xml, svg 文件也是一种特殊的 xml, 
    	以 svg 为文件尾缀时需要加上  xmlns="http://www.w3.org/2000/svg"
    -->
    
  3. **在 HTML 的 img 标签中引用 **(还能在 svg 里插图片! 套娃操作!)

    <img src="circle.svg" alt="">
    
  4. 作为 CSS 背景使用

    div {
        width: 500px;
        height: 500px;
        background: url("circle.svg") no-repeat;
    }
    

标签和标签属性

  • <svg></svg>
  • <circle></circle>
  • <rect></rect>
  • <ellipse></ellipse>

svg 标签属性们

矩形, 圆形, 椭圆形
<rect></rect>
  • x/y: 指定绘制的位置
  • width/height: 指定绘制的大小
  • fill: 修改填充的颜色
  • stroke: 修改描边的颜色 (和 canvas 放一起讲果然很合适)
  • stroke-width: 修改描边的宽度
  • rx/ry: 设置圆角的半径
<circle></circle>
<rect x="100" y="100" width="100" height="100" rx="50"></rect>
<circle cx="100" cy="100" r="50"></circle>
<ellipse></ellipse>
<rect x="100" y="100" width="200" height="100" rx="100" ry="50"></rect>
<ellipse cx="100" cy="100" rx="100" ry="50"></ellipse>

<rect></rect> 通过设置 rx(ry) 为宽度(高度) 的一般可以画出圆(或椭圆) <circle></circle> <ellipse></ellipse> 可以写短一点点

  • cx/cy: 圆绘制的位置(圆心的位置)
  • r: 圆的半径
  • cx/cy: 椭圆绘制的位置(圆心的位置)
  • rx: 水平方向的半径
  • ry: 垂直方向的半径
折线, 多边形
<polyline></polyline>
<line x1="100" y1="100" x2="300" y2="100" stroke="#000"></line>
<polyline points="100 100 300 100 300 300" stroke="#000" fill="none"></polyline>
<polygon></polygon>

polygon和polyline差不多, 只不过会自动关闭路径

<polygon points="100 100 300 100 300 300" stroke="#000" fill="none"></polygon>
  • x1/y1: 设置起点
  • x2/y2: 设置终点
  • points: 设置所有的点, 两两一对
  • fill: 修改填充颜色
  • fill-opacity: 0~1 设置填充颜色的透明度
  • stroke: 修改描边颜色
  • stroke-width: 修改描边宽度
  • stroke-opacity: 0~1 设置描边透明度
  • stroke-linecap: butt/square/round 设置线段两端帽子stroke-dasharray: 设置虚线
  • stroke-dashoffset: 设置虚线偏移位
  • stroke-linejoin: miter/bevel/round 设置折线转角样式
文字
<text></text>
<tspan></tspan>

svg 路径

<path></path>
简介

什么是SVG路径?

  • SVG 路径是一个比较牛X的东西, 可以绘制任意图形, 只不过比较复杂
  • 可以给图里话的东西包裹 a 标签, 用视觉层面的蛇皮走位的元素做跳转链接

注意点

  • 大写字母是绝对定位, 小写字母是相对定位
    • 绝对定位: 相对于 svg 块块左上角
    • 相对定位: 相对上一次的位置, 在上一次位置基础上做调整
线
  • M = moveto 起点
  • L = lineto 其它点
  • H = horizontal lineto 和上一个点Y相等
  • V = vertical lineto 和上一个点X相等
  • Z = closepath 关闭当前路径
  • A = elliptical Arc
  • A(rx, ry, xr, laf, sf, x, y) 从当前位置绘制弧线到指定位置
  • rx (radiux-x): 弧线X半径
  • ry (radiux-y): 弧线Y半径
  • xr (xAxis-rotation): 弧线所在椭圆旋转角度
  • laf(large-arc-flag): 是否选择弧长较长的那一段
  • sf (sweep-flag): 是否顺时针绘制
  • x,y: 弧的终点位置
贝塞尔曲线
  • Q = quadratic Bézier curve
    • Q(x1, y1, x, y) 从当前位置绘制二次贝塞尔曲线到指定位置
    • x1,y1: 控制点位置
    • x,y: 终点位置
  • C = curveto
    • C(x1, y1, x2, y2, x, y) 从当前位置绘制三次贝塞尔曲线到指定位置
    • x1, y1: 控制点1位置
    • x2, y2: 控制点2位置
    • x, y: 终点位置
绘制文本路径 (真的骚)

步骤

  1. 定义一个路径
  2. 告诉文本需要按照哪个路径来绘制

注意点 如果是绘制路径文本, 则超出路径范围的内容不会被绘制出来

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>11-SVG绘制路径文本</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        svg{
            display: block;
            margin: 0 auto;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
<svg width="500" height="500">
    <defs>
        <path id="myPath" d="M 100 100 Q 150 50 200 100" stroke="red" fill="none"></path>
    </defs>
    <text>
        <textPath xlink:href="#myPath">知播渔教育(http://www.it666.com)</textPath>
    </text>
</svg>
</body>
</html>
g 结构元素(复用)
  1. g 结构元素
    • g 是 group 的缩写, 可以将多个元素放到一个 g 标记中, 这样就组成了一个组
    • 以便统一操作,比如旋转,缩放或者添加相关样式等
    • 对 g 标记设置的所有样式都会应用到这一组所有的元素中
  2. use
    • g 结构元素封装的图形还可以通过 <use> 元素进行复制使用
  3. defs
    • g 封装的元素默认是可见的, 如果仅仅是需要定义一组模板, 将来需要用到时候才显示, 那么就可以使用 defs
  4. symbol
    • symbol ==兼具== <g> 的分组功能和 <defs> 初始不可见的特性,
    • symbol 能够创建自己的视窗,所以能够应用 viewBox 和 preserveAspectRatio 属性
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SVG 结构元素</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        svg{
            display: block;
            margin: 0 auto;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
<svg width="500" height="500">
    <!--
    <circle cx="100" cy="100" r="100" fill="red"></circle>
    <circle cx="100" cy="200" r="50" fill="red"></circle>
    <circle cx="100" cy="300" r="30" fill="red"></circle>

    <circle cx="300" cy="100" r="100" fill="red"></circle>
    <circle cx="300" cy="200" r="50" fill="red"></circle>
    <circle cx="300" cy="300" r="30" fill="red"></circle>
    -->
    <!--
    <g id="myGroup">
        <circle cx="100" cy="100" r="100"></circle>
        <circle cx="100" cy="200" r="50"></circle>
        <circle cx="100" cy="300" r="30"></circle>
    </g>
    <use xlink:href="#myGroup" x="300" fill="blue"></use>
    -->
    <!--
    <defs>
        <g id="myGroup">
            <circle cx="100" cy="100" r="100"></circle>
            <circle cx="100" cy="200" r="50"></circle>
            <circle cx="100" cy="300" r="30"></circle>
        </g>
    </defs>
    <use xlink:href="#myGroup" x="0" fill="blue"></use>
    <use xlink:href="#myGroup" x="300" fill="red"></use>
    -->
    <symbol>
        <g id="myGroup">
            <circle cx="100" cy="100" r="100"></circle>
            <circle cx="100" cy="200" r="50"></circle>
            <circle cx="100" cy="300" r="30"></circle>
        </g>
    </symbol>
    <use xlink:href="#myGroup" x="0" fill="blue"></use>
    <use xlink:href="#myGroup" x="300" fill="red"></use>
</svg>
</body>
</html>

其余

裁剪与蒙版
<clipPath></clipPath>
<mask></mask>

用法: 用 id 标记组件, 通过 属性名=“url()” 的方式使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>15-SVG裁剪和蒙版</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        svg{
            display: block;
            margin: 0 auto;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
<svg width="500" height="500">
    <!--
	<rect x="100" y="100" width="300" height="200" fill="blue"></rect>
    <circle cx="200" cy="200" r="100" fill="red"></circle>
	-->
    <!--
    <clipPath id="myClip">
        <circle cx="200" cy="200" r="100" fill="red"></circle>
    </clipPath>
    <rect x="100" y="100" width="300" height="200" fill="blue" clip-path="url(#myClip)"></rect>
    -->
    <mask id="myMask">
        <circle cx="200" cy="200" r="100" fill="rgba(255, 0, 0, 0.5)"></circle>
    </mask>
    <rect x="100" y="100" width="300" height="200" fill="blue" mask="url(#myMask)"></rect>
</svg>
</body>
</html>
线性渐变与径向渐变
<linearGradient></linearGradient>
<radialGradient></radialGradient>
  1. 和Canvas一样, 在SVG中也可以生成渐变颜色
    • <linearGradient></linearGradient> 线性渐变
    • <radialGradient></radialGradient> 径向渐变
  2. 渐变属性
    • x1/y1: 渐变范围开始位置
    • x2/y2: 渐变范围结束位置
    • 默认情况下 x1/y1/x2/y2 是当前元素的百分比
    • 可以通过gradientUnits修改
      • gradientUnits="objectBoundingBox" (默认是这个)
      • gradientUnits="userSpaceOnUse"
  3. 注意点
    • 使用渐变颜色需要通过url(#id)格式来使用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>16-SVG渐变</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        svg{
            display: block;
            margin: 0 auto;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
<svg width="500" height="500">
    <defs>
        <!--<linearGradient id="myColor" x1="0" y1="0" x2="1" y2="1">-->
        <!--
		<linearGradient id="myColor" x1="0" y1="0" x2="1" y2="1" gradientUnits="objectBoundingBox">
		-->
        <linearGradient id="myColor" x1="100" y1="100" x2="400" y2="100" gradientUnits="userSpaceOnUse">
            <stop offset="0" stop-color="red"></stop>
            <stop offset="1" stop-color="blue"></stop>
        </linearGradient>
    </defs>
    <rect x="100" y="100" width="300" height="200" fill="url(#myColor)"></rect>
</svg>
</body>
</html>
svg 画笔 (填充自定义)
<pattern></pattern>

在SVG中除了可以使用纯色和渐变色作为填充色以外, 还==可以使用自定义图形作为填充==

Pattern属性

  • width/height 默认情况下也是百分比
  • 可以通过gradientUnits修改
  • patternUnits="objectBoundingBox" (默认取值)
  • patternUnits="userSpaceOnUse" (改为这个就由百分比改为像素值)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>17-SVG画笔</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        svg{
            display: block;
            margin: 0 auto;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
<svg width="500" height="500">
    <defs>
        <!--<pattern id="myPattern" width="0.2" height="0.2">-->
        <!--<pattern id="myPattern" width="0.2" height="0.2" patternUnits="objectBoundingBox">-->
        <pattern id="myPattern" width="20" height="20" patternUnits="userSpaceOnUse">
            <circle cx="10" cy="10" r="10" fill="red"></circle>
        </pattern>
    </defs>
    <!--<circle cx="10" cy="10" r="10" fill="red"></circle>-->
    <rect x="100" y="100" width="300" height="200" fill="url(#myPattern)"></rect>
</svg>
</body>
</html>
svg 形变

和 canvas 一样, 形变是基于坐标系的改变

用法是在对应图形标签内添加 transform 属性, 值是想要的行变操作及其值

svg 可视区域

内容区域指块内内容, 可视区域(viewBox)是看得到内容的部分, 内容区域==可以大于==可视区域

用法是在对应图形标签内添加 viewBox 属性, 值是想要的行变操作及其值

ViewBox 属性格式
  • viewBox="x y width height"
  • x: 修改视口向 x方向偏移量
  • y: 修改视口向 y方向偏移量
  • width/height: 修改可视区域尺寸, ==近大远小==
preserveAspectRatio 属性格式

默认情况下如果 viewBox 的尺寸是等比缩放的, 那么调整后 viewBox 区域的 x, y 和内容区域的 x, y 对齐, 但是如果 viewBox 的尺寸不是等比缩放的, 系统就会调整 viewBox 的位置, 我们设置的 x/y 会失效 此时如果需要 viewBox 的 x, y 和内容区域(viewProt)的 x, y 继续保持重合, 那么就需要使用 preserveAspectRatio 属性来设置对齐方式

  1. preserveAspectRatio 第一个参数 xMin viewport和viewBox左边对齐 xMid viewport和viewBox x轴中心对齐 xMax viewport和viewBox右边对齐 YMin viewport和viewBox上边缘对齐。注意Y是大写。 YMid viewport和viewBox y轴中心点对齐。注意Y是大写。 YMax viewport和viewBox下边缘对齐。注意Y是大写。
  2. preserveAspectRatio 第二个参数 meet 保持纵横比缩放viewBox适应viewport,受 slice 保持纵横比同时比例小的方向放大填满viewport,攻 none 扭曲纵横比以充分适应viewport,变态
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>20-SVG-ViewBox下</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        svg{
            display: block;
            margin: 0 auto;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <svg width="200" height="200" viewBox="0 0 200 200">
        <circle cx="50" cy="50" r="50" fill="red"></circle>
    </svg>
    <!---->
    <svg width="200" height="200" viewBox="0 0 400 400">
        <circle cx="50" cy="50" r="50" fill="red"></circle>
    </svg>
    <svg width="200" height="200" viewBox="0 0 150 150">
        <circle cx="50" cy="50" r="50" fill="red"></circle>
    </svg>

    <svg width="200" height="200" viewBox="0 0 50 150" preserveAspectRatio="xMinYMin">
        <circle cx="50" cy="50" r="50" fill="red"></circle>
    </svg>
    <svg width="200" height="200" viewBox="0 0 150 50" preserveAspectRatio="xMinYMin">
        <circle cx="50" cy="50" r="50" fill="red"></circle>
    </svg>
</body>
</html>
svg 动画
  1. SVG动画

    • 在SVG中提供了三种常用动画标记
    • <animate> 基础动画
    • <animateTransform> 形变动画 (默认也是对坐标系做操作, 但可以指定原点位置)
    • <animateMotion> 路径动画
  2. SVG 动画使用方式

    1. 创建动画, 告诉动画标记哪个元素需要执行动画
    2. 创建元素, 在元素中说明需要执行什么动画 (标签包裹 animate 标签)
  3. SVG 动画属性

    • attributeType: CSS/XML 规定的属性值的名称空间
    • attributeName: 规定元素的哪个属性会产生动画效果
    • from/to: 从哪到哪
    • dur: 动画时长
    • fill: 动画结束之后的状态 保持 freeze 结束状态/remove 恢复初始状态
  4. SVG 动画其他属性

    • repeatCount: 规定动画重复的次数。
    • repeatDur: 规定动画重复总时长
    • begin: 规定动画开始的时间
      • begin="1s"
      • begin="click"
      • begin="click + 1s"
    • restart: 规定元素开始动画之后,是否可以被重新开始执行
      • always:动画可以在任何时候被重置。这是默认值
      • whenNotActive:只有在动画没有被激活的时候才能被重置,例如在动画结束之后
      • never:在整个SVG执行的过程中,元素动画不能被重置
    • calcMode: 规定每一个动画片段的动画表现
      • linear:默认属性值, 匀速动画
      • discrete: 非连续动画, 没有动画效果瞬间完成
      • paced: 规定整个动画效果始终以相同的速度进行,设置keyTimes属性无效
      • spline: 配合 keySplines 属性来定义各个动画过渡效, 自定义动画
    • keyTimes
      • 划分动画时间片段, 取值0-1
    • values
      • 划分对应取值片段的值

    更多

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>21-SVG动画</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        svg{
            display: block;
            margin: 0 auto;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <svg width="500" height="500">
        <!--
        <circle id="myCircle" cx="100" cy="100" r="50" fill="blue"></circle>
        <animate
          attributeName="r"
          from="50"
          to="100"
          dur="5s"
          xlink:href="#myCircle"
        ></animate>
        -->
        <circle cx="100" cy="100" r="50" fill="blue">
            <animate
                    attributeName="r"
                    from="50"
                    to="100"
                    dur="5s"
                    fill="freeze"
            ></animate>
        </circle>
    </svg>
</body>
</html>
svg 往返动画
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>23-SVG混合动画</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        svg{
            display: block;
            margin: 0 auto;
            border: 1px solid #000;
        }
    </style>
    <svg width="500" height="500">
        <circle cx="100" cy="100" r="50" fill="blue">
            <!--
            <animate
                    attributeName="r"
                    from="50"
                    to="100"
                    dur="2s"
                    fill="freeze"
                    begin="click"
            ></animate>
            <animate
                    attributeName="fill"
                    from="blue"
                    to="red"
                    dur="2s"
                    fill="freeze"
                    begin="click"
            ></animate>
            -->
            <animate
                    id="toRight"
                    attributeName="cx"
                    from="100"
                    to="300"
                    dur="2s"
                    begin="0;toLeft.end"
                    fill="freeze"
            ></animate>
            <animate
                    id="toLeft"
                    attributeName="cx"
                    from="300"
                    to="100"
                    dur="2s"
                    begin="toRight.end + 2s"
                    fill="freeze"
            ></animate>
        </circle>
    </svg>
</head>
<body>
	震惊, 居然可以不放在 body 标签里
</body>
</html>

用 js 画 svg 注意点

  1. 创建SVG时必须指定命名空间

  2. SVG脚本编程注意点