Javascript 基于滚动位置沿路径绝对定位元素
我试图将div元素放置在正弦波上,正弦波用作其路径。当用户滚动时,回调应该能够沿着正弦波计算Javascript 基于滚动位置沿路径绝对定位元素,javascript,reactjs,Javascript,Reactjs,我试图将div元素放置在正弦波上,正弦波用作其路径。当用户滚动时,回调应该能够沿着正弦波计算球的左和顶属性。我的定位有问题。我在y轴上使用Math.abs,在x轴上添加了8(或-8)个像素 我注意到的另一件事是滚动事件侦听器回调有时会错过某些断点。我已经记录了滚动位置及其真值,回调要么每隔3个像素执行一次,要么浏览器出于某种原因自行限制scroll事件(我可以理解,跟踪每个像素的滚动没有意义) 无论如何,我想知道为什么我目前的方法不起作用,是否有更好的解决方案?我觉得事情太多了,这可以用更好的方
球的左
和顶
属性。我的定位有问题。我在y轴上使用Math.abs
,在x轴上添加了8(或-8)个像素
我注意到的另一件事是滚动事件侦听器回调有时会错过某些断点。我已经记录了滚动位置及其真值,回调要么每隔3个像素执行一次,要么浏览器出于某种原因自行限制scroll
事件(我可以理解,跟踪每个像素的滚动没有意义)
无论如何,我想知道为什么我目前的方法不起作用,是否有更好的解决方案?我觉得事情太多了,这可以用更好的方式实现。以下是我所拥有的:
import React from "react";
import styled from "styled-components";
const lineHeight = 200;
export default React.memo(() => {
const [top, setTop] = React.useState(275);
const [left, setLeft] = React.useState(0);
const [previousPosition, setPreviousPosition] = React.useState(0);
React.useEffect(() => { const s = skrollr.init() }, []);
React.useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, [previousPosition, left]);
const handleScroll = React.useCallback(() => {
const pageYOffset = window.pageYOffset;
const isMovingForward = pageYOffset > previousPosition;
setPreviousPosition(window.pageYOffset);
setTop(lineHeight - Math.abs(lineHeight - pageYOffset));
if (isMovingForward) {
if (pageYOffset > 575 && pageYOffset <= 770) setLeft(left + 8);
} else {
if (pageYOffset <= 770 && pageYOffset >= 575) setLeft(left - 8)
}
}, [previousPosition, left]);
return (
<Main>
<Container
data-500p="transform: translateX(0%)"
data-1000p="transform: translateX(-800%)"
>
<Content>
<WaveContainer>
<Wave src="https://www.designcrispy.com/wp-content/uploads/2017/11/Sine-Wave-Curve.png" />
</WaveContainer>
<BallContainer top={top} left={left}>
<Ball />
</BallContainer>
</Content>
</Container>
</Main>
);
});
const Main = styled.div`
margin: 0;
padding: 0;
box-sizing: border-box;
`;
const Container = styled.div`
position: fixed;
width: 100%;
display: flex;
top: 0;
left: 0;
`;
const Content = styled.div`
min-width: 100vw;
height: auto;
display: grid;
place-items: center;
height: 100vh;
background: #fffee1;
font-weight: 900;
position: relative;
`;
const Wave = styled.img`
width: 600px;
`;
const WaveContainer = styled.div`
position: absolute;
left: -40px;
top: 45%;
`;
const Ball = styled.div`
width: 20px;
height: 20px;
border-radius: 50%;
background: black;
`;
const BallContainer = styled.div`
position: absolute;
transition: 0.25s;
${({ top, left }) => `top: ${top}px; left: ${left}px;`};
`;
从“React”导入React;
从“样式化组件”导入样式化;
常数线宽=200;
导出默认的React.memo(()=>{
const[top,setTop]=React.useState(275);
const[left,setLeft]=React.useState(0);
const[previousPosition,setPreviousPosition]=React.useState(0);
React.useffect(()=>{const s=skrollr.init()},[]);
React.useffect(()=>{
window.addEventListener(“滚动”,handleScroll);
return()=>window.removeEventListener(“滚动”,handleScroll);
},[previousPosition,左];
const handleScroll=React.useCallback(()=>{
const pageYOffset=window.pageYOffset;
常量isMovingForward=pageYOffset>previousPosition;
setPreviousPosition(window.pageYOffset);
setTop(lineHeight-Math.abs(lineHeight-pageYOffset));
如果(isMovingForward){
如果(pageYOffset>575&&pageYOffset`top:${top}px;left:${left}px;`};
`;
我用它来处理固定的画布+滚动长度
如果您可以支持(显然,IE或Safari上不提供),我强烈建议您将尽可能多的内容转移到基于CSS和SVG的动画。下面是一个普通的JS示例-您在这里实际需要计算的唯一一件事是希望动画的百分比,它可以基于任意滚动条件:
constball=document.querySelector('.ball');
window.addEventListener('scroll',()=>{
const winHeight=document.body.offsetHeight;
const pageOffset=window.pageYOffset;
常数pc=(页偏移量*2/winHeight)*100;
ball.style.offsetDistance=`${pc}%`;
});
*{
填充:0;
保证金:0;
}
.第页{
高度:200vh;
}
.集装箱{
位置:粘性;
排名:0;
宽度:100%;
}
svg{
位置:绝对位置;
填充:透明;
笔画:蓝色;
笔画宽度:2px;
}
.球{
偏移路径:路径(“M10 80 C 40 10、65 10、95 80 S 150、180 80”);
宽度:20px;
高度:20px;
背景:黑色;
边界半径:50%;
}
我更改了您的代码沙盒,以便它满足您的需要:(我希望)
我应该补充一点,我更改了有关您代码的各种内容:
- 无需每次左键或上一个键时设置新的滚动侦听器
职位变动。关于上一个职位和职位的所有代码是什么
决定页面是向上还是向下滚动?我删除了它
- 动画因过渡而被限制:0.25秒
球形容器。为了计算相对于
图像-鼻窦,我把它们移到同一个容器中
- 计算球的准确位置、波幅和波高
需要使用常数,需要使用适当的数学-
图像上的窦房结似乎有2,5个周期,但是有2,58个周期
比较适合动画。我会尝试使用不同的
鼻窦并找出原因