【问题标题】:Donut Chart connect all arcs甜甜圈图连接所有弧线
【发布时间】:2023-02-09 00:08:38
【问题描述】:

使用圆圈绘制 svg 圆环图。我需要连接所有弧线,而不是它们之间的间隙。是否可以? 我设置了 stroke-dasharray="${item.percent} 100" 但它不起作用。我也设置了 pathLength="${100+0*arr.length}" 但它也不起作用。看下面的代码

var DonutSlice = [{
      id: 1,
      percent: 60,
      color: 'DarkSeaGreen',
      label: 'Slice 1'
    },
    {
      id: 2,
      percent: 30,
      color: 'DarkOrchid',
      label: 'Slice 2'
    },
    {
      id: 3,
      percent: 10,
      color: 'Tomato',
      label: 'Slice 3'
    }
    ];

    var circlecontainer = document.getElementById('circlecontainer');
    var output = document.getElementById('output');

    circlecontainer.innerHTML = DonutSlice.map((item, i, arr) => {
      let offset = 1 * i + arr.filter((item, j) => j < i)
        .reduce((total, item) => total + item.percent, 0);
      return `<circle data-id="${item.id}" stroke="${item.color}"
          cx="80" cy="80" r="79" class="slice"
          pathLength="${100+0*arr.length}"
          stroke-dasharray="${item.percent} 100"
          stroke-dashoffset="-${offset}" />`;
    }).join('');

    circlecontainer.addEventListener('mouseover', e => {
      let slice = e.target.closest('.slice');
      if (slice) {
        item = DonutSlice.find(item => item.id == parseInt(slice.dataset.id));
        output.innerHTML = `${item.label} was clicked`;
      }
    });
  .slice {
    /* stroke-linecap: round; */
    stroke-width: 15;
    fill: none;
    cursor: pointer;
  }

  p#output {
    text-align: center;
  }
  <div style="width: 200px">
    <svg class="svg2" width="174" height="174" preserveAspectRatio="xMinYMin meet"
        xmlns="http://www.w3.org/2000/svg" viewBox="0 0 174 174" version="1.1">
      <circle fill="#000000" cx="87" cy="87" r="87" />
      <g id="circlecontainer" transform="rotate(0 0 0)"></g>
    </svg>
    <p id="output"></p>
  </div>

【问题讨论】:

    标签: svg charts


    【解决方案1】:

    我不喜欢使用 stroke-dashoffset,而是使用 transform rotate。所以偏移值需要是度数。我在计算中添加了/ 100 * 360

    如果您使用 circlecontainer 组来定位图表,您可以跳过 circle 元素上的 cx 和 cy 属性。

    var DonutSlice = [{
          id: 1,
          percent: 60,
          color: 'DarkSeaGreen',
          label: 'Slice 1'
        },
        {
          id: 2,
          percent: 30,
          color: 'DarkOrchid',
          label: 'Slice 2'
        },
        {
          id: 3,
          percent: 10,
          color: 'Tomato',
          label: 'Slice 3'
        }
        ];
    
        var circlecontainer = document.getElementById('circlecontainer');
        var output = document.getElementById('output');
    
        circlecontainer.innerHTML = DonutSlice.map((item, i, arr) => {
          let offset = arr.filter((item, j) => j < i)
            .reduce((total, item) => total + item.percent, 0) / 100 * 360;
          return `<circle data-id="${item.id}" stroke="${item.color}"
              r="72" class="slice"
              pathLength="100"
              stroke-dasharray="${item.percent} 100"
              transform="rotate(${offset})" />`;
        }).join('');
    
        circlecontainer.addEventListener('mouseover', e => {
          let slice = e.target.closest('.slice');
          if (slice) {
            item = DonutSlice.find(item => item.id == parseInt(slice.dataset.id));
            output.innerHTML = `${item.label} was clicked`;
          }
        });
    .slice {
        /* stroke-linecap: round; */
        stroke-width: 16;
        fill: none;
        cursor: pointer;
      }
    
      p#output {
        text-align: center;
      }
    <div style="width: 200px">
        <svg class="svg2" preserveAspectRatio="xMinYMin meet"
            xmlns="http://www.w3.org/2000/svg" viewBox="0 0 164 164">
          <circle fill="#000000" cx="84" cy="84" r="80" />
          <g id="circlecontainer" transform="translate(80 80) rotate(-90)"></g>
        </svg>
        <p id="output"></p>
      </div>

    【讨论】:

      【解决方案2】:

      您的偏移量计算增加了一个差距。
      改成(删除多余的1 * i +):

      let offset = arr.filter((item, j) => j < i)
              .reduce((total, item) => total + item.percent, 0);
      

      var DonutSlice = [{
          id: 1,
          percent: 60,
          color: 'DarkSeaGreen',
          label: 'Slice 1'
        },
        {
          id: 2,
          percent: 30,
          color: 'DarkOrchid',
          label: 'Slice 2'
        },
        {
          id: 3,
          percent: 10,
          color: 'Tomato',
          label: 'Slice 3'
        }
      ];
      
      var circlecontainer = document.getElementById('circlecontainer');
      var output = document.getElementById('output');
      
      circlecontainer.innerHTML = DonutSlice.map((item, i, arr) => {
        let offset = arr.filter((item, j) => j < i)
          .reduce((total, item) => total + item.percent, 0);
      
        return `<circle data-id="${item.id}" stroke="${item.color}"
                cx="80" cy="80" r="79" class="slice"
                pathLength="${100+0*arr.length}"
                stroke-dasharray="${item.percent} 100"
                stroke-dashoffset="-${offset}" />`;
      }).join('');
      
      circlecontainer.addEventListener('mouseover', e => {
        let slice = e.target.closest('.slice');
        if (slice) {
          item = DonutSlice.find(item => item.id == parseInt(slice.dataset.id));
          output.innerHTML = `${item.label} was clicked`;
        }
      });
      .slice {
        /* stroke-linecap: round; */
        stroke-width: 15;
        fill: none;
        cursor: pointer;
      }
      
      p#output {
        text-align: center;
      }
      <div style="width: 200px">
        <svg class="svg2" width="174" height="174" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 174 174" version="1.1">
          <circle fill="#000000" cx="87" cy="87" r="87" />
          <g id="circlecontainer" transform="rotate(0 0 0)"></g>
        </svg>
        <p id="output"></p>
      </div>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多