Hello everyone!
I currently have this script here: Nabil - Photos THREE JS
… but I would like to have the same movement capability (via the MacBook trackpad) as this website: SOOT
Here is my current script:
<script>
// Variables globales
let camera, scene, renderer;
let images = [];
let frustum;
let cameraViewProjectionMatrix;
const IMAGE_LOAD_DISTANCE = 50;
let imageBoundingBox;
let minZoom = 0, maxZoom = 50; // Valeurs initiales, peuvent être ajustées dynamiquement
let targetZPosition = 30;
// Initialisation Three.js
function initThreeJS() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xf5f5f5);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = targetZPosition;
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
const canvasContainer = document.getElementById('canvas-container');
if (canvasContainer) { // Vérification pour éviter une erreur si l'élément n'existe pas
canvasContainer.appendChild(renderer.domElement);
} else {
console.error("Élément 'canvas-container' non trouvé.");
}
frustum = new THREE.Frustum();
cameraViewProjectionMatrix = new THREE.Matrix4();
}
// Gestionnaire de chargement d'images (amélioré)
function loadImage(url, index, callback) {
const loader = new THREE.TextureLoader();
loader.load(url, texture => callback(texture, index), undefined, error => console.error(`Erreur de chargement de ${url}:`, error));
}
// Charge les images et les ajoute à la scène
function loadImages(imageUrls, scaleFactor) {
const loadingManager = new THREE.LoadingManager();
loadingManager.onProgress = (url, itemsLoaded, itemsTotal) => {
const percent = (itemsLoaded / itemsTotal * 100).toFixed(0);
const loadingIndicator = document.getElementById('loading-indicator') || createLoadingIndicator();
loadingIndicator.textContent = `Chargement : ${percent}%`;
if (itemsLoaded === itemsTotal) {
setTimeout(() => (loadingIndicator.style.display = 'none'), 1000);
}
};
imageUrls.forEach((url, index) => {
loadImage(url, index, (texture, index) => {
const width = texture.image.width * scaleFactor;
const height = texture.image.height * scaleFactor;
const geometry = new THREE.PlaneGeometry(width / 100, height / 100);
const material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide, transparent: true, opacity: 1 });
const mesh = new THREE.Mesh(geometry, material);
mesh.position.x = (Math.random() - 0.5) * 80;
mesh.position.y = (Math.random() - 0.5) * 40;
mesh.position.z = (Math.random() - 0.5) * 10;
mesh.userData.url = url;
mesh.userData.highResLoaded = false;
images.push(mesh);
scene.add(mesh);
if (index === imageUrls.length - 1) {
calculateImageBounds();
}
});
});
}
// Crée l'indicateur de chargement
function createLoadingIndicator() {
const loadingIndicator = document.createElement('div');
loadingIndicator.id = 'loading-indicator';
loadingIndicator.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: rgba(0,0,0,0.7);
color: white;
padding: 10px;
border-radius: 5px;
z-index: 1000;
`;
document.body.appendChild(loadingIndicator);
return loadingIndicator;
}
// Calcule les limites de la boîte englobante des images
function calculateImageBounds() {
imageBoundingBox = new THREE.Box3();
images.forEach(mesh => imageBoundingBox.expandByObject(mesh));
const size = new THREE.Vector3();
imageBoundingBox.getSize(size);
const diagonal = size.length();
maxZoom = Math.max(50, diagonal * 2);
camera.position.z = maxZoom * 0.5;
}
// Gestionnaire d'événements
function addEventListeners() {
const canvas = renderer.domElement;
let isDragging = false;
let mouseDownPosition = null;
let offsetX, offsetY;
// Gestion du déplacement de la caméra avec la souris
canvas.addEventListener('mousedown', (e) => {
isDragging = true;
mouseDownPosition = { x: e.clientX, y: e.clientY };
e.preventDefault();
});
canvas.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const deltaX = e.clientX - mouseDownPosition.x;
const deltaY = e.clientY - mouseDownPosition.y;
camera.position.x -= deltaX * 0.02;
camera.position.y += deltaY * 0.02;
mouseDownPosition = { x: e.clientX, y: e.clientY };
e.preventDefault();
});
canvas.addEventListener('mouseup', () => { isDragging = false; });
canvas.addEventListener('wheel', onWheel, { passive: false });
canvas.addEventListener('click', onClick);
// Gestion des événements tactiles (à réactiver si besoin)
// ...
}
// Gestionnaire de l'événement wheel
function onWheel(event) {
event.preventDefault();
const zoomSpeed = 0.1;
targetZPosition += event.deltaY * zoomSpeed;
targetZPosition = Math.min(Math.max(targetZPosition, minZoom), maxZoom);
camera.position.z = targetZPosition;
}
// Gestionnaire de clics sur les images
function onClick(event) {
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1);
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(images);
if (intersects.length > 0) {
openImageSlider(intersects[0].object.userData.url);
}
}
// Fonction pour ouvrir la boîte à lumière
function openImageSlider(imageUrl) {
// ... (votre code existant) ...
}
// Gestionnaire de redimensionnement de la fenêtre
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
calculateImageBounds();
}
// Boucle d'animation
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
// Fonction d'initialisation principale
function init() {
initThreeJS();
const cmsImages = document.querySelectorAll('[data-img="person"]');
const imageUrls = Array.from(cmsImages).map(img => img.src);
const scaleFactor = 0.23;
loadImages(imageUrls, scaleFactor);
addEventListeners();
animate();
}
document.addEventListener('DOMContentLoaded', init);
</script>
Can someone help me? Please.