Javascript 如何根据当前页面偏移和上一页偏移计算动画的速度(以秒为单位)?
我正在尝试基于用户交互来旋转轮子。如果用户正在加速滚动,滚轮应该旋转得更快。同样,如果用户正在减速滚动,滚轮应该停止。我正在使用Skrollr库对样式化组件和React状态应用这些条件 以下是我所拥有的:Javascript 如何根据当前页面偏移和上一页偏移计算动画的速度(以秒为单位)?,javascript,reactjs,styled-components,Javascript,Reactjs,Styled Components,我正在尝试基于用户交互来旋转轮子。如果用户正在加速滚动,滚轮应该旋转得更快。同样,如果用户正在减速滚动,滚轮应该停止。我正在使用Skrollr库对样式化组件和React状态应用这些条件 以下是我所拥有的: import React from "react"; import styled, { createGlobalStyle, css, keyframes } from "styled-components"; export default funct
import React from "react";
import styled, { createGlobalStyle, css, keyframes } from "styled-components";
export default function App() {
const [previousPosition, setPreviousPosition] = React.useState(0);
const [previousDelta, setPreviousDelta] = React.useState(0);
const [speed, setSpeed] = React.useState(1);
const [isStopping, setIsStopping] = React.useState(false);
React.useEffect(() => {
skrollr.init();
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, [previousPosition, previousDelta]);
const handleScroll = React.useCallback(() => {
// get delta
const delta = window.pageYOffset - previousPosition;
if (previousDelta > delta) {
// is stopping
setIsStopping(true);
setSpeed(0);
} else {
// is accelerating
// calculate delta as a percentage
const deltaAsPercentage = (delta / previousPosition) * 100;
console.log("deltaAsPercentage", deltaAsPercentage);
setIsStopping(false);
setSpeed(deltaAsPercentage);
}
setPreviousPosition(window.pageYOffset);
}, [previousPosition, previousDelta]);
return (
<Container data-10000p="transform: translateX(0%)">
<GlobalStyles />
<WheelContainer speed={speed} isStopping={isStopping}>
<Image src="wheel.png" alt="wheel" />
</WheelContainer>
</Container>
);
}
const Container = styled.div`
position: fixed;
width: 100%;
display: flex;
top: 0;
left: 0;
`;
const spinForward = keyframes`
0% {
transform: rotateZ(0deg);
}
50% {
transform: rotateZ(180deg);
}
100% {
transform: rotateZ(360deg);
}
`;
const stopWheel = keyframes`
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(360deg);
}
`;
const WheelContainer = styled.div`
${({ speed, isStopping }) =>
isStopping
? css`
animation: ${stopWheel} 1s ease-out;
`
: css`
animation: ${speed
? css`
${spinForward} ${speed}s linear infinite
`
: ""};
`}
`;
const Image = styled.img``;
const GlobalStyles = createGlobalStyle`
* {
&::-webkit-scrollbar {
display: none;
}
}
`;
从“React”导入React;
从“样式化组件”导入样式化,{createGlobalStyle,css,keyframes};
导出默认函数App(){
const[previousPosition,setPreviousPosition]=React.useState(0);
const[previousDelta,setPreviousDelta]=React.useState(0);
常数[速度,设定速度]=反应。使用状态(1);
常量[isStopping,setIsStopping]=React.useState(false);
React.useffect(()=>{
skrollr.init();
window.addEventListener(“滚动”,handleScroll);
return()=>window.removeEventListener(“滚动”,handleScroll);
},[previousPosition,previousDelta]);
const handleScroll=React.useCallback(()=>{
//得到三角洲
常量增量=window.pageYOffset-上一个位置;
如果(以前的增量>增量){
//正在停止
setIsStopping(真);
设定速度(0);
}否则{
//正在加速
//以百分比计算增量
常量deltaAsPercentage=(增量/先前位置)*100;
log(“deltaAsPercentage”,deltaAsPercentage);
setIsStopping(假);
设置速度(deltaAsPercentage);
}
setPreviousPosition(window.pageYOffset);
},[previousPosition,previousDelta]);
返回(
);
}
const Container=styled.div`
位置:固定;
宽度:100%;
显示器:flex;
排名:0;
左:0;
`;
常量向前旋转=关键帧`
0% {
变换:旋转(0度);
}
50% {
变换:旋转(180度);
}
100% {
变换:旋转(360度);
}
`;
const stopWheel=关键帧`
0% {
变换:旋转(0度);
}
100% {
变换:旋转(360度);
}
`;
const WheelContainer=styled.div`
${({speed,isStopping})=>
isStopping
?css`
动画:${stopWheel}1放松;
`
:css`
动画:${speed
?css`
${spinForward}${speed}的线性无限
`
: ""};
`}
`;
const Image=styled.img``;
const GlobalStyles=createGlobalStyle`
* {
&:-webkit滚动条{
显示:无;
}
}
`;
我数学不太好,所以我在用我所知道的尽我所能
我在scroll上做的第一件事是确定车轮是否应该停止或加速。如果它停止,我会改变组件的状态,让wheelcainer
知道它应该调出当前动画。如果轮子不应该停止,我将保持当前动画并改变旋转速度
不管怎么说,我已经开始工作了。我遇到的问题是,它无法识别“较慢的滚动”。例如,用户可以快速或缓慢地滚动,但仍然可以滚动。缓慢的滚动不一定意味着它应该停止
另一个问题是,spinBack
似乎永远不会被调用。即使是这样,我也不知道如何区分“较慢”的滚动和向后旋转
最后,我应该注意到,加速滚动似乎只有在mac的触摸板上才能识别。我只是插入了一个外部鼠标来测试它,但它并没有像预期的那样旋转
除此之外,我觉得还有更好的方法。也许是一些关于Math.sin
或Math.cos
的东西,或者类似的东西,我应该在高中数学课上更加注意。这个组件感觉太笨重了,因为它似乎有一个更简单的方法
这是一个沙箱
以下是我的尝试:
对我来说,第一个问题是代码在输入时执行。感觉函数计算需要一些小的时间延迟。
我们将使用setTimeout
来实现这一点
第二:是的,你说得对。我们需要一个类似数学/触发器的函数,对于非常小的值,该函数将给出一个接近于零的值,对于增加的值,该函数将给出一个接近于1的值
第三点是……嗯,这更像是个人的事情——我不确定这是否是故意的,但我注意到,一旦滚动到顶部(即window.pageYOffset=0
),回滚功能就不起作用了。
因此,我使用了wheel
eventListener,而不是scroll
eventListener——这样,我可以使用deltaY
属性查看它的变化程度
第四,我将速度设置为时间所覆盖距离的函数
最后:CSS的速度一开始对我来说是违反直觉的-出于某种原因,值越高,旋转速度越慢!我一直在想到底出了什么问题,直到我意识到我愚蠢的错误!