Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/435.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 基于滚动位置沿路径绝对定位元素_Javascript_Reactjs - Fatal编程技术网

Javascript 基于滚动位置沿路径绝对定位元素

Javascript 基于滚动位置沿路径绝对定位元素,javascript,reactjs,Javascript,Reactjs,我试图将div元素放置在正弦波上,正弦波用作其路径。当用户滚动时,回调应该能够沿着正弦波计算球的左和顶属性。我的定位有问题。我在y轴上使用Math.abs,在x轴上添加了8(或-8)个像素 我注意到的另一件事是滚动事件侦听器回调有时会错过某些断点。我已经记录了滚动位置及其真值,回调要么每隔3个像素执行一次,要么浏览器出于某种原因自行限制scroll事件(我可以理解,跟踪每个像素的滚动没有意义) 无论如何,我想知道为什么我目前的方法不起作用,是否有更好的解决方案?我觉得事情太多了,这可以用更好的方

我试图将div元素放置在正弦波上,正弦波用作其路径。当用户滚动时,回调应该能够沿着正弦波计算
球的
属性。我的定位有问题。我在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个周期 比较适合动画。我会尝试使用不同的 鼻窦并找出原因