javascript - 带百分比的虚线圆条

标签 javascript html css reactjs

我正在尝试制作一个带有虚线的圆形进度条。我以编程方式创建 stroke-dasharraystroke-dashoffset 以绘制带百分比的圆。

我需要绘制如下所示的虚线圆圈,而不是实心圆圈:

dashed line

我无法将实心圆圈更改为虚线圆圈。我是否遗漏了什么,或者我是否需要更改我的逻辑来绘制虚线圆圈?

https://jsfiddle.net/6mu97jyL/

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`}
            transform={`rotate(-90 ${this.props.sqSize / 2} ${this.props.sqSize / 2})`}
            style={{
              strokeDasharray: dashArray,
              strokeDashoffset: dashOffset
            }} />
      </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: #ddd;
}

.circle-progress {
  stroke: #F99123;
  stroke-linecap: round;
  stroke-linejoin: round;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>

<div class="container">
  <div class="text-center" id="app">
  </div>

</div>

最佳答案

不确定这是否在您要寻找的范围内。 (下面的完整片段/演示)

我不是这方面的专家,所以可能还有另一种选择(比如两个具有不同样式的半圆)——但这里基本上要做的是在实心圆上放置另一个圆,并确保它有与页面相同的笔触颜色。然后,这将掩盖后面圆圈的间隙(基本上隐藏圆圈的一部分)。

          <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;
}

并删除

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

根据您的需要进行一些小的调整,希望您能做到!

Preview of result

如果您用另一种背景颜色查看该应用,变化可能会更加明显。

With dark background

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: #ddd;
}

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

关于javascript - 带百分比的虚线圆条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55455050/

相关文章:

javascript - 当函数和选择器不在一起时使用 "this"

javascript - JQuery 与 HTML 图像映射

javascript - mootools 按文档 ID 加载

php - 插值是 LESS 变量

javascript - bootstrap slider /旋转木马如何在 div 上最大化?

Javascript:函数中的变量赋值

javascript - 修改没有ID引用的对象的CSS

javascript - 当提供者重新渲染时消费者重新渲染

html - div 占用新的一行而不只是占用更多的垂直空间

jquery - 打开对话时如何隐藏对话背景?