const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 100;
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
setTimeout(() => {
document.querySelector('.loading').style.display = 'none';
}, 1000);
// 光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
const pointLight = new THREE.PointLight(0x00ffff, 1, 100);
pointLight.position.set(20, 20, 20);
scene.add(pointLight);
// 粒子背景
const particleCount = 2000;
const particles = new THREE.BufferGeometry();
const posArray = new Float32Array(particleCount * 3);
const colorArray = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount * 3; i += 3) {
posArray[i] = (Math.random() - 0.5) * 500;
posArray[i + 1] = (Math.random() - 0.5) * 500;
posArray[i + 2] = (Math.random() - 0.5) * 500;
colorArray[i] = Math.random();
colorArray[i + 1] = Math.random();
colorArray[i + 2] = Math.random();
}
particles.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
particles.setAttribute('color', new THREE.BufferAttribute(colorArray, 3));
const particleMaterial = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true,
transparent: true,
opacity: 0.8
});
const particleSystem = new THREE.Points(particles, particleMaterial);
scene.add(particleSystem);
// 3D文字
let textMesh;
const createText = () => {
const loader = new THREE.FontLoader();
loader.load('https://cdn.jsdelivr.net/npm/three@0.132.2/examples/fonts/helvetiker_regular.typeface.json', (font) => {
const textGeometry = new THREE.TextGeometry('3D jiang feng', {
font: font,
size: 20,
height: 10,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 1,
bevelSize: 1,
bevelOffset: 0,
bevelSegments: 5
});
textGeometry.center();
const textMaterial = new THREE.MeshPhongMaterial({
color: 0x00ffff,
emissive: 0x006666,
shininess: 100,
specular: 0xffffff
});
textMesh = new THREE.Mesh(textGeometry, textMaterial);
scene.add(textMesh);
});
};
createText();
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// 旋转控制变量
let autoRotate = true;
let lastInteractionTime = Date.now();
const rotationSpeed = 0.005;
// 重置自动旋转计时器
const resetAutoRotateTimer = () => {
lastInteractionTime = Date.now();
autoRotate = false;
};
// 事件监听器
window.addEventListener('mousedown', resetAutoRotateTimer);
window.addEventListener('mousemove', resetAutoRotateTimer);
window.addEventListener('touchstart', resetAutoRotateTimer);
window.addEventListener('touchmove', resetAutoRotateTimer);
window.addEventListener('wheel', resetAutoRotateTimer);
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// 动画循环
const animate = () => {
requestAnimationFrame(animate);
// 检查是否需要恢复自动旋转
const currentTime = Date.now();
if (!autoRotate && currentTime - lastInteractionTime > 3000) {
autoRotate = true;
}
// 自动旋转
if (autoRotate && textMesh) {
textMesh.rotation.y += rotationSpeed;
}
controls.update();
// 粒子动画
const positions = particles.attributes.position.array;
for (let i = 0; i < positions.length; i += 3) {
positions[i] += (Math.random() - 0.5) * 0.2;
positions[i + 1] += (Math.random() - 0.5) * 0.2;
positions[i + 2] += (Math.random() - 0.5) * 0.2;
}
particles.attributes.position.needsUpdate = true;
renderer.render(scene, camera);
};
animate();