SVG实现画弧线进度条
先看效果图
关键API
svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
画一段到(x,y)的椭圆弧. 椭圆弧的 x, y 轴半径分别为 rx,ry. 椭圆相对于 x 轴旋转 x-axis-rotation 度.
large-arc=0表明弧线小于180读, large-arc=1表示弧线大于180度. sweep=0表明弧线逆时针旋转,
sweep=1表明弧线顺时间旋转.
相应知识点
角度换算弧度: 弧度的计算公式为: 2*π/360*角度
三角形的正玄、余弦: 数学公用库Math提供正玄函数sin(x)和余弦函数cos(x) 注意:函数中的X 都是指的“弧度”而非“角度
SVG: SVG相关知识
应用:如何得到圆上每个点的坐标?
解决思路:根据三角形的正玄、余弦来得值;
假设一个圆的圆心坐标是(a,b),半径为r,
则圆上每个点的X坐标=a + Math.sin(2*Math.PI / 360) * r ;Y坐标=b + Math.cos(2*Math.PI / 360) * r ;
标题实
现
/**
* 传入相应参数返回圆形制定半径的弧度坐标
* @param {*} x 中心点X坐标
* @param {*} y 中心点y坐标
* @param {*} R 圆半径
* @param {*} a 角度
*/
function coordMap(x, y, R, a) {
var ta = (360 - a) * Math.PI / 180,
tx, ty;
tx = R * Math.cos(ta); // 角度邻边
ty = R * Math.sin(ta); // 角度的对边
return {
x: x + tx,
y: y - ty // 注意此处是“-”号,因为我们要得到的Y是相对于(0,0)而言的。
}
}
/**
* 创建弧线
* @param {*} data.startAngle 开始角度
* @param {*} data.endAngle 结束角度
* @param {*} data.R 圆半径
* @param {*} data.x 中心点X坐标
* @param {*} data.y 中心点y坐标
* @param {*} data.color 边框颜色 默认#CCC
* @param {*} data.strokeWidth 边框宽度 默认1
* @param {*} data.strokelinecap 不同类型的路径的开始结束点 可选值 butt round square 默认butt
* @param {*} data.strokeDasharray 虚线设置 它是一个<length>和<percentage>数列,数与数之间用逗号或者
* 空白隔开,指定短划线和缺口的长度。如果提供了奇数个值,则这个值的数列重复一次,从而变成偶数个值。因此,5,3,2等同于5,3,2,5,3,2。
* @param {*} data.transform CSS3旋转设置
*/
function drawSVG(data) {
var path,
// 起点坐标
s = new coordMap(data.x, data.y, data.R, data.startAngle),
// 结束坐标
e = new coordMap(data.x, data.y, data.R, data.endAngle),
// 创建弧线路径
tpath = document.createElementNS("http://www.w3.org/2000/svg", "path");
// 画一段到(x,y)的椭圆弧. 椭圆弧的 x, y 轴半径分别为 rx,ry. 椭圆相对于 x 轴旋转 x-axis-rotation 度. large-arc=0表明弧线小于180读, large-arc=1表示弧线大于180度. sweep=0表明弧线逆时针旋转, sweep=1表明弧线顺时间旋转.
// svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
path = 'M' + s.x + ',' + s.y + 'A' + data.R + ',' + data.R + ',0,' + (+(data.endAngle - data.startAngle > 180)) + ',1,' + e.x + ',' + e.y;
// 设置路径
tpath.setAttribute('d', path);
// 去掉填充
tpath.setAttribute("fill", "none");
// 设置颜色
tpath.setAttribute('stroke', data.color || '#CCC');
// 边线宽度
tpath.setAttribute('stroke-width', data.strokeWidth || 1);
data.strokelinecap ? tpath.setAttribute('stroke-linecap', data.strokelinecap) : '';
data.strokeDasharray ? tpath.setAttribute('stroke-dasharray', data.strokeDasharray) : '';
data.transform ? tpath.setAttribute('transform', data.transform) : '';
return tpath;
}
/**
* 画进度条
* @param {*} $select 容器
* @param {*} size 多少步 共100步
*/
function svgView($select, size) {
var size = size,
// 创建SVG
svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("version", "1.1"); // IE9+ support SVG 1.1 version
svg.setAttribute("width", "240px");
svg.setAttribute("height", "240px");
// 画底线并加入SVG中
svg.appendChild(new drawSVG({
startAngle: 45,
endAngle: 315,
x: 120,
y: 130,
R: 90,
strokelinecap: 'round',
color: '#FFF',
strokeWidth: 10,
transform: 'rotate(-270, 120, 130)'
}));
// 步长
var step = (315 - 45) / 100,
i = 1;
// 画第一步并加入SVG中
svg.appendChild(new drawSVG({
startAngle: 45,
endAngle: 45 + step * i,
x: 120,
y: 130,
R: 90,
strokelinecap: 'round',
strokeWidth: 10,
color: '#ffe400',
transform: 'rotate(-270, 120, 130)'
}));
// 写入页面
document.querySelector($select).appendChild(svg);
// 通过设置时间循环步
var tc = setInterval(function() {
console.log(i, '----', 45 + step * i, '-----', 315);
// 创建新的弧线 替换进度弧线
svg.replaceChild(new drawSVG({
startAngle: 45,
endAngle: 45 + step * i,
x: 120,
y: 130,
R: 90,
strokelinecap: 'round',
strokeWidth: 10,
color: '#ffe400',
transform: 'rotate(-270, 120, 130)'
}), svg.lastChild);
i++;
if (i > size) {
clearInterval(tc);
}
}, 20);
};
svgView('#svgView', 80);