React SVG ring

Time:2020-1-9

ReactringSemiCircle

React SVG ring

Code

import React from "react";

class SemiCircle extends React.Component {
  constructor(props) {
    super(props);
  }

  polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
    var angleInRadians = ((angleInDegrees - 180) * Math.PI) / 180;

    return {
      x: centerX + radius * Math.cos(angleInRadians),
      y: centerY + radius * Math.sin(angleInRadians)
    };
  };

  describeArc = (x, y, radius, startAngle, endAngle) => {
    var start = this.polarToCartesian(x, y, radius, endAngle);
    var end = this.polarToCartesian(x, y, radius, startAngle);
    var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
    var d = [
      "M",
      start.x,
      start.y,
      "A",
      radius,
      radius,
      0,
      largeArcFlag,
      0,
      end.x,
      end.y
    ].join(" ");
    return d;
  };
  render() {
    const { size, scoreSafe, strokeColor, safeText } = this.props;
    const gradient = strokeColor => {
      if (!strokeColor) return;
      let arr = strokeColor.map((item, index) => {
        let { offset, color, opacity } = item;
        return (
          <stop
            offset={offset + "%"}
            key={index}
            style={{ stopColor: color, stopOpacity: opacity }}
          />
        );
      });
      return (
        <defs>
          <linearGradient
            id="sanyuelanvGradient"
            x1="0%"
            y1="0%"
            x2={this.gradientDirection == "horizontal" ? "0%" : "100%"}
            y2={this.gradientDirection == "vertical" ? "0%" : "100%"}
          >
            {arr}
          </linearGradient>
        </defs>
      );
    };
    return (
      <div className="u-tc">
        <svg
          viewBox={"0 0 " + 128 + " " + 128}
          width={size}
          height={size}
          version="1.1"
        >
          {gradient(strokeColor)}
          <path
            id="arc1"
            fill="none"
            stroke="#F6F6FB"
            d={this.describeArc(64, 64, 54, -45, 225)}
            strokeWidth="10"
            strokeLinecap="round"
          />
          <path
            id="arc2"
            fill="none"
            d={this.describeArc(64, 64, 54, -45, scoreSafe)}
            style={{
              strokeLinecap: "round",
              stroke: "url('#sanyuelanvGradient')",
              fill: "transparent",
              strokeWidth: 10
            }}
          />

          <text
            x={"50%"}
            y={"35%"}
            dy={20}
            style={{
              fontSize: "20px",
              fill: "url('#sanyuelanvGradient')",
              textAnchor: "middle"
            }}
          >
            {localTranslate(safeText)}
          </text>
          <text
            x={"50%"}
            y={"55%"}
            dy={20}
            style={{
              fontSize: "12px",
              fill: "#6b798e",
              textAnchor: "middle"
            }}
          >
            {localTranslate("USERINFO142")}
          </text>
        </svg>
      </div>
    );
  }
}

export default SemiCircle;

// example
 <SemiCircle
    size={128}
    scoreSafe={scoreSafe * 37.5}
    strokeColor={strokeColor[scoreSafe]}
    safeText={safeText[scoreSafe - 1]}
    gradientDirection={"horizontal"}
></SemiCircle>