React JS 中的进度条

Progress circle bar in React JS

我正在创建一个进度圆条,与滑块一起用作计时器,其中每张幻灯片都有自己的进度条

我可以实现,但是我无法将条与它们自己同步。

这是正在发生的事情:

如您所见,它无法正常工作。我需要条形图填充 100% 的圆,然后继续下一个点并重复该过程,但是我无法同步它们。

如果我只有一个点,它似乎工作正常,但:

我正在使用两个 setTimeout,一个通过 percentage 的控制减少 circle 的 属性 stroke-dashoffset,这个使酒吧被填补;第二个setTimeout就是让圆圈出现在后面的点周围。我有变量 timer 来控制变化的间隔,它在第二个 setTimeout 中。我相信问题可能在于两者之间的时间setTimeout,但这只是一个猜测。

我正在使用钩子,但是我不能让它在 Codepen 上以这种方式工作,因为我创建了一个带有 class 组件的代码笔,但更糟糕的是,我没有知道为什么,因为它遵循相同的逻辑。

https://codepen.io/WegisSilveira/pen/poyPVWq

无论如何,这是我的带钩子的代码。 css与codepen上的相同:

import React, { Fragment } from 'react'

import './ProgressBar.css'


const ProgressBar = props => {

let [sqSize, setSqSize] = React.useState(30)
let [percentage, setPercentage] = React.useState(0)
let [strokeWidth, setStrokeWidth] = React.useState(3)

let [trigger, setTrigger] = React.useState(false)
let [barIndex, setBarIndex] = React.useState(0)

let bars = Array(props.bar).fill(1)
let timer = 3000


const barTriggerHandler = () => {
    setTrigger(!trigger)
}


if (trigger) {
    setTimeout(() => {
        percentage < 99 ? setPercentage(percentage + 1) : setPercentage(0)
    }, timer / 100);

    setTimeout(() => {
        console.log(percentage)
        barIndex < bars.length - 1 ? setBarIndex(barIndex + 1) : setBarIndex(0)
    }, timer);
    
}

// SVG centers the stroke width on the radius, subtract out so circle fits in square
const radius = (sqSize - strokeWidth) / 2;
// Enclose cicle in a circumscribing square
const viewBox = `0 0 ${sqSize} ${sqSize}`;
// Arc length at 100% coverage is the circle circumference
const dashArray = radius * Math.PI * 2;
// Scale 100% coverage overlay with the actual percent
const dashOffset = dashArray - dashArray * percentage / 100;
// console.log(dashOffset)

return (
    <Fragment>
        { bars.map((bar, i) => {
            return <svg
                        key={i}

                        width={sqSize}
                        height={sqSize}
                        viewBox={viewBox}

                        onClick={() => barTriggerHandler()}
                    >
                        { i === barIndex ?  
                            <Fragment>
                                <circle
                                    className="circle-progress"
                                    cx={sqSize / 2}
                                    cy={sqSize / 2}
                                    r={radius}
                                    strokeWidth={`${strokeWidth}px`}
                                    // Start progress marker at 12 O'Clock
                                    transform={`rotate(-90 ${sqSize / 2} ${sqSize / 2})`}
                                    style={{
                                        strokeDasharray: dashArray,
                                        strokeDashoffset: dashOffset
                                    }} 
                                /> 
                            </Fragment>
                        : null }
                        <circle
                            className="circle-center"
                            cx="50%"
                            cy="50%"
                            r="3"
                        /> 
                        
                    </svg>
        }) }
    </Fragment>
);
}

export default ProgressBar

我正在使用元素 svgcircle 创建该栏,也许问题就在这里,因为直到昨天我什至不知道这些标签而且我有点迷路。

如果有人能帮助我,我将不胜感激。这已经让我发疯了。

P.S。我以这个笔为例创建了这个栏:https://codepen.io/bbrady/pen/ozrjKE?editors=1010

我没有使用两个 setTimeout,而是只使用了一个。我删除了第二个,它用于将 1 添加到包含点的数组的索引中,并将此步骤放在第一个 setTimeout 中,现在而不是检查时间来进行添加我只是检查圆圈是否已填充 99%,如果是,则圆圈转到下一个点。

这是第一个逻辑:

if (trigger) {
    setTimeout(() => {
        percentage < 99 ? setPercentage(percentage + 1) : setPercentage(0)
    }, timer / 100);

    setTimeout(() => {
        barIndex < bars.length - 1 ? setBarIndex(barIndex + 1) : setBarIndex(0)
    }, timer);
    
}

现在我正在这样做:

if (trigger) {
    setTimeout(() => {
        percentage < 99 ? setPercentage(percentage + 1) : setPercentage(0)

        if (percentage === 99) {
             barIndex < bars.length - 1 ? setBarIndex(barIndex + 1) : setBarIndex(0)
        }

    }, timer / 100);        
}

由于两个步骤都在同一个setTimeout中,因此不再有任何间隔冲突。