You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何集成现成脚本?以MousePRLX鼠标视差脚本为例

如何将原生鼠标视差脚本迁移到React项目

我有一套现成的页面布局,包含spoilers、sliders、parallax等功能脚本,现在想迁移到React项目,但之前都是从零编写代码,不清楚如何引入这些现成脚本。以下是布局阶段使用的鼠标视差脚本:

class MousePRLX {
constructor(props, data = null) {
    let defaultConfig = {
        init: true,
        logging: true,
    }
    this.config = Object.assign(defaultConfig, props);
    if (this.config.init) {
        const paralaxMouse = document.querySelectorAll('[data-prlx-mouse]');
        if (paralaxMouse.length) {
            this.paralaxMouseInit(paralaxMouse);
        } 
    }
}
paralaxMouseInit(paralaxMouse) {
    paralaxMouse.forEach(el => {
        const paralaxMouseWrapper = el.closest('[data-prlx-mouse-wrapper]');

        const paramСoefficientX = el.dataset.prlxCx ? +el.dataset.prlxCx : 100;
        const paramСoefficientY = el.dataset.prlxCy ? +el.dataset.prlxCy : 100;
        const directionX = el.hasAttribute('data-prlx-dxr') ? -1 : 1;
        const directionY = el.hasAttribute('data-prlx-dyr') ? -1 : 1;
        const paramAnimation = el.dataset.prlxA ? +el.dataset.prlxA : 50;

        let positionX = 0, positionY = 0;
        let coordXprocent = 0, coordYprocent = 0;

        // 存储动画ID,用于后续清理
        el._animationId = requestAnimationFrame(setMouseParallaxStyle);

        if (paralaxMouseWrapper) {
            el._mouseMoveHandler = mouseMoveParallax.bind(null, paralaxMouseWrapper);
            paralaxMouseWrapper.addEventListener("mousemove", el._mouseMoveHandler);
        } else {
            el._mouseMoveHandler = mouseMoveParallax.bind(null);
            window.addEventListener("mousemove", el._mouseMoveHandler);
        }

        function setMouseParallaxStyle() {
            const distX = coordXprocent - positionX;
            const distY = coordYprocent - positionY;
            positionX = positionX + (distX * paramAnimation / 1000);
            positionY = positionY + (distY * paramAnimation / 1000);
            el.style.cssText = `transform: translate3D(${directionX * positionX / (paramСoefficientX / 10)}%,${directionY * positionY / (paramСoefficientY / 10)}%,0);`;
            el._animationId = requestAnimationFrame(setMouseParallaxStyle);
        }
        function mouseMoveParallax(wrapper = window) {
            return function(e) {
                const offsetTop = el.getBoundingClientRect().top + window.scrollY;
                if (offsetTop >= window.scrollY || (offsetTop + el.offsetHeight) >= window.scrollY) {
                    const parallaxWidth = window.innerWidth;
                    const parallaxHeight = window.innerHeight;
                    
                    const coordX = e.clientX - parallaxWidth / 2;
                    const coordY = e.clientY - parallaxHeight / 2;
                    
                    coordXprocent = coordX / parallaxWidth * 100;
                    coordYprocent = coordY / parallaxHeight * 100;
                }
            }
        }
    });
}
// 添加清理方法,适配React组件卸载逻辑
stop() {
    const paralaxMouse = document.querySelectorAll('[data-prlx-mouse]');
    paralaxMouse.forEach(el => {
        // 取消动画帧循环
        el._animationId && cancelAnimationFrame(el._animationId);
        // 移除鼠标移动事件监听
        const wrapper = el.closest('[data-prlx-mouse-wrapper]') || window;
        el._mouseMoveHandler && wrapper.removeEventListener('mousemove', el._mouseMoveHandler);
        // 清除元素上存储的临时属性
        delete el._animationId;
        delete el._mouseMoveHandler;
    });
}
}

迁移步骤

1. 封装脚本为可导出模块

在React项目的src/utils目录下新建MousePRLX.js文件,将上述修改后的脚本复制进去,最后添加导出语句:

export default MousePRLX;

2. 在React组件中引入并初始化

React组件的DOM是动态渲染的,必须在组件挂载完成后再初始化脚本,同时要在组件卸载时清理资源,避免内存泄漏。示例组件代码如下:

import { useEffect } from 'react';
import MousePRLX from '../utils/MousePRLX';

function ParallaxSection() {
  useEffect(() => {
    // 初始化视差效果
    const mouseParallaxInstance = new MousePRLX({
      init: true,
      logging: false // 生产环境建议关闭日志
    });

    // 组件卸载时执行资源清理
    return () => {
      mouseParallaxInstance.stop();
    };
  }, []); // 空依赖数组确保只在挂载和卸载时执行一次

  return (
    <section>
      {/* 按照原布局的data属性配置视差元素 */}
      <div 
        data-prlx-mouse 
        data-prlxCx="80" 
        data-prlxCy="80" 
        style={{width: '300px', height: '300px', background: '#ccc', margin: '20px auto'}}
      >
        鼠标移动查看视差效果
      </div>
    </section>
  );
}

export default ParallaxSection;

3. 适配动态DOM场景

如果组件存在条件渲染、列表更新等动态DOM变化,需要在DOM更新完成后重新初始化脚本。可以将相关状态变量加入useEffect的依赖数组,确保状态变化时重新执行初始化:

useEffect(() => {
  const mouseParallaxInstance = new MousePRLX({ init: true });
  return () => mouseParallaxInstance.stop();
}, [dynamicState]); // dynamicState是触发DOM更新的状态变量

关键注意事项

  • 原脚本直接操作DOM,要确保初始化时机在React完成DOM渲染之后,避免出现找不到元素的问题。
  • 必须添加清理逻辑,移除事件监听并取消requestAnimationFrame循环,防止内存泄漏。
  • 如果原布局还有配套的CSS样式,需要将对应的CSS文件导入到React项目中,保证样式正常生效。

内容的提问来源于stack exchange,提问作者Default

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 22:48:51