gpt4 book ai didi

javascript - 使用 useEffect 操作 DOM 事件在不同屏幕上不响应

转载 作者:行者123 更新时间:2023-12-04 11:29:20 25 4
gpt4 key购买 nike

目前我正在尝试在 React 中实现以下视差效果,其中我的图像垂直处于固定位置,但随着文本从左到右移动。
我使用 useEffect 来实现这一点,我获取总高度像素并相应地移动我的组件。这样做的问题是它在我的屏幕上看起来很完美,但是一旦我将其调整到更大或更小的屏幕,布局就会变得很乱。反正有没有同样的效果,但响应友好。随意编辑 CodeSandBox
CodeSandBox(全屏查看以获得更好的引用):https://codesandbox.io/s/stoic-rumple-s8cr6?file=/src/App.js
代码:

export default function App() {
const [index, setIndex] = useState(false);
const [display, setDisplay] = useState(false);
const [number, setNumber] = useState(false);
const [screen, setScreen] = useState(false);

useEffect(function onFirstMount() {
const changeBackground = () => {
let value = window.scrollY;
console.log(value);
let img = document.getElementById("moveLeft");
let text = document.getElementById("moveUp");
let text2 = document.getElementById("text2");
let text3 = document.getElementById("text3");
let text4 = document.getElementById("text4");

let imgWidth = 280;

text.style.marginTop = "-" + value * 0.5 + "px";
text2.style.transform = `translateX(${value * 1.3}px)`;
text3.style.transform = `translateX(-${value * 1.3}px)`;
text4.style.transform = `translateX(${value * 1.3}px)`;

if (value > 600) {
img.style.transform = `translateX(${value * 0.8 - 480 - imgWidth}px)`;
} else {
img.style.transform = `translateX(-${value * 0.5}px)`;
}

if (value > 1400) {
img.style.transform = `translateX(${
-1 * (value * 0.8 - 1120) + 80 + imgWidth
}px)`;
}

if (value > 1700) {
setNumber(true);
} else {
setNumber(false);
}

if (value > 1100) {
setIndex(true);
} else {
setIndex(false);
}
};
window.addEventListener("scroll", changeBackground);
return () => window.removeEventListener("scroll", changeBackground);
}, []);

return (
<>
<div className="App">
<div className="middletext" id="moveUp" style={{ zIndex: "9" }}>
Random Text
</div>

<div class="inflow">
<div class="positioner">
<div class="fixed" style={{ zIndex: "11" }}>
<div id="moveLeft">
<img
alt="passport"
src="https://cdn.britannica.com/87/122087-050-1C269E8D/Cover-passport.jpg"
/>
</div>
</div>
</div>
<div className="halfWindow" style={{ zIndex: "8" }}></div>
<div>
<div class="fixedText" style={{ zIndex: "7" }}>
<div id="text2" className="text2">
Random Text
</div>
</div>
</div>
<div className="secondhalfWindow" style={{ zIndex: index ? "10" : "6" }}></div>
<div>
<div
class="secondfixedText"
style={{
zIndex: index ? "9" : "5",
display: "block"
}}
>
<div id="text3" className="text3">
Random Text 2
</div>
</div>
</div>

<div className="thirdhalfWindow" style={{ zIndex: "4" }}></div>
<div>
<div
class="thirdfixedText"
style={{
zIndex: number ? "10" : "3"
}}
>
<div id="text4" className="text4">
Random Text 3
</div>
</div>
</div>
</div>
</div>
</>
使用 vw 而不是 px 应该可以,但计算非常复杂。

最佳答案

解决方案是重构您的代码。

  • 将所有元素放在中心并创建四个部分。
  • 定义部分的中心,这有助于找到需要停止移动图像并将其移回的位置。
  • 以同样的方式需要处理文本。
  • 当窗口调整大小时,所有内容都以 window.resize 为中心。

  • 沙盒示例 link

    function App() {
    const [screen, setScreen] = React.useState(false);

    const ref = React.useRef(null);

    // Reduce value if want the image to be closer to the edges
    // otherwise to the center
    const setImageLimitMovement = 2;

    const setTextLimitMovement = 4;
    const opacityRange = 400;
    // Speed text movement
    const speed = 2; // .5

    React.useEffect(() => {
    window.addEventListener("resize", () => {
    if (window.innerWidth !== 0) {
    setScreen(window.innerWidth);
    }
    });
    }, []);

    React.useEffect(() => {
    const app = [...ref.current.children];
    const titles = app.filter((el) => el.matches(".titles") && el);
    const blocks = app.filter((el) => el.matches(".blocks") && el);
    const img = app.find((el) => el.matches("#passport") && el);

    // Get the center point of blocks in an array
    const centerPoints = blocks.map((blockEl, idx) => {
    const blockindex = idx + 1;
    const blockHeight = Math.floor(blockEl.getBoundingClientRect().height);
    const blockHalf = blockHeight / 2;
    return blockHeight * blockindex - blockHalf;
    });

    const leftMoveLimitImg = -centerPoints[0] / setImageLimitMovement;
    const rightMoveLimitImg = centerPoints[0] / setImageLimitMovement;

    const textLimit = centerPoints[0] / setTextLimitMovement;

    const changeBackground = () => {
    const value = window.scrollY;

    titles[0].style.transform = `translateY(-${value * speed}px)`;
    // IMAGE BOUNCE
    // Move to <==
    if (centerPoints[0] > value) {
    img.style.transform = `translateX(-${
    value * (1 / setImageLimitMovement)
    }px)`;

    titles[1].style.transform = `translateX( ${
    0 + value / setTextLimitMovement
    }px)`;
    titles[1].style.opacity = value / opacityRange;
    return;
    }

    // Move to ==>
    if (centerPoints[1] > value) {
    const moveTextToRight =
    centerPoints[1] / setTextLimitMovement - textLimit;
    const hideText = centerPoints[0] / opacityRange;
    const checkDirection = Math.sign(
    textLimit + (textLimit - value / setTextLimitMovement)
    );

    const moveImageToRight =
    (value - centerPoints[0]) / setImageLimitMovement;
    img.style.transform = `translateX(${
    leftMoveLimitImg + moveImageToRight
    }px)`;

    if (checkDirection === -1) {
    titles[1].style.opacity = 0;
    titles[1].style.transform = `translateX(${0}px)`;

    titles[2].style.opacity =
    Math.abs(hideText - value / opacityRange) - 1;
    titles[2].style.transform = `translateX(${
    moveTextToRight - value / setTextLimitMovement
    }px)`;
    return;
    }
    if (checkDirection === 1) {
    titles[1].style.opacity = 1 + (hideText - value / opacityRange);
    titles[1].style.transform = `translateX(${
    textLimit + (textLimit - value / setTextLimitMovement)
    }px)`;

    titles[2].style.opacity = 0;
    titles[2].style.transform = `translateX(${0}px)`;
    }
    return;
    }

    // Move to <==
    if (centerPoints[2] > value) {
    const moveTextToLeft =
    centerPoints[2] / setTextLimitMovement - textLimit;
    const hideText = centerPoints[1] / opacityRange;
    const checkDirection = Math.sign(
    moveTextToLeft - value / setTextLimitMovement
    );

    const moveImageToLeft =
    (-value + centerPoints[1]) / setImageLimitMovement;
    img.style.transform = `translateX(${
    rightMoveLimitImg + moveImageToLeft
    }px)`;

    if (checkDirection === -1) {
    titles[2].style.opacity = 0;
    titles[2].style.transform = `translateX(${0}px)`;

    titles[3].style.opacity =
    Math.abs(hideText - value / opacityRange) - 1;
    titles[3].style.transform = `translateX(${Math.abs(
    moveTextToLeft - value / setTextLimitMovement
    )}px)`;
    }

    if (checkDirection === 1) {
    titles[2].style.opacity = 1 + (hideText - value / opacityRange);
    titles[2].style.transform = `translateX(-${
    moveTextToLeft - value / setTextLimitMovement
    }px)`;

    titles[3].style.opacity = 0;
    titles[3].style.transform = `translateX(${0}px)`;
    }
    return;
    }

    // Move to ==>
    if (centerPoints[3] > value) {
    const moveTextToRight =
    centerPoints[3] / setTextLimitMovement - textLimit;
    const hideText = centerPoints[2] / opacityRange;
    const checkDirection = Math.sign(
    moveTextToRight - value / setTextLimitMovement
    );

    const moveImageToRight =
    (value - centerPoints[2]) / setImageLimitMovement;
    img.style.transform = `translateX(${
    leftMoveLimitImg + moveImageToRight
    }px)`;

    if (checkDirection === -1) {
    titles[3].style.opacity = 0;
    titles[3].style.transform = `translateX(${0}px)`;
    }
    if (checkDirection === 1) {
    titles[3].style.opacity = 1 + (hideText - value / opacityRange);
    titles[3].style.transform = `translateX(${
    moveTextToRight - value / setTextLimitMovement
    }px)`;
    }
    return;
    }

    window.requestAnimationFrame(changeBackground);
    };
    window.addEventListener("scroll", changeBackground);
    return () => window.removeEventListener("scroll", changeBackground);
    }, [screen]);

    return (
    <div className="App" ref={ref}>
    <h1 id="title" className="titles">
    Random Title
    </h1>
    <section id="block1" className="blocks">
    <h4>Block 1</h4>
    </section>
    <figure id="passport">
    <img
    alt="passport"
    src="https://cdn.britannica.com/87/122087-050-1C269E8D/Cover-passport.jpg"
    />
    </figure>
    <h2 id="text1" className="titles text1">
    Random Text 1
    </h2>
    <section id="block2" className="blocks">
    <h4>Block 2</h4>
    </section>
    <h2 id="text2" className="titles text2">
    Random Text 2
    </h2>
    <section id="block3" className="blocks">
    <h4>Block 3</h4>
    </section>
    <h2 id="text3" className="titles text3">
    Random Text 3
    </h2>
    <section id="block4" className="blocks">
    <h4>Block 4</h4>
    </section>
    </div>
    );
    }


    const rootElement = document.getElementById("root");
    ReactDOM.render( <
    App / > ,
    rootElement
    );
    * {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
    }
    .App {
    font-family: sans-serif;
    width: 100%;
    background-color: hsl(220, 65%, 16%);
    }
    figure {
    width: 280px;
    height: max-content;
    position: fixed;
    inset: 0;
    margin: auto;
    z-index: 100;
    }
    img {
    width: 100%;
    }

    .blocks {
    height: 100vh;
    display: flex;
    position: relative;
    grid-column: 1 / -1;
    color: grey;
    }

    .titles {
    width: max-content;
    height: max-content;
    position: fixed;
    inset: 0;
    margin: auto;
    color: white;
    z-index: 99;
    }

    h1 {
    font-size: 3.5em;
    }
    h2 {
    display: flex;
    opacity: 0;
    font-size: 2.5em;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <div id="root"></div>

    关于javascript - 使用 useEffect 操作 DOM 事件在不同屏幕上不响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68920034/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com