Dashed Circular Bar with Percentage

前端 未结 1 1776
半阙折子戏
半阙折子戏 2021-01-28 13:35

I am trying to make a circular progress bar with dashed line. I programmatically create stroke-dasharray and stroke-dashoffset to draw a circle with pe

相关标签:
1条回答
  • 2021-01-28 14:00

    Not sure if this is somewhat in the range of what you are looking for. ( full snippet / demo below)

    Im not an expert on this subject, so there might be another option (like two half circles with different styling) - but what is basically done here is to lay another circle on top of the solid circle, and make sure it has the same stroke color as the page. This will then mask over gaps of the circle behind, (basically hide parts of the circle).

              <circle
                className="circle-dashes"
                cx={this.props.sqSize / 2}
                cy={this.props.sqSize / 2}
                r={radius}
                strokeWidth={`${this.props.strokeWidth}px`}
                style={{
                  strokeDasharray: "5 10" // Adjust the spacing here
                }} />
    

    css:

    .circle-dashes {
      stroke: #FFF;
      fill: none;
    }
    

    and remove

      stroke-linecap: round;
      stroke-linejoin: round;
    

    A few minor tweaks to fit your need, and hopefully you got it!

    If you take a look at the app with another background color, the changes might be more obvious.

    class CircularProgressBar extends React.Component {
      constructor(props) {
        super(props);
        this.state = {};
      }
    
      render() {
        // Size of the enclosing square
        const sqSize = this.props.sqSize;
        // SVG centers the stroke width on the radius, subtract out so circle fits in square
        const radius = (this.props.sqSize - this.props.strokeWidth) / 2;
        // Enclose cicle in a circumscribing square
        const viewBox = `0 0 ${sqSize} ${sqSize}`;
        // Arc length at 100% coverage is the circle circumference
        const dashArray = radius * Math.PI * 2;
        // Scale 100% coverage overlay with the actual percent
        const dashOffset = dashArray - dashArray * this.props.percentage / 100;
    
        return (
          <svg
              width={this.props.sqSize}
              height={this.props.sqSize}
              viewBox={viewBox}>
              <circle
                className="circle-background"
                cx={this.props.sqSize / 2}
                cy={this.props.sqSize / 2}
                r={radius}
                strokeWidth={`${this.props.strokeWidth}px`} />
              <circle
                className="circle-progress"
                cx={this.props.sqSize / 2}
                cy={this.props.sqSize / 2}
                r={radius}
                strokeWidth={`${this.props.strokeWidth}px`}
                // Start progress marker at 12 O'Clock
                transform={`rotate(-90 ${this.props.sqSize / 2} ${this.props.sqSize / 2})`}
                style={{
                  strokeDasharray: dashArray,
                  strokeDashoffset: dashOffset
                }} />
                
                <circle
                className="circle-dashes"
                cx={this.props.sqSize / 2}
                cy={this.props.sqSize / 2}
                r={radius}
                strokeWidth={`${this.props.strokeWidth}px`}
                style={{
                  strokeDasharray: "5 10"
                }} />
          </svg>
        );
      }
    }
    
    CircularProgressBar.defaultProps = {
      sqSize: 200,
      percentage: 25,
      strokeWidth: 10
    };
    
    class App extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          percentage: 25
        };
    
        this.handleChangeEvent = this.handleChangeEvent.bind(this);
      }
    
      handleChangeEvent(event) {
        this.setState({
          percentage: event.target.value
        });
      }
    
      render() {
        return (
          <div>
              <CircularProgressBar
                strokeWidth="10"
                sqSize="200"
                percentage={this.state.percentage}/>
              <div>
                <input 
                  id="progressInput" 
                  type="range" 
                  min="0" 
                  max="100" 
                  step="1"
                  value={this.state.percentage}
                  onChange={this.handleChangeEvent}/>
              </div>
            </div>
        );
      }
    }
    
    ReactDOM.render(
      <App/>,
      document.getElementById('app')
    );
    #app {
      margin-top: 40px;
      margin-left: 50px;
    }
    
    #progressInput {
      margin: 20px auto;
      width: 30%;
    }
    
    .circle-background,
    .circle-progress {
      fill: none;
    }
    
    .circle-background {
      stroke: #ffffd;
    }
    
    .circle-dashes {
      stroke: #fff;
      fill: none;
    }
    
    .circle-progress {
      stroke: #F99123;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div class="container">
      <div class="text-center" id="app">
      </div>
    		
    </div>

    0 讨论(0)
提交回复
热议问题