-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathanimatedskybox.html
158 lines (136 loc) · 6.29 KB
/
animatedskybox.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js Cube Skybox with Video Left Pane and FOV Zoom</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
</style>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/[email protected]/build/three.module.js",
"three/examples/jsm/controls/OrbitControls": "https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js"
}
}
</script>
</head>
<body>
<video id="video" src="rickrollt.mp4" loop playsinline style="display:none"></video>
<div id="startPrompt" style="position: absolute; z-index: 100; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; background-color: rgba(0,0,0,0.5); color: white; font-size: 24px;">
Tap to start
</div>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const video = document.getElementById('video');
const startPrompt = document.getElementById('startPrompt');
let videoPlaying = false;
// Set up the scene, camera, and renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Load the equirectangular texture
const loader = new THREE.TextureLoader();
loader.load('https://threejs.org/examples/textures/2294472375_24a3b8ef46_o.jpg', (texture) => {
const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
rt.fromEquirectangularTexture(renderer, texture);
scene.background = rt.texture;
// Create video texture for the left pane
const videoTexture = new THREE.VideoTexture(video);
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
videoTexture.format = THREE.RGBFormat;
// Create a plane for the video
const planeGeometry = new THREE.PlaneGeometry(500, 500);
const planeMaterial = new THREE.MeshBasicMaterial({ map: videoTexture, side: THREE.DoubleSide });
const videoPlane = new THREE.Mesh(planeGeometry, planeMaterial);
videoPlane.rotation.y = Math.PI / 2;
videoPlane.position.x = -249; // Slightly inside the left of the skybox
scene.add(videoPlane);
// Function to start the video
function startVideo() {
if (!videoPlaying) {
video.play().then(() => {
videoPlaying = true;
startPrompt.style.display = 'none';
}).catch(error => {
console.error("Video playback failed:", error);
});
}
}
// Add click event listener to start the video
document.addEventListener('click', startVideo);
document.addEventListener('touchstart', startVideo);
});
// Position the camera
camera.position.set(0, 0, 0.1);
// Add OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 0.1;
controls.maxDistance = 500;
controls.maxPolarAngle = Math.PI;
controls.enableZoom = false; // Disable default zoom
// FOV zoom parameters
const minFov = 30;
const maxFov = 90;
const zoomSpeed = 0.1;
// Add mouse wheel event listener for FOV zoom
renderer.domElement.addEventListener('wheel', (event) => {
event.preventDefault();
const fov = camera.fov + event.deltaY * zoomSpeed;
camera.fov = THREE.MathUtils.clamp(fov, minFov, maxFov);
camera.updateProjectionMatrix();
});
// Add touch events for pinch-to-zoom
let initialPinchDistance = null;
renderer.domElement.addEventListener('touchstart', (event) => {
if (event.touches.length === 2) {
initialPinchDistance = getPinchDistance(event);
}
});
renderer.domElement.addEventListener('touchmove', (event) => {
if (event.touches.length === 2) {
event.preventDefault();
const currentPinchDistance = getPinchDistance(event);
if (initialPinchDistance) {
const pinchDelta = initialPinchDistance - currentPinchDistance;
const fov = camera.fov + pinchDelta * zoomSpeed * 0.5;
camera.fov = THREE.MathUtils.clamp(fov, minFov, maxFov);
camera.updateProjectionMatrix();
}
initialPinchDistance = currentPinchDistance;
}
});
renderer.domElement.addEventListener('touchend', () => {
initialPinchDistance = null;
});
function getPinchDistance(event) {
const touch1 = event.touches[0];
const touch2 = event.touches[1];
return Math.hypot(touch1.clientX - touch2.clientX, touch1.clientY - touch2.clientY);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
// Handle window resizing
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
</script>
</body>
</html>