代码之家  ›  专栏  ›  技术社区  ›  Radek Å váb

我的自定义css变量在css圆锥渐变函数中不起作用。如何修复?

  •  0
  • Radek Å váb  · 技术社区  · 3 年前

    因此,我试图构建这个自定义组件,以饼图的形式指示方向, 其中方向由图表的切片指示。

    My direction indicator

    我正在使用CSS来实现这一点,但我只是设法使切片成为静态的。我需要切片来改变基于组件道具的角度(开始和结束角度)。

    我遇到了将自定义css变量传递到元素和使css圆锥梯度函数与给定变量一起工作的问题。

    我不知道这是否重要,但就上下文而言,这是在React项目中,使用顺风顺水的MUI库。

    以下是我的组件:

    (注意我是如何使用普通文档设置元素属性的。这错了吗?感觉不对,但我没有找到其他方法,如何设置自定义css变量。)

    import "./DirectionIndicator.css";
    
    type Props = {
        startAngle: number
        endAngle: number
    }
    
    export default function DirectionIndicator(props: Props) {
    
        const element = document?.getElementById("pieSlice")
        if (element) {
            element.style.setProperty("--startAngle", props.startAngle.toString())
            element.style.setProperty("--endAngle", props.endAngle.toString())
        }
    
        return (
            <div className={"pieContainer"}>
                <div className={"pieBackground"}>
                    <div id="pieSlice" className={"slice"}/>
                    <div className={"innerCircle"}>
                        <div className={"content"}>
                            <b>N</b>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
    

    这是我的css:

    (请注意,在class.sice中,有两行包含圆锥梯度函数。它们是相同的,只是其中一行使用了--startAngle和--endAngle变量,而不是硬编码值。当我使用带硬编码值的行时,css运行良好。当我切换到带变量的行时时,slice不显示。我不明白怎么回事。我试图通过JS,并使用CSS文件中的默认值,但这两者都不起作用。指示器保持为空。)

    Empty direction indicator

    .pieContainer {
        height: var(--containerSize);
        position: relative;
        --containerSize: 100px;
        --innerCircleSize: 70px;
        --directionColor: #590;
        --innerCircleColor: #fff;
    }
    
    .pieBackground {
        position: absolute;
        width: var(--containerSize);
        height: var(--containerSize);
        border-radius: 100%;
        box-shadow: 0px 2px 5px rgba(0,0,0,0.5);
    }
    
    .slice {
        --startAngle: 0;
        --endAngle: 12;
        transition: all 1000ms;
        width: var(--containerSize);
        height: var(--containerSize);
        border-radius: 100%;
        /*background: conic-gradient(from var(--startAngle)deg, var(--directionColor) var(--endAngle)deg, transparent 1deg);*/
        background: conic-gradient(from 60deg, var(--directionColor) 120deg, transparent 1deg);
    }
    
    .innerCircle {
        position: absolute;
        width: var(--innerCircleSize);
        height: var(--innerCircleSize);
        background-color: var(--innerCircleColor);
        border-radius: 100%;
        top:  calc((var(--containerSize) - var(--innerCircleSize)) / 2);
        left:  calc((var(--containerSize) - var(--innerCircleSize)) / 2);
        box-shadow: 2px 5px 8px rgba(0,0,0,0.5) inset;
        color: black;
    }
    
    .innerCircle .content {
        position: absolute;
        display: block;
        width: var(--innerCircleSize);
        top: 5px;
        left: 0;
        text-align: center;
        font-size: 12px;
    }
    
    

    我将非常感谢任何关于如何解决这个问题的提示。非常感谢。

    1 回复  |  直到 3 年前
        1
  •  1
  •   Wongjn    3 年前

    (注意我是如何使用普通文档设置元素的属性的。这是错误的吗?)?

    这是错误的。你应该设置 style 属性属性。

    对于CSS,省略 deg CSS变量值的后缀。当CSS解析时,周围实际上总是有空格 var() 功能。因此 conic-gradient() 值将变为无效。相反,可以考虑 度 作为React代码中值的一部分:

    function DirectionIndicator(props) {
      const style = {
        '--startAngle': `${props.startAngle.toString()}deg`,
        '--endAngle': `${props.endAngle.toString()}deg`,
      };
    
      return (
        <div className={"pieContainer"}>
          <div className={"pieBackground"}>
            <div className={"slice"} style={style} />
            <div className={"innerCircle"}>
              <div className={"content"}>
                <b>N</b>
              </div>
            </div>
          </div>
        </div>
      )
    }
    
    function App() {
      return <DirectionIndicator startAngle={90} endAngle={135} />
    }
    
    ReactDOM.createRoot(document.getElementById('app')).render(<App/>);
    .pieContainer {
      height: var(--containerSize);
      position: relative;
      --containerSize: 100px;
      --innerCircleSize: 70px;
      --directionColor: #590;
      --innerCircleColor: #fff;
    }
    
    .pieBackground {
      position: absolute;
      width: var(--containerSize);
      height: var(--containerSize);
      border-radius: 100%;
      box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.5);
    }
    
    .slice {
      --startAngle: 0;
      --endAngle: 12;
      transition: all 1000ms;
      width: var(--containerSize);
      height: var(--containerSize);
      border-radius: 100%;
      background: conic-gradient(from var(--startAngle), var(--directionColor) var(--endAngle), transparent 1deg);
    }
    
    .innerCircle {
      position: absolute;
      width: var(--innerCircleSize);
      height: var(--innerCircleSize);
      background-color: var(--innerCircleColor);
      border-radius: 100%;
      top: calc((var(--containerSize) - var(--innerCircleSize)) / 2);
      left: calc((var(--containerSize) - var(--innerCircleSize)) / 2);
      box-shadow: 2px 5px 8px rgba(0, 0, 0, 0.5) inset;
      color: black;
    }
    
    .innerCircle .content {
      position: absolute;
      display: block;
      width: var(--innerCircleSize);
      top: 5px;
      left: 0;
      text-align: center;
      font-size: 12px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    
    <div id="app"></div>