【H5】 svg画扇形饼图

【H5】 svg画扇形饼图

效果图如下:

【H5】 svg画扇形饼图_第1张图片

封装代码如下:

代码内有详细注解哦!


<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>Documenttitle>
  <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标签 

    //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>

你可能感兴趣的:(HTML5,svg)