simple Three.js site

This commit is contained in:
Arnaud Lier 2025-02-18 10:37:35 +01:00
parent e33031c071
commit 830af4ac9b
11 changed files with 2306 additions and 1 deletions

View file

@ -93,6 +93,13 @@ services:
secrets:
- db_password
env_file: .env
site:
restart: on-failure
build:
context: ./requirements/bonus/site
dockerfile: Dockerfile
networks:
- inception
secrets:
db_password:

View file

@ -0,0 +1,16 @@
FROM alpine:3.21.2
LABEL org.opencontainers.image.authors="alier@student.42mulhouse.fr"
RUN apk add nodejs curl npm
COPY app/ /app
RUN cd /app && npm install && npm run build
EXPOSE 3000
HEALTHCHECK --start-period=5s \
CMD curl "http://site:3000/site/index.html" --fail || exit 1
ENTRYPOINT ["node", "/app/index.mjs"]

View file

@ -0,0 +1,20 @@
import Fastify from 'fastify';
import path from 'node:path';
import * as staticPlugin from '@fastify/static';
const fastify = Fastify({
logger: true
});
fastify.register(staticPlugin, {
root: path.join(import.meta.dirname, 'dist'),
prefix: '/site/',
})
try {
await fastify.listen({ port: 3000, host: 'site' });
} catch (err) {
fastify.log.error(err);
process.exit(1);
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,14 @@
{
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build src --outDir ../dist --emptyOutDir --base /site"
},
"dependencies": {
"@fastify/static": "^8.1.1",
"fastify": "^5.2.1",
"lil-gui": "^0.20.0",
"three": "^0.173.0",
"vite": "^6.1.0"
}
}

View file

@ -0,0 +1,115 @@
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import GUI from 'lil-gui';
const gui = new GUI();
const sizes = {
width: window.innerWidth,
height: window.innerHeight
};
const scene = new THREE.Scene();
const fontLoader = new FontLoader();
const textureLoader = new THREE.TextureLoader();
const gltfLoader = new GLTFLoader();
scene.add(new THREE.AmbientLight());
const light = new THREE.PointLight();
light.intensity = 50;
light.position.y = 6;
scene.add(light);
const matcapTexture = textureLoader.load('/site/textures/matcaps/gold.png');
matcapTexture.colorSpace = THREE.SRGBColorSpace;
const material = new THREE.MeshMatcapMaterial({ matcap: matcapTexture });
fontLoader.load('/site/fonts/helvetiker_regular.typeface.json', function (font) {
const textGeometry = new TextGeometry('oui oui baguette', {
font,
size: 1,
depth: 0.5
});
textGeometry.center();
const cubeMesh = new THREE.Mesh(textGeometry, material);
scene.add(cubeMesh);
cubeMesh.position.x = 0;
cubeMesh.position.y = 0;
gui.add(cubeMesh.position, 'y', -3, 3, 0.01);
gui.add(cubeMesh, 'visible');
gui.add(cubeMat, 'wireframe');
gui.addColor(cubeMat, 'color');
});
gltfLoader.load('/site/models/baguette.glb', function (gltf) {
for (let i = 0; i < 100; i++) {
const baguette = gltf.scene.clone();
baguette.position.x = (Math.random() - 0.5) * 10;
baguette.position.y = (Math.random() - 0.5) * 10;
baguette.position.z = (Math.random() - 0.5) * 10;
baguette.rotation.x = Math.random() * Math.PI;
baguette.rotation.y = Math.random() * Math.PI;
const scale = Math.random();
baguette.scale.set(scale, scale, scale);
scene.add(baguette);
}
});
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height);
camera.position.z = 5;
//const axesHelper = new THREE.AxesHelper(1);
//scene.add(axesHelper);
const canvas = document.getElementById('three');
function updateSize() {
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
}
const renderer = new THREE.WebGLRenderer({ canvas });
updateSize();
const clock = new THREE.Clock();
const controls = new OrbitControls(camera, canvas);
function render() {
const elapsedTime = clock.getElapsedTime();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
window.addEventListener('resize', () => {
updateSize();
});
window.addEventListener('dblclick', () => {
if (!document.fullscreenElement) {
canvas.requestFullscreen();
} else {
document.exitFullscreen();
}
});

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Baguette Land</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<style>
* {
margin: 0;
padding: 0;
}
#three {
display: block;
}
</style>
</head>
<body>
<canvas id="three"></canvas>
<script src="app.mjs" type="module"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View file

@ -31,4 +31,8 @@ server {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
location /site {
proxy_pass http://site:3000;
}
}