diff --git a/christmas.html b/christmas.html
index 6dcde05..2c8a443 100644
--- a/christmas.html
+++ b/christmas.html
@@ -507,8 +507,15 @@
// 限制散射模式下粒子的分布范围,防止超出屏幕
let rScatter = this.isDust ? (12 + Math.random() * 15) : (8 + Math.random() * 10);
+ // 根据屏幕尺寸调整最大范围
+ let maxRScatter = 25;
+ if (window.innerWidth <= 480) {
+ maxRScatter = 15; // 小屏幕设备上减小范围
+ } else if (window.innerWidth <= 768) {
+ maxRScatter = 20; // 中等屏幕设备
+ }
// 限制最大范围,防止照片飞出屏幕
- rScatter = Math.min(rScatter, 25);
+ rScatter = Math.min(rScatter, maxRScatter);
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
this.posScatter.set(
@@ -528,7 +535,15 @@
if (mode === 'TREE') target = this.posTree;
else if (mode === 'FOCUS') {
if (this.mesh === focusTargetMesh) {
- const desiredWorldPos = new THREE.Vector3(0, 2, 35);
+ // 根据屏幕尺寸调整焦点照片的位置和距离
+ let focusZ = 35;
+ if (window.innerWidth <= 480) {
+ focusZ = 25; // 小屏幕设备上更靠近摄像机
+ } else if (window.innerWidth <= 768) {
+ focusZ = 30; // 中等屏幕设备
+ }
+
+ const desiredWorldPos = new THREE.Vector3(0, 2, focusZ);
const invMatrix = new THREE.Matrix4().copy(mainGroup.matrixWorld).invert();
target = desiredWorldPos.applyMatrix4(invMatrix);
} else {
@@ -538,32 +553,62 @@
// 在散射模式下添加噪声扰动,让粒子运动更生动
if (mode === 'SCATTER') {
- const noiseX = this.noise(elapsedTime * 0.5 + this.noiseOffset.x) * CONFIG.animation.noiseStrength;
- const noiseY = this.noise(elapsedTime * 0.5 + this.noiseOffset.y) * CONFIG.animation.noiseStrength;
- const noiseZ = this.noise(elapsedTime * 0.5 + this.noiseOffset.z) * CONFIG.animation.noiseStrength;
+ // 根据屏幕尺寸调整噪声强度
+ let noiseStrength = CONFIG.animation.noiseStrength;
+ if (window.innerWidth <= 480) {
+ noiseStrength *= 0.7; // 小屏幕设备上减小噪声
+ } else if (window.innerWidth <= 768) {
+ noiseStrength *= 0.8; // 中等屏幕设备
+ }
+
+ const noiseX = this.noise(elapsedTime * 0.5 + this.noiseOffset.x) * noiseStrength;
+ const noiseY = this.noise(elapsedTime * 0.5 + this.noiseOffset.y) * noiseStrength;
+ const noiseZ = this.noise(elapsedTime * 0.5 + this.noiseOffset.z) * noiseStrength;
target.x += noiseX;
target.y += noiseY;
target.z += noiseZ;
// 限制粒子位置,防止飞出屏幕
- const maxDistance = 30;
+ let maxDistance = 30;
+ // 根据屏幕尺寸调整粒子分布范围
+ if (window.innerWidth <= 480) {
+ maxDistance = 20; // 小屏幕设备上减小范围
+ } else if (window.innerWidth <= 768) {
+ maxDistance = 25; // 中等屏幕设备
+ }
+
if (target.length() > maxDistance) {
target.normalize().multiplyScalar(maxDistance);
}
// 实时手势影响 - 只关注当前手势位置,不使用历史轨迹
- if (handState.detected) {
+ // 在触摸屏设备上增加手势灵敏度
+ if (handState.detected && ('ontouchstart' in window || navigator.maxTouchPoints > 0)) {
// 将2D手势坐标转换为3D空间中的影响点
+ // 根据屏幕尺寸调整手势影响范围
+ let handInfluenceRange = 15;
+ if (window.innerWidth <= 480) {
+ handInfluenceRange = 10; // 小屏幕设备上减小影响范围
+ } else if (window.innerWidth <= 768) {
+ handInfluenceRange = 12; // 中等屏幕设备
+ }
+
const handInfluencePoint = new THREE.Vector3(
- handState.x * 15, // 调整影响范围
- handState.y * 15,
+ handState.x * handInfluenceRange, // 调整影响范围
+ handState.y * handInfluenceRange,
0
);
// 计算粒子与手势影响点之间的距离
const distance = this.mesh.position.distanceTo(handInfluencePoint);
- const maxInfluenceDistance = 8.0;
+ // 根据屏幕尺寸调整最大影响距离
+ let maxInfluenceDistance = 8.0;
+ if (window.innerWidth <= 480) {
+ maxInfluenceDistance = 6.0; // 小屏幕设备上减小影响范围
+ } else if (window.innerWidth <= 768) {
+ maxInfluenceDistance = 7.0; // 中等屏幕设备
+ }
// 如果粒子在影响范围内,则受到手势牵引
if (distance < maxInfluenceDistance) {
@@ -601,14 +646,27 @@
}
// 应用影响到目标位置
+ // 在触摸屏设备上增强手势影响
+ let influenceMultiplier = 2.0;
+ if ('ontouchstart' in window || navigator.maxTouchPoints > 0) {
+ influenceMultiplier = 2.5; // 触摸屏设备增强影响
+ }
+
target.add(
- direction.multiplyScalar(influenceStrength * 2.0)
+ direction.multiplyScalar(influenceStrength * influenceMultiplier)
);
}
}
}
- const lerpSpeed = (mode === 'FOCUS' && this.mesh === focusTargetMesh) ? 7.0 : CONFIG.animation.positionLerp;
+ // 根据屏幕尺寸调整插值速度
+ let lerpSpeed = (mode === 'FOCUS' && this.mesh === focusTargetMesh) ? 7.0 : CONFIG.animation.positionLerp;
+ if (window.innerWidth <= 480) {
+ lerpSpeed *= 1.2; // 小屏幕设备上加快动画速度
+ } else if (window.innerWidth <= 768) {
+ lerpSpeed *= 1.1; // 中等屏幕设备
+ }
+
this.mesh.position.lerp(target, Math.min(lerpSpeed * dt, 1.0));
if (mode === 'SCATTER') {
@@ -632,11 +690,27 @@
} else if (mode === 'SCATTER' && this.type === 'PHOTO') {
s = this.baseScale * 2.5;
} else if (mode === 'FOCUS') {
- if (this.mesh === focusTargetMesh) s = 4.5;
+ // 根据屏幕尺寸调整焦点照片的缩放比例
+ let focusScale = 4.5;
+ if (window.innerWidth <= 480) {
+ focusScale = 3.0; // 小屏幕设备上较小的缩放比例
+ } else if (window.innerWidth <= 768) {
+ focusScale = 3.5; // 中等屏幕设备
+ }
+
+ if (this.mesh === focusTargetMesh) s = focusScale;
else s = this.baseScale * 0.8;
}
- this.mesh.scale.lerp(new THREE.Vector3(s, s, s), Math.min(CONFIG.animation.scaleLerp * dt, 1.0));
+ // 根据屏幕尺寸调整缩放插值速度
+ let scaleLerpSpeed = CONFIG.animation.scaleLerp;
+ if (window.innerWidth <= 480) {
+ scaleLerpSpeed *= 1.2; // 小屏幕设备上加快缩放动画
+ } else if (window.innerWidth <= 768) {
+ scaleLerpSpeed *= 1.1; // 中等屏幕设备
+ }
+
+ this.mesh.scale.lerp(new THREE.Vector3(s, s, s), Math.min(scaleLerpSpeed * dt, 1.0));
}
}
// --- End of Particle Class ---
@@ -1011,17 +1085,20 @@
}
}
+ function handleWindowResize() {
+ // 监听窗口大小变化,更新渲染器和相机
+ camera.aspect = window.innerWidth / window.innerHeight;
+ camera.updateProjectionMatrix();
+ renderer.setSize(window.innerWidth, window.innerHeight);
+ composer.setSize(window.innerWidth, window.innerHeight);
+ }
+
// --- Event Handling ---
function setupEvents() {
let resizeTimeout;
window.addEventListener('resize', () => {
clearTimeout(resizeTimeout);
- resizeTimeout = setTimeout(() => {
- camera.aspect = window.innerWidth / window.innerHeight;
- camera.updateProjectionMatrix();
- renderer.setSize(window.innerWidth, window.innerHeight);
- composer.setSize(window.innerWidth, window.innerHeight);
- }, 100);
+ resizeTimeout = setTimeout(handleWindowResize, 100);
});
document.getElementById('file-input').addEventListener('change', handleImageUpload);