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

如何用GSAP移动Three.js动画对象且不遮挡HTML文本?

问题描述

我是网页设计新手,若问题较为基础还请见谅。我想要使用GSAP将Three.js中的动画对象移至屏幕左侧,但屏幕左侧已有文本“Hello”。当前GSAP动画移动的是整个场景,移动过程中会短暂遮挡HTML文本。请问是否可以仅移动对象而非整个场景,或是始终保持HTML文本可见?


Three.js代码

import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js';
import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader.js';

// Scene 1 - Landing Page 

container = document.getElementById( 'canvas' );

document.body.appendChild( container );

const renderer = new THREE.WebGLRenderer({antialias: true});

renderer.setSize(window.innerWidth, window.innerHeight);

container.appendChild( renderer.domElement );

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(
    45,
    window.innerWidth / window.innerHeight,
    0.1,
    700
);

const orbit = new OrbitControls(camera, renderer.domElement);

camera.position.x = 90
camera.position.y = 200
camera.position.z = 250
orbit.update();

//const grid = new THREE.GridHelper(30, 30);

const gltfLoader = new GLTFLoader();

const rgbeLoader = new RGBELoader();

renderer.linearEncoding = THREE.SRGBColorSpace;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 4;

let car;

rgbeLoader.load('./assets/MR_INT-005_WhiteNeons_NAD.hdr', function(texture) {
    texture.mapping = THREE.EquirectangularReflectionMapping;
    scene.environment = texture;

    gltfLoader.load('./assets/scene.gltf', function(gltf) {
        const model = gltf.scene;
        scene.add(model);
        car = model;
    });
});

function animate(time) {
    if(car)
        car.rotation.y = - time / 3000;
    renderer.render(scene, camera);
}

renderer.setAnimationLoop(animate);

window.addEventListener('resize', function() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

HTML及CSS代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./style.css"> 
</head>
<body>
    <div id="canvas"></div>
    <div class="text-container">
        <div class="title">
            <h1>Hello</h1>
        </div>
    </div>
<body>
    <script src="./js/scripts.js" type="module"></script>
    <script src="./js/app.js" type="module"></script>
    <!--
        npm install @parcel/config-default -d
        
        "staticFiles": {
    "staticOutPath": "static"
    }
    -->
</body>
</html>
@import url('https://fonts.googleapi.com/css2?family=Montserrat&display=swap');
html {
    background: black;
    scroll-behavior: smooth;
  }
  
body {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    overflow-x: hidden;
    overflow-y: hidden;
  }

.canvas{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.text-container{
    position: absolute;
    top: 50%;
    left: 50;
    width: 50%;
    height: auto;
}

.title{
    color: whitesmoke
}

.title h1{
    color:whitesmoke
}

GSAP脚本

// GSAP Animations 
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

gsap.to("#canvas",{
    x: 350,
    duration: 2,
    delay: 1
});

解决方案

方案一:仅移动Three.js中的3D对象(推荐)

你当前的GSAP是直接移动承载Three.js的#canvas容器,导致整个画布移动。正确做法是直接控制Three.js加载的模型对象(即car变量),而非整个容器。

步骤1:让car变量全局可访问

在Three.js脚本末尾添加导出语句,让GSAP脚本能访问到模型对象:

// 在Three.js脚本最后添加
export let car;

步骤2:修改GSAP脚本,直接动画模型位置

// GSAP Animations 
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
// 导入Three.js脚本中的car变量
import { car } from './path-to-your-threejs-script.js';

gsap.registerPlugin(ScrollTrigger);

// 等待模型加载完成后执行动画(避免car未初始化)
gsap.to(car.position,{
    x: -100, // 根据需求调整X轴偏移值,负数为向左移动
    duration: 2,
    delay: 1
});

说明

  • Three.js的3D坐标与DOM像素坐标不同,需测试调整x值以达到理想位置
  • 模型的renderLoop已在运行,无需额外触发渲染更新

方案二:让HTML文本始终显示在最上层

若不想修改Three.js动画逻辑,可通过CSS提升文本容器层级,确保不会被画布遮挡:

修改后的CSS代码

@import url('https://fonts.googleapi.com/css2?family=Montserrat&display=swap');
html {
    background: black;
    scroll-behavior: smooth;
  }
  
body {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    overflow-x: hidden;
    overflow-y: hidden;
  }

/* 修复选择器:HTML中是id="canvas",对应#canvas而非.canvas */
#canvas{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    z-index: 1; /* 明确画布层级低于文本 */
}

.text-container{
    position: absolute;
    top: 50%;
    left: 50px; /* 修复笔误:原left:50改为具体数值 */
    width: 50%;
    height: auto;
    z-index: 9999; /* 提升文本层级,确保不会被遮挡 */
    transform: translateY(-50%); /* 让文本垂直居中,可选优化 */
}

.title{
    color: whitesmoke
}

.title h1{
    color:whitesmoke
}

说明

  • 修复了CSS中的选择器错误:.canvas改为#canvas
  • z-index:9999确保文本容器层级远高于画布
  • transform: translateY(-50%)优化文本垂直居中效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 06:45:32