Effect:
image.png
Without svg, almost always need to have additional element occlusion to achieve, but there is no way to achieve the translucent ring effect. Pure svg drawing, widening the stroke width of the path visually presents a ring. (Did you forget about the trigonometric functions in high school?)

Take a circle with a radius of 32 as an example. Note that the brush positioning datum is at the center. The size of the viewbox needs to be adjusted to avoid incomplete circle display. (Copy for personal use)

import { createElement, useState, useEffect, useRef, useCallback } from 'rax';

interface IProps {
  time: number; // milliseconds
  style?: Rax.CSSProperties;
  onEnd?: () => void;
}
export const CircleTimer = (props: IProps) => {
  const curT = useRef(0);
  const timer = useRef<number>();
  const [point, setPoint] = useState('32 0');

  useEffect(() => {
    return () => {
      if (timer.current) {
        clearTimeout(timer.current);
      }
    };
  }, []);

  const calPoint = useCallback(() => {
    if (curT.current >= props.time) {
      props.onEnd && props.onEnd();
      return;
    }

    timer.current = setTimeout(() => {
      curT.current += 50;
      const deg = (curT.current / props.time) * Math.PI * 2;
      const x = 32 + 32 * Math.sin(deg);
      const y = 32 - 32 * Math.cos(deg);
      if (curT.current < (1 / 2) * props.time) {
        setPoint(`${x} ${y}`);
      } else if (curT.current > (1 / 2) * props.time) {
        setPoint(`32 64 A 32 32 0 0 1 ${x} ${y}`);
      }
      calPoint();
    }, 50);
  }, [props.time, props.onEnd]);

  useEffect(() => {
    calPoint();
  }, [calPoint]);

  return (
    <svg
      width="60rpx"
      height="60rpx"
      style={props.style || {}}
      viewBox="-2 -2 68 68"
      version="1.1"
      xmlns="http://www.w3.org/2000/svg"
      xmlnsXlink="http://www.w3.org/1999/xlink"
    >
      <path
        d={`M32 0 A 32 32 0 0 1 ${point}`}
        stroke="white"
        fill="transparent"
        stroke-width="4"
      />
    </svg>
  );
};

Remark:

  1. Stroke width does not take effect: It is suspected that stroke-width cannot be written as strokeWidth in rax.
  2. The ring radius does not affect the actual size, but pay attention to adjust the viewbox size according to your own ring radius to avoid incomplete display. In this case, the ring radius is 32.
  3. The coordinates of the start and end points of the circle are the same, so when drawing in the path method, the middle point of a path must be set. In this example, the 180 degree position is set as the middle point.

Marckon
1k 声望169 粉丝

正在成长的小前端...