SVG之线条动画相关

前言

最近在实现VUI库的基础组件progress,其中涉及到圆形进度相关的绘制,参考了element ui框架的实现发现是通过svg来实现的。

实际上自身之前对于svg仅仅是知道的水平,本文旨在提交自身对于svg路径path以及动画相关内容的了解。

本文内容主要分为三块:

  • viewBox属性
  • svg路径path相关知识学习
  • stroke-dasharray和stroke-dashoffset属性学习

viewBox属性

首先来学习viewBox属性的,该属性是用于呈现内容区域的,常用于svg等标签上。

viewBox属性存在4个值:

viewBox=“x y width height”

其中x/y表示起始点坐标,width/height表示呈现区域的宽高。

viewBox属性存在的特点:

  • 当svg的父标签的width或height小于viewBox的设置,svg会等比调整到svg父标签width/height中最小值
  • 当svg的父标签的width或height大于viewBox的设置,svg会等比调整到svg父标签width/height中最大值

即总是以适合的比例来呈现内容

实例1:

父标签width设置为50px,viewBox的width/height统一设置成100
在这里插入图片描述

实例2:

父标签width设置成300px,viewBox的width/height统一设置成100
在这里插入图片描述

实例3:

viewBox属性前2个属性值即起始坐标设置的呈现效果
在这里插入图片描述

从上面可以看出,当设置x/y值是,实际上svg中的内容在x轴方向相对右侧向左移动了10px,y轴方向上相对底部向上移动了10px。

实际上x/y也可以设置负值,负值在x轴方向会相对左侧向右移动一定像素,y轴的则如正值的相反。

一般场景,viewBox中的x/y都是设置为0

<path>标签

svg中 标签可以实现所有其他的基本形状,也是svg中相对比较复杂的标签。

该标签提供一些绘制命令,使用d属性来存储路径命令数据,命令主要如下:

  • M/m:移动命令,表示绘制轮廓的起始位置

  • L/l:绘制直线到指定坐标

  • V/v:垂直方向绘制直线到指定坐标

  • H/h:水平方向绘制直线到指定坐标

  • A/a:绘制弧线

    A/a: rx ry xr laf sf x y

    • rx、ry:表示圆弧的x和y方向的半径
    • xr:圆弧横轴相对坐标系横轴的偏移角度
    • laf:取大角度弧还是小角度弧,1表示大角度弧,0表示小角度弧
    • sf:顺时针还是逆时针,1表示顺,0表示逆
    • x、y:弧的终点坐标

需要注意的是:

大写命令的坐标表示绝对坐标,小写命令的坐标表示相对坐标

实例1:

通过path + circle来查看绘制起点的位置问题
在这里插入图片描述
path绘制一个圆,circle是用于标识指定坐标。

从上面可以看出,在svg viewBox为100即父容器恰好可以呈现的情况下,(50,50)实际上对应path绘制圆的顶点,那这里是不是可以认为:

path中M移动位置即依据绝对坐标来移动,是依据最最接近坐标原点的顶点为基础来进行的,即上图中圆黑点的位置

现在想要是圆点位置在svg的中心即黑点位置,要如何做呢?

<path
	d="M 50 50 m 0 -47 a 47 47 0 1 1 0 94 a 47 47 0 1 1 0 -94"
	stroke="#ebeef5"
  stroke-width="2.0"
  fill="none">
</path>

需要解释下d中内容:

M 50 50 m 0 -47 a 47 47 0 1 1 0 94 a 47 47 0 1 1 0 -94

  • M 50 50:表示已绝对坐标移动到(50,50)

  • m 0 -47:表示已相对坐标延y轴方向上向上移动47px,即顶点位置在(50, 3)处

  • a 47 47 0 1 1 0 94:

    以相对坐标绘制圆弧,这里47表示半径,为什么是47呢?

    实际上这里半径是(viewbox的width/2 - 边框的strokeWidth)得到的,即实际上这里也可以是 50 - 2即48

    以当前点位置为起始点即(50,3),终点的绝对坐标是(50,94),即从(50, 3)以半径47逆时针画弧到(50,94)

    这里实际上需要专注第3个参数,该参数表示圆弧横轴相对坐标系横轴的偏移角度,需要注意的是:

    实际上当x轴半径和y轴半径相同,即形成圆时,该参数不论设置为任何值都没有效果

实例2:

查看path中a中第三个参数的影响效果
在这里插入图片描述
从上面实例可知道:

path a的第三个参数需要在圆弧x轴和y轴半径不对时,才会有效果

storke-dasharray和stroke-dashoffset

首先先介绍stroke-dasharray属性,该属性是用于设置边框的实虚线的即哪里是实线,哪里是虚线。

实例1:

在这里插入图片描述
上面例子中设置了stroke-dasharray为1px,这里整个直线原始长度为10px(在上面中实际上被放大了10倍,即100px)。从上图中可知实线区域是5个即5px,虚线也是5个即每1px有一个实线区域。

  • 当设置stroke-dasharray为2px时,实线区域数目为3
  • 当设置stroke-dasharray为3px时,实线区域数目为2
  • 当设置stroke-dasharray为4px时,实线区域数目为2
  • 当设置stroke-dasharray为5px时,实线区域数目为1
  • 当设置stroke-dasharray为6px时,实线区域数目为1

上面说的实线区域数目都是指viewBox即可视区域展示出来的实线数目,由上面的逻辑可知实线数目在可视区域是可被计算出来的:

实线数目计算值 = 直线原始长度 / (2 * stroke-dasharray定义的虚线宽度) 
实线数目 = Number.isInteger(实线数据计算值) ? 实线数目计算值 : parseInt(实线数据计算值 + 1, 10);

实际上:

stroke-dasharray是设置虚线宽度,当虚线宽度被增加,在一定可视范围内,就会呈现出虚线宽度增加,实线宽度也会增加的效果,即拉伸的效果

线条动画正是基于拉伸效果产生的

紧接着介绍stroke-dashoffset属性,线条动画另一个关键属性,该属性是设置dasharray数组呈现时的偏移量。

stroke-dashoffset设置的效果是自身循环的,即不需要担心stroke-dashoffset设置超过总长度的问题。

实例2:

在这里插入图片描述
上面是stroke-dashoffset设置为0时的显示情况,当stroke-dashoffset设置1px时,具体呈现如下:
在这里插入图片描述
从上图中可知,当stroke-dashoffset设置为1px时,效果上向左移动了1px。

stroke-dashoffset支持正负数,效果上正数表示向左移动或逆时针移动,负数表示向右移动或顺时针移动

动画实例:进度条

使用stroke-dasharray + stroke-dashoffset实现一个小动画:直线进度条。

<!DOCTYPE html>
<html>
	<head>
		<style type="text/css">
			@keyframes progress-animate {
				form {
					stroke-dashoffset: 200px;
				}
				to {
					stroke-dashoffset: 0px;
				}
			}
			.progress {
				stroke-dasharray: 200px;
				stroke-dashoffset: 200px;
				animation: progress-animate 3s infinite;
			}
		</style>
	</head>
<body>
	<div style="width: 100px;height: 100px;">
		<svg>
			<path
				 d="M 10 10 L 210 10"
				  stroke="#ddd"
				  stroke-width="8"
				  stroke-linecap="round">
			</path>
			<path
				class="progress"
				d="M 10 10 L 210 10"
				stroke="rgb(64, 158, 255)"
				stroke-width="8"
				stroke-linecap="round">
			</path>
		</svg>
	</div>
</body>
</html>

实现效果:
audio.gif
实际上上面简单动画核心原理在于:

  • 设置stroke-dasharray >= 直线长度

  • 设置stroke-dashoffset = 直线长度 * 进度百分比

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值