You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于现有D3.js代码实现弧形矩形压力仪表盘?

目标压力图表

如何将现有代码改造成弧形排列矩形的压力图表?

我想实现这类压力图表:让矩形按弧形排列,并高亮最优刻度来表示数值。核心需求是添加矩形并在构建骨架时调整其角度。

我已经做了一个生成分散矩形并调整角度的Demo,但还没实现稳定的弧形排列效果(从左侧开始的弧形):

var svg = d3.select('body').append('svg').attr("height", 500).attr("width", 500).attr("class", "svger")

var rectbuf = 50;
var padd = 1;
  
for (let i = 0; i < 20; i++) {
  svg.append("rect")
    .attr("width", 30)
    .attr("height", 20)
    .attr("fill", "red")
    .attr("y", 20)
    .attr("x", rectbuf * 5)
    .attr("transform", "rotate("+((5+padd) *i)+")")
}

我还写了一段基础矩形绘制代码:

// 创建SVG元素:
var svg = d3.select("#rect").append("svg").attr("width", 800).attr("height", 200)

// 使用辅助函数添加路径
svg.append('rect')
  .attr('x', 10)
  .attr('y', 120)
  .attr('width', 600)
  .attr('height', 40)
  .attr('stroke', 'black')
  .attr('fill', '#69a3b2');

我目前已有一个仪表盘图表:
现有仪表盘图表

对应的React + D3代码如下:

import React from 'react'
import * as d3 from 'd3'

class GaugeChart extends React.Component {
  constructor(props) {
    super(props)
    this.myRef = React.createRef()
    this.state = {
      data: [],
      theme: this.props.theme
        ? this.props.theme
        : ['#bde0fe', '#2698f9', '#71bcfd', '#f1f8fe'],
    }
  }

  componentDidMount() {
    var $this = this.myRef.current

    d3.select($this).selectAll('svg').remove()

    const value = this.props.value
    const data = [
      {
        label: 'Completed',
        value: value,
      },
      {
        label: 'Remaining',
        value: 100 - value,
      },
    ]

    const width = parseInt(this.props.width, 10),
      height = parseInt(this.props.height, 10),
      radius = parseInt(this.props.r, 10),
      innerradius = parseInt(this.props.ir, 10)

    var color = d3.scaleOrdinal().range(this.state.theme)

    var arc = d3.arc().outerRadius(radius).innerRadius(innerradius)

    data.forEach(function (d) {
      d.total = +d.value
    })

    var pie = d3
      .pie()
      .startAngle(-90 * (Math.PI / 180))
      .endAngle(90 * (Math.PI / 180))
      .padAngle(0.02) // 扇区间留白
      .sort(null)
      .value(function (d) {
        return d.total
      })

    var svg = d3
      .select($this)
      .append('svg')
      .attr('width', width)
      .attr('height', height + 5)
      .append('g')
      .attr('class', 'piechart')
      .attr('transform', 'translate(' + width / 2 + ',' + height + ')')

    var segments = svg.append('g').attr('class', 'segments')

    var slices = segments
      .selectAll('.arc')
      .data(pie(data))
      .enter()
      .append('g')
      .attr('class', 'arc')

    slices
      .append('path')
      .attr('d', arc)
      .attr('fill', function (d, i) {
        return color(i)
      })
    /*.transition()
          .attrTween('d', function(d) {
            var i = d3.interpolate(d.startAngle + 0.1, d.endAngle);
            return function(t) {
              d.endAngle = i(t);
              return arc(d);
            }
          } )*/

    var arrow = svg.append('g').attr('transform', 'rotate( 0  )')

    arrow
      .append('path')
      .attr('fill', '#ef7e60')
      .attr(
        'd',
        `M -${innerradius - 5},0 -${innerradius - 12},-5 -${
          innerradius - 12
        },5`,
      ) // 绘制三角形

    var text = svg
      .append('text')
      .attr('text-anchor', 'middle')
      .attr('dy', 0)
      .attr('fill', '#ef7e60')

    function update(data) {
      text.text(`${Math.round(data[0].value)}%`) // 设置百分比文本

      arrow.transition().attr('transform', `rotate( ${data[0].value * 1.8}  )`) // 旋转至目标数值(对应180度的比例)
    }
    update(data)
  }

  render() {
    return <div ref={this.myRef} className="GaugeChart" />
  }
}
export default GaugeChart

后续更新的示例:

  • 12月2日最新示例
  • 12月3日最新示例

内容的提问来源于stack exchange,提问作者The Old County

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 05:35:03