【问题标题】:Best way to add conic gradient to the circle in SVG向 SVG 中的圆添加圆锥渐变的最佳方法
【发布时间】:2023-01-30 07:14:49
【问题描述】:

我在 React 组件中有一个类似甜甜圈的圆圈(进度圆圈),我想为其添加圆锥渐变。怎么做?

我知道在 SVG 中我们不能使用圆锥渐变。我认为这可以通过使用带有渐变的添加 css 的掩码和通常的块来完成,但不确定如何正确执行。

现在它看起来像这样:

反应组件:

import React from 'react';

import { Box, Text } from '@chakra-ui/react';

const GradientProgress = ({ modifier, score, size, strokeWidth }) => {
  const DIAMETER = 51;
  const WIDTH = DIAMETER + strokeWidth;

  const RADIUS = DIAMETER / 2;
  const CIRC = 2 * Math.PI * RADIUS;

  const foregroundCirc = (CIRC * score) / 100;
  const frontCirc = (CIRC * modifier) / 100;

  return (
    <Box
      position='relative'
      style={{ width: `${size}px`, height: `${size}px` }}
      sx={{
        circle: {
          background:
            'conic-gradient(from 270deg, #ff4800 10%, #dfd902 35%, #20dc68, #0092f4, #da54d8 72% 75%, #ff4800 95%)',
        },
      }}
    >
      <svg
        className='donut'
        transform='rotate(-90)'
        viewBox={`0 0 ${WIDTH} ${WIDTH}`}
      >
        <circle
          className='donut-ring'
          cx={RADIUS + strokeWidth / 2}
          cy={RADIUS + strokeWidth / 2}
          fill='transparent'
          pathLength={CIRC}
          r={RADIUS}
          stroke='#d2d3d4'
          strokeWidth={strokeWidth}
        />

        <circle
          className='donut-segment'
          cx={RADIUS + strokeWidth / 2}
          cy={RADIUS + strokeWidth / 2}
          fill='transparent'
          opacity={0.5}
          pathLength={CIRC}
          r={RADIUS}
          stroke='green'
          strokeDasharray={`${frontCirc} ${CIRC - frontCirc}`}
          strokeDashoffset={0}
          strokeLinecap='round'
          strokeWidth={strokeWidth}
        />

        <circle
          className='donut-segment'
          cx={RADIUS + strokeWidth / 2}
          cy={RADIUS + strokeWidth / 2}
          fill='transparent'
          pathLength={CIRC}
          r={RADIUS}
          stroke='red'
          strokeDasharray={`${foregroundCirc} ${CIRC - foregroundCirc}`}
          strokeDashoffset={0}
          strokeLinecap='round'
          strokeWidth={strokeWidth}
        />
      </svg>
      <Text>{modifier || score}</Text>
    </Box>
  );
};

export default GradientProgress;

【问题讨论】:

    标签: reactjs svg conic-gradients


    【解决方案1】:

    您可以通过将圆圈转换为掩码并将其分配给 foreignObject 来实现此目的,该对象包含一个具有锥形渐变样式的 div。

    这是它如何工作的示例:

    const control = document.getElementById('control');
    const circle = document.getElementsByClassName('circle')[0];
    const bg = document.getElementsByClassName('bg')[0];
    
    control.addEventListener('input', function(event) {
      circle.style.setProperty('--progress', event.target.valueAsNumber);
      const deg = (event.target.valueAsNumber/100) * 360;
      bg.style.setProperty('background', `conic-gradient(#00bcd4, #ffeb3b ${deg}deg)`);
    });
    .root {
      width: 400px;
      height: 400px;
      text-align: center;
    }
    
    svg {
    
    }
    
    .circle {
      stroke: white;
      stroke-width: 3;
      stroke-linecap: round;
      stroke-dasharray: calc((2 * 3.14) * 45);
      stroke-dashoffset: calc((2 * 3.14 * 45) * (1 - calc(var(--progress, 50) / 100)));
      transform-origin: 50% 50%;
      transform: rotate(-87deg);
    }
    
    .bg {
      background: conic-gradient(#00bcd4, #ffeb3b 180deg);
      width: 100%;
      height: 100%;
    }
    <div class='wrap'>
    
      <div class='root'>
        <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
          <defs>
            <mask id="mask">
              <circle class='circle' cx="50" cy="50" r="45" stroke='white' stroke-width='3' fill='none' />
            </mask>
          </defs>
          <foreignObject x="0" y="0" width="100" height="100" mask="url(#mask)">
            <div class='bg'></div>
          </foreignObject>
        </svg>
        <input id="control" type="range" value="60" />
      </div>
    
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      • 2022-01-12
      • 2020-11-21
      相关资源
      最近更新 更多