【H5】 svg画扇形饼图
效果图如下:
封装代码如下:
代码内有详细注解哦!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {margin: 0;padding: 0;}
#wrap {
width: 300px;
height: 300px;
/* border:1px solid #000; */
margin: 50px auto 0;
}
</style>
</head>
<body>
<div id="wrap">
<svg id='svg' xmlns="http://www.w3.org/2000/svg" width='100%' height='100%'>
</svg>
</div>
<script>
let svg = document.getElementById('svg');
//creatTagEle是定义的一个生成path标签的方法
//6.传值:tag为path标签 tagAttr:标签的样式属性(fill填充颜色,d线路样式)
function creatTagEle(tag, tagAttr) {
let svgNS = "http://www.w3.org/2000/svg"; //svg的规则
//createElementNS()方法创建带有指定命名空间的元素节点
// svgNS是规定svg的规则 tag为path标签
let oTag = document.createElementNS(svgNS, tag)
//for...in...遍历到里面的标签属性
for (let attr in tagAttr) {
//在path标签里设定样式:attr键 与 tagAttr[attr]键的值
oTag.setAttribute(attr, tagAttr[attr])
}
return oTag;
}
//oTag就是一个path标签 <path fill="#24acf2" d="M270 150A120 120 0 0 1 224 243 L193 204 70 0 0 0 220 150"></path>
//2.主执行方法 (扇形百分百数组,伞形颜色数组,运动时间ms)
function move(num, color, time) {
let nowTime = new Date(); //获取初始时间
//外边的半径
let outR = 120;
//内边的半径
let inneR = 70;
//中心点( centerX,centerY )
let centerX = 150;
let centerY = 150;
let n = 0; //定时器计入执行的次数
//下面的3→4→5→6→7一直循环执行 直到prop=1才结束
let timer = setInterval(function () {
let prop = (new Date() - nowTime) / time; // (当前时间-初始时间)/1000ms
if (prop >= 1) { //设置一秒钟后动画完成
prop = 1
clearInterval(timer) //清除定时器 清除定时器后下面任然会执行一遍
}
//一共运动的角度
let angleNum = 0;
//动画的起始坐标,需要用数组来进行取值;
let outXY = [{ x: 270, y: 150 }];
let inneXY = [{ x: 220, y: 150 }];
//3.计算外圆与内圆运动到的坐标;存储到 outXY 与 inneXY数组内
for (let i = 0; i < num.length; i++) {
//需要得出每一部分所占的比例值;
let aNum = num[i] / 100 * 360; //计算多少度
angleNum += aNum; // 每一份加起来的最后总的结果 等于360
if (i == num.length - 1) {angleNum = 360;} //最后保证圆为360度
//外圆的坐标 当prop等于1,每个扇形区块才能达到100%的显示 从而形成一个饼图
let outX = Math.cos(angleNum * prop * Math.PI / 180) * outR + centerX;
let outY = Math.sin(angleNum * prop * Math.PI / 180) * outR + centerY;
outXY.push({ x: outX, y: outY }) //把每一个点都放到数组里边去;
//内圆的坐标
let inneX = Math.cos(angleNum * prop * Math.PI / 180) * inneR + centerX;
let inneY = Math.sin(angleNum * prop * Math.PI / 180) * inneR + centerY;
inneXY.push({ x: inneX, y: inneY }) //把每一个点都放到数组里边去;
}
// console.log(outXY); 由这里打印可以看出移动点(x,y)都是慢慢变"大", 所以每个扇形区面积都是慢慢变大的
//4.画上去 通过每个扇形区运动的(x,y)点 填充对应区域的颜色
for (let i = 0; i < outXY.length - 1; i++) { //每一次for循环填充一个扇形区
//5.生成path标签
let oPath = creatTagEle('path', {
fill: color[i],//渲染颜色值;
//填充一个扇形区的外弧与内弧
d: `M${outXY[i].x} ${outXY[i].y}A${outR} ${outR} 0 0 1 ${outXY[i + 1].x} ${outXY[i + 1].y}L${inneXY[i + 1].x} ${inneXY[i + 1].y}A${inneR} ${inneR} 0 0 0 ${inneXY[i].x} ${inneXY[i].y}`
});
//7.将创建的oPath标签添加到画布上
svg.appendChild(oPath) //一轮for完毕后填充了所有的扇形区 但每个扇形区面积并未达到100% 最后一次填充才为100%
}
//将前面绘画的path删除
if(n++){
for(let i=0; i<num.length; i++){
console.log(1)
svg.removeChild(svg.childNodes[1]) //删除
}
}
}, 1000 / 60); //一秒钟60帧为流畅
}
//1.程序入口 参数一为饼图每一部分的百分百 参数二为颜色 (两个数组长度必须对应相等) 参数3为动画执行的时间
move(
[15.5, 32.11, 22.22, 10, 13.14, 7.03],
["#24acf2", "#dd5044", "yellow", "orange", "#a83d34","purple"],
2000
)
</script>
</body>
</html>