canvas 和 svg
canvas 和 svg 的一些东西有相同的名字和作用, 比如 stroke 和 fill 区别在于
- canvas 是做位图的, svg 是做矢量图的
- canvas 用 js 来画, svg 在标签里面写 (当然也能用 js 写)
==canvas 和 svg 都非常多而且比较难, 以下内容了解即可, 工作中都是利用框架==
canvas
简介
什么是Canvas?
- Canvas 是 H5 新增的一个标签, 我们可以通过 JS 在这个标签上绘制各种图案
- Canvas 拥有多种绘制==路径==, ==矩形==, ==圆形==, ==字符==以及==图片==的方法
canvas 注意点
- canvas有默认的宽度和高度
- 默认宽300px
- 高150px
- canvas 的坐标的原点在==左上角==, 向右是 x 轴正方向, 向下是 y 轴正方向
- ==不能==通过CSS设置画布的宽高
- 通过CSS设置画布宽高会在默认宽高的基础上拉伸
- 如果需要设置 canvas 宽高请通过元素行内属性 width 和 height 设置
- 线条默认宽度和颜色
- 通过 canvas 绘制的线条默认宽度是 1px, 颜色是纯黑色
- 但是由于默认情况下canvas会将==线条的中心点和像素的底部==对齐 (数值后面加 .5 就能解决问题)
- 所以会导致显示效果是 2px 和非纯黑色问题 (实际的 1px 由于显示方式问题看起来像 2px 可还行)
- 要先给工具指定要的各种属性, 再画
- 画图以==左上==角为参考点, 画文字以==左下==角为参考点
- ==canvas 中所有的形变属性操作的都是坐标系== (svg 的形变也是)
- .translate(x, y)
- .rotate(x, y)
- .scale(x, y)
极简使用
- 通过 js 代码拿到 canvas 标签
- 从 canvas 标签中获取到绘图工具 (平面图有参数 “2d”)
- 通过绘图工具调方法在 canvas 标签上绘制图形
- 方法
- .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>
多根线条
- 多根线条注意点
- 如果是同一个路径, 那么路径样式会被重(chong)用
- 如果是同一个路径, 那么后设置的路径样式会覆盖先设置的路径样式
- 如何给每根线条单独设置路径样式?
- 每根线条都开启一个新的路径:
绘图工具.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
- 什么是 SVG?
- SVG 英文全称为 Scalable Vector Graphics,意思为可缩放的矢量图
- 使用中 svg 是与 table 和 form 拥有多个子标签的标签组
- 位图和矢量图
在计算机中有两种图形, 一种是位图, 一种是矢量图
- 位图 传统的 jpg / png / gif图都是位图 位图是一个个很小的颜色小方块组合在一起的图片。一个小方块代表 1px
- 位图的优点和缺点 优点: 色彩丰富逼真 缺点: 放大后会失真, 体积大
- 矢量图 矢量图是==用 XML 格式==定义, 通过各种「==路径==」和「==填充颜色==」来描述渲染的的图片
- 矢量图优点和缺点: 优点: 放大后不会失真, 体积小 缺点: 不易制作色彩变化太多的图象
svg vs canvas
- 区别一
- svg绘制出来的每一个图形的元素都是独立的 DOM 节点, 能够方便的绑定事件或用来修改
- canvas输出的是一整幅画布;
- 区别二
- svg输出的图形是矢量图形,后期可以修改参数来自由放大缩小,不会是真和锯齿
- canvas 输出标量画布,就像一张图片一样,放大会失真或者锯齿。
svg 注意点
-
和 canvas 一样, svg 也有默认的宽高, 并且默认的宽高和 canvas 都是一样的 默认的宽度是 300px, 默认的高度是 150px
-
和 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常见的四种使用方式
-
内嵌到HTML中(直接在 HTML 的 svg 标签中绘制)
-
通过浏览器直接打开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" --> -
-
**在 HTML 的 img 标签中引用 **(还能在 svg 里插图片! 套娃操作!)
<img src="circle.svg" alt=""> -
作为 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: 终点位置
绘制文本路径 (真的骚)
步骤
- 定义一个路径
- 告诉文本需要按照哪个路径来绘制
注意点 如果是绘制路径文本, 则超出路径范围的内容不会被绘制出来
<!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 结构元素(复用)
- g 结构元素
- g 是 group 的缩写, 可以将多个元素放到一个 g 标记中, 这样就组成了一个组
- 以便统一操作,比如旋转,缩放或者添加相关样式等
- 对 g 标记设置的所有样式都会应用到这一组所有的元素中
- use
- g 结构元素封装的图形还可以通过
<use>元素进行复制使用
- g 结构元素封装的图形还可以通过
- defs
- g 封装的元素默认是可见的, 如果仅仅是需要定义一组模板, 将来需要用到时候才显示, 那么就可以使用 defs
- symbol
- symbol ==兼具==
<g>的分组功能和<defs>初始不可见的特性, - symbol 能够创建自己的视窗,所以能够应用 viewBox 和 preserveAspectRatio 属性
- symbol ==兼具==
<!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>
- 和Canvas一样, 在SVG中也可以生成渐变颜色
<linearGradient></linearGradient>线性渐变<radialGradient></radialGradient>径向渐变
- 渐变属性
- x1/y1: 渐变范围开始位置
- x2/y2: 渐变范围结束位置
- 默认情况下 x1/y1/x2/y2 是当前元素的百分比
- 可以通过gradientUnits修改
- gradientUnits="objectBoundingBox" (默认是这个)
- gradientUnits="userSpaceOnUse"
- 注意点
- 使用渐变颜色需要通过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 属性来设置对齐方式
- preserveAspectRatio 第一个参数 xMin viewport和viewBox左边对齐 xMid viewport和viewBox x轴中心对齐 xMax viewport和viewBox右边对齐 YMin viewport和viewBox上边缘对齐。注意Y是大写。 YMid viewport和viewBox y轴中心点对齐。注意Y是大写。 YMax viewport和viewBox下边缘对齐。注意Y是大写。
- 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 动画
-
SVG动画
- 在SVG中提供了三种常用动画标记
<animate>基础动画<animateTransform>形变动画 (默认也是对坐标系做操作, 但可以指定原点位置)<animateMotion>路径动画
-
SVG 动画使用方式
- 创建动画, 告诉动画标记哪个元素需要执行动画
- 创建元素, 在元素中说明需要执行什么动画 (标签包裹 animate 标签)
-
SVG 动画属性
- attributeType: CSS/XML 规定的属性值的名称空间
- attributeName: 规定元素的哪个属性会产生动画效果
- from/to: 从哪到哪
- dur: 动画时长
- fill: 动画结束之后的状态 保持 freeze 结束状态/remove 恢复初始状态
-
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 注意点
-
创建SVG时必须指定命名空间
- const SVG_NS = "www.w3.org/2000/svg"
-
SVG脚本编程注意点
- 使用xlink属性也必须指定命名空间
- const XLINK_NS = "www.w3.org/1999/xlink";