reactjschartsgauge

React Speedometer or gauge. How to created labelled speedometer in react?


I have used this library to draw speedometer. https://github.com/palerdot/react-d3-speedometer I want to set label on each segment. Please help if there is any other library to draw chart like this. enter image description here


Solution

  • According to the answer on that issue it's not doable: Is it possible to set label on segments

    Currently the labels are automatically calculated based on maxValue, 'minValue' and segments. This may not be possible at all, as per the library functionality, there will be 5 values for your chart instead of 4 you have mentioned. I'm afraid this is not possible at all as far as I see. So I'm closing this issue.

    There are many libraries that draw charts but each of them comes with its limitations, for my projects I ended up implementing the charts by myself, it's not so hard and lets you do exactly what you need without suffering the quirks.

    Here is some code I extracted from my ReactPie component, it draws a PieSegment so you could use that to create a similar result than the gauge pretty easily. You can try it in that pen: https://codepen.io/leefsmp/pen/dJjpXx

    class ReactPieSegment extends React.Component {
    
        constructor (props) {
    
          super (props)
        }
    
        generatePathDef(centre, rIn, rOut, start, delta) {
    
          const endRad = start + delta
    
          const startOut = {
            x: centre.x + rOut * Math.cos(start),
            y: centre.y + rOut * Math.sin(start)
          }
    
          const endOut = {
            x: centre.x + rOut * Math.cos(endRad),
            y: centre.y + rOut * Math.sin(endRad)
          }
    
          const startIn = {
            x: centre.x + rIn * Math.cos(endRad),
            y: centre.y + rIn * Math.sin(endRad)
          };
    
          var endIn = {
            x: centre.x + rIn * Math.cos(start),
            y: centre.y + rIn * Math.sin(start)
          }
    
          const largeArc = delta > Math.PI ? 1 : 0
    
          return (
            `M${startOut.x},${startOut.y}` +
            ` A${rOut},${rOut} 0 ` +
            `${largeArc},1 ${endOut.x},${endOut.y}` +
            ` L${startIn.x},${startIn.y}` +
            ` A${rIn},${rIn} 0 ` +
            `${largeArc},0 ${endIn.x},${endIn.y}` +
            ` L${startOut.x},${startOut.y} Z`
          )
        }
    
        render () {
    
          const {
            fillColor, strokeColor,
            start, delta,
            rIn, rOut,
            centre
          } = this.props
    
          const pathDef = this.generatePathDef(
            centre, rIn, rOut, start, delta)
    
          const labelDist = rIn + 1.2 * (rOut-rIn)
    
          const labelRad = start + 0.5 * delta
    
          const labelPos = {
            x: centre.x + labelDist * Math.cos (labelRad) - 10,
            y: centre.y + labelDist * Math.sin (labelRad)
          }
    
          const labelStyle = {
            transform: `translate(${labelPos.x}px, ${labelPos.y}px)`
          }
    
          return (
            <g className='react-pie-segment'>
              <path
                stroke={strokeColor}
                fill={fillColor}
                d={pathDef}
              />
              <text style={labelStyle}>
                {this.props.label}
              </text>
            </g>
          )
        }
      }
    
    
      class Demo extends React.Component {
    
        constructor (props) {
          super (props)
        }
    
        render() {
          return (
            <div className="demo">
              <svg>
              <ReactPieSegment
                centre={{x:150, y:150}}
                strokeColor={"green"}
                fillColor={"green"}
                delta={Math.PI/4}
                start={Math.PI}
                label={"label 1"}
                rOut={90}
                rIn={50}
              />
              <ReactPieSegment
                centre={{x:150, y:150}}
                strokeColor={"yellow"}
                fillColor={"yellow"}
                delta={Math.PI/4}
                start={5*Math.PI/4}
                label={"label 2"}
                rOut={90}
                rIn={50}
              /> 
              <ReactPieSegment
                centre={{x:150, y:150}}
                strokeColor={"orange"}
                fillColor={"orange"}
                delta={Math.PI/4}
                start={6*Math.PI/4}
                label={"label 3"}
                rOut={90}
                rIn={50}
              /> 
              <ReactPieSegment
                centre={{x:150, y:150}}
                strokeColor={"red"}
                fillColor={"red"}
                delta={Math.PI/4}
                start={7*Math.PI/4}
                label={"label 4"}
                rOut={90}
                rIn={50}
              /> 
              </svg>  
            </div>
          )
        }
      }
    
      const root = document.getElementById('root')
    
      ReactDOM.render(<Demo/>, root)  
    

    enter image description here