曲线进度条的实现

位置: 首页 > 前端三套件
[发布: 2023.9.18  作者: 马黑  阅读: 171]

总体思路:

借助 svg 的 path 元素创建曲线路径 d,d 路径将显示在容器元素之上,它还将成为模拟进度滑块的 html 元素的 offset-path 值,即 d 路径同时也是描述滑块行进的路线。

路径设计:

考虑到易用性和复用性,容器元素应可以自定义宽高,为此,路径应能依据容器元素的尺寸动态生成。svg d 路径不支持百分比,为此只能在运行时根据容器元素尺寸设计路径,出于简化目的,可以使用二次贝塞尔曲线来完成曲线设计:从容器的左上角开始到容器的右上角终止,控制点 (x,y) 的 x 为容器宽度的一半、y 为容器高度减去 20。

实现细节:

一、CSS样式

#mydiv 选择器指向容器元素,#ball 选择器是模拟滑块,#svg 选择器是 svg 元素,#mypath 是在 svg 里设计的 path 路径。

<style>

#mydiv {
	margin: 20px auto;
	width: 200px;
	height: 120px;
	box-sizing: border-box;
	position: relative;
	--prog: 0%;
}

#ball, #svg { position: absolute; }

#ball {
	position: absolute;
	width: 10px;
	height: 10px;
	background: green;
	pointer-events: none;
	offset-distance: var(--prog);
}

#mypath { cursor: pointer; }

</style>

二、HTML结构

容器元素下包裹一个 svg 元素和 一个 div 模拟滑块,svg 标签下有一个 path 路径元素,其 d 路径可以随意设置,它将被后面 JS 动态生成的实际使用路径所覆盖。

<div id="mydiv">
	<svg id="svg" width="100%" height="100%">
		<path id="mypath" d="M0 0 Q100 140 200 0" fill="none" stroke="silver" stroke-width="4" />
	</svg>
	<div id="ball"></div>
</div>

三、JS完成路径生成与进度交互

首先,声明两个变量:

let posAr = [], len = 0;

posAr 数组变量用来记录路径上每一个点的 x 坐标,将来进度交互会用到它;len 是曲线长度,0 表示它是一个数值,将来会被实际长度覆盖。

接下来写一个自执行匿名函数,它完成两个功能:一是根据容器元素的尺寸生成我们前面设计好大体模样的路径,并将路径加诸于 mypath 元素 和 ball 元素;二是获得曲线每一个像素的 X 坐标值,存入 posAr 数组中。

(function() {
	let ww = mydiv.offsetWidth, hh = mydiv.offsetHeight;
	let d = `M0 0 Q${ww/2} ${hh * 2 - 20} ${ww} 0`;
	ball.style.setProperty('offset-path', `path('${d}')`);
	mypath.setAttribute('d', d);
	len = mypath.getTotalLength(); //路径总长度
	//遍历路径长度每一个像素单位,储存其所对应的X坐标
	for(let j = 0; j < len; j++) {
		posAr.push(mypath.getPointAtLength(j).x);
	};
})();

以上匿名函数,关键在于基于 svg 的两个内置 API 函数,getTotalLength 和 getPointAtLength,前者获得 svg 内部元素的总长度,后者获取内部元素某个长度下的XY坐标,其值以对象 {x: n1, y: n2} 返回。

最后,通过 mypath 路径的点击事件,动态更改进度:

mypath.onclick = (e) => {
	for(let j = 0; j < len; j++) {
		if(e.offsetX <= posAr[j]) {
			mydiv.style.setProperty('--prog', j / len * 100 + '%');
			break;
		}
	}
};

这里,被点击对象(mypath)的 e.offsetX 指向点击处的X坐标值,如果该值在数组 posAr 遍历其元素时小于等于某个数组元素所记录的坐标值,则终止for循环(break),终止循环前给 CSS变量 --prog 赋值,这样,html 元素 ball 就会移动到这个 X 坐标值上。

效果:

前一篇: JS:同步、异步与回调
下一篇: 判断不规则svg路径被点击点的路径长度

发表评论:

  
 

评论列表 [0条]

Copyright © 2023 All Right Reserved 马黑PHP文章管理整站系统v1.8
联系我们: gxblk@163.com