javascript - 在 React 中让元素随着延迟顺序变化
问题描述
我试图让一排点以很小的延迟(在每个点变化之间)按顺序变化,但遇到了麻烦。这是我到目前为止所拥有的:
const Dots = () => {
const [currentDot, setCurrentSegment] = useState(1);
return (
<Wrapper>
<StyledLargeDot
onClick={() => setCurrentSegment(1)}
isActive={currentDot >= 1}
/>
<StyledLargeDot
onClick={() => setCurrentSegment(2)}
isActive={currentDot >= 2}
/>
<StyledLargeDot
onClick={() => setCurrentSegment(3)}
isActive={currentDot >= 3}
/>
<StyledLargeDot
onClick={() => setCurrentSegment(4)}
isActive={currentDot >= 4}
/>
<StyledLargeDot
onClick={() => setCurrentSegment(5)}
isActive={currentDot >= 5}
/>
<StyledLargeDot
onClick={() => setCurrentSegment(6)}
isActive={currentDot >= 6}
/>
</Wrapper>
);
};
export default Dots;
const Wrapper = styled.div`
background: green;
display: flex;
height: 100vh;
align-items: center;
justify-content: space-evenly;
width: 100vw;
`;
const StyledLargeDot = styled.div`
background: #ffffff;
border: 2px solid #fff;
border-radius: 50%;
cursor: pointer;
position: relative;
height: 5px;
opacity: ${(props) => (props.isActive ? "1" : "0.3")};
transform: ${(props) => (props.isActive ? "scale(2)" : "")};
transition: all 0.5s 1s linear;
width: 5px;
&:hover {
transform: ${(props) => (props.isActive ? "" : "scale(2)")};
opacity: ${(props) => (props.isActive ? "" : "1")};
}
`;
一个“工作”的例子在这里:https ://codesandbox.io/s/optimistic-smoke-qlv2i?file=/src/components/Dots.js
我想要发生的是:
第一个点(从左到右)始终处于活动状态。在职的
当单击另一个点时,它之间的点会按顺序激活,并会稍有延迟,直到单击的点最后亮起。不工作 - 单击的点首先激活,中间的点不按顺序激活。
如果它点击了前一个点,那么它之后的点会依次停用(从右到左),直到它们到达它但它仍然保持活动状态。不工作 - 单击的那个仍然处于活动状态,但介于两者之间的那些似乎没有按顺序一起停用。
理想情况下,任何未激活的点都会在悬停时缩放到激活的大小而不激活。不工作,但我知道为什么,并且可能会在修复其他所有内容后弄清楚。
正如你所看到的,我所做的有些工作,但不是真的。我想我可以弄清楚悬停,但真正的问题是我被难住的顺序和时间:/
我什至不确定这是否是最好的方法,真的很感激一些帮助吗?
先感谢您
解决方案
https://codesandbox.io/s/gifted-ramanujan-h41iu多田!
首先我用一个对象创建了一个数组来保存每个点的属性
const initialDots = [
{ isActive: true, delay: 0},
{ isActive: false, delay: 0},
{ isActive: false, delay: 0 },
{ isActive: false, delay: 0 },
{ isActive: false, delay: 0},
{ isActive: false, delay: 0 }
];
我将每个元素映射到一个<StyledLargeDot {...dot} onClick={() => handleChange(index)} />.
句柄更改函数将改变数组以获得正确的效果。
return (
<Wrapper>
{dots.map((dot, index) => {
return (
<StyledLargeDot {...dot} onClick={() => handleChange(index)}/>
);
})}
</Wrapper>
);
后来我将其更改为下面添加悬停功能的内容,因为过渡延迟<StyledLargeDot/>
使得很难在没有延迟的情况下添加任何悬停效果。
return (
<Wrapper>
{dots.map((dot, index) => {
return (
<div
onClick={() => handleChange(index)}
style={{ position: "relative" }}
>
<StyledLargeDot {...dot} />
<HoverEffect {...dot} />
</div>
);
})}
</Wrapper>
);
我必须对您的组件进行以下更改才能获取新delay
属性。
const StyledLargeDot = styled.div`
background: #ffffff;
border: 2px solid #fff;
border-radius: 50%;
cursor: pointer;
position: relative;
height: 5px;
opacity: ${(props) => (props.isActive ? "1" : "0.3")};
transform: ${(props) => (props.isActive ? "scale(2)" : "")};
transition: all 0.5s ${(props) => props.delay}s linear;
width: 5px;
`;
重要的部分是handleChange()
使效果成为可能的功能。它通过计算每个点的适当转换延迟并正确更新isActive
属性来在单击一个点后工作。该delayFix
变量不是必需的,但您可以将其设置为 0 以查看差异。
const [dots, setDots] = useState(initialDots);
const handleChange = (currentIndex) => {
let delayFix = currentIndex > currentDot ? -1 : 0;
setDots(
dots.map((dot, index) => {
return {
isActive: index <= currentIndex,
delay: Math.abs(index - currentDot) + delayFix
};
})
);
setCurrentSegment(currentIndex);
};
为了得到<HoverEffect/>
工作,我在下面创建了这个组件。
const HoverEffect = styled.div`
background: #ffffff;
border: 2px solid #fff;
border-radius: 50%;
cursor: pointer;
position: absolute;
height: 5px;
width: 5px;
top: 0;
left: 0;
z-index: 100;
opacity: 0.3;
transition: all 0.5s linear;
:hover {
opacity: ${(props) => (props.isActive ? "0.3" : "1")};
transform: ${(props) => (props.isActive ? "" : "scale(2)")};
}
`;
推荐阅读
- excel - VBA使用lastrow范围将数据从一个工作簿复制到另一个工作簿
- woocommerce - 将 Woocommerce 存款插件“未来付款”总计更改为每月?
- r - 使用 R 单击网页中的按钮
- javascript - 如何在 Recharts 中为 YAxis 创建一个自定义垂直标签,以防标签太长?
- java - 如果我有一个字符串,如何在日历上设置 maxDate?
- selenium - 如何在 UWP 中使用 WinAppDriver 等待元素?
- sql - 大日期范围内的最小/最大日期值取决于值
- laravel - 如何获取特定用户的一列的平均值
- php - 从 codeigniter 中的查询获取结果时出错
- c# - 将多个实现注册到同一个接口