6

svg实现react/rax圆环倒计时进度条组件code snippet

 2 years ago
source link: https://segmentfault.com/a/1190000040542290
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

svg实现react/rax圆环倒计时进度条组件code snippet

效果:
image.png
不用svg几乎都是需要有额外的元素遮挡实现,但没有办法做到半透明圆环效果。纯svg画,加宽path的stroke宽度视觉上呈现圆环。(是不是高中学过的三角函数快忘光了?)

以半径32的圆环为例,注意画笔定位基准落在中心位置,需要调整viewbox尺寸避免出现圆环显示不完整。(拷贝自用)

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>
  );
};
  1. 出现stroke width不生效:rax中疑似不能把stroke-width写成strokeWidth。
  2. 圆环半径不影响实际尺寸,但注意根据自己的圆环半径调整viewbox尺寸避免显示不完整,本例圆环半径32.。
  3. 圆环起终点坐标相同,故使用path方式绘制时,必须要设定一个路径的中间点,本例设定了180度位置为中间点。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK