This September, I took a course that deals with the deepening of
design basics for digital media using examples of projects from the
field of editorial design. In addition to technical basics, the focus
is also on conceptual aspects, the area of UI/UX, and the exploration
of design boundaries. For this project, we were assigned to design a
website using a poster as inspiration. I imagined how the poster could
become interactive and used it as a starting point for the design. The
poster was for a techno event in the UK and featured a 3D-modeled
warehouse in the background. I sketched out ideas for a website where
users could scroll through the various sections of the event, starting
with the title and moving on to the line-up and curator. To bring my
vision to life, I used three.js, a JavaScript library, to create
interactive 3D elements on the website and Francis Belte created the
3D model of the warehouse.
Tree.js requires a lot of research and understanding of Java Script.
Luckily there are a verity of different resources online. But to
understand the answers to the questions you might have, a good base in
three.js is required. So if you are starting with three.js here is a
jump-start deep dive into my project and how it's made.
To start with three.js you have to set up the library. There are
different ways to do that, but to prevent having very slow loading
times I used a content delivery network (CDN).
Here is how that looks in HTML:
<script
async
src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js">
</script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.147.0/build/three.module.js",
"GLTFLoader": "https://unpkg.com/three@0.147.0/examples/jsm/loaders/GLTFLoader.js",
"OrbitControls": "https://unpkg.com/three@0.147.0/examples/jsm/controls/OrbitControls.js"
}
}
</script>
And in JS:
"use strict";
import * as THREE from "three";
import { GLTFLoader } from "GLTFLoader";
Once that is good to go you can start coding with three.js by linking
a .js file:
<script src="script.js" type="module"></script>
Let's set up our three.js scene with a camera and a renderer:
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer();
Here are a few lines that will handle the width and height of your
canvas relative to the perspective of your camera:
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
Now we are getting into the serious stuff, lol. Let's load a 3D shape.
Maybe challenge yourself to make a quirky shape in Blender, or
photogram your dog, idk, anything is better than grabbing pre-made
objects from sketchfap. Just make sure it's in a GLTF format. Here is
what the GLTF loader looks like:
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var loader = new GLTFLoader();
var mixer;
var model;
loader.load("export/warehouse.gltf", function (gltf) {
gltf.scene.traverse(function (node) {
if (node instanceof THREE.Mesh) {
node.castShadow = true;
node.material.side = THREE.DoubleSide;
}
});
model = gltf.scene;
scene.add(model);
});
After loading an object, apart from just looking at it we can add some
movement based on the position of your mouse, the scroll amount, or
many other things. I found this wonderful lerp function in a tutorial
by Sean Bradley (
https://sbcode.net/threejs/animate-on-scroll/
).
function lerp(x, y, a) {
return (1 - a) * x + a * y;
}
function scalePercent(start, end) {
return (scrollPercent - start) / (end - start);
}
const animationScripts = [];
start: 0,
end: 40,
func: () => {
camera.position.set(0, 3, lerp(10, 0, scalePercent(0, 40)));
camera.rotation.y = 0;
camera.rotation.x = 0;
},
});
animationScripts.push({
start: 40,
end: 60,
func: () => {
camera.position.set(0, 3, lerp(0, -5, scalePercent(40, 60)));
camera.rotation.y = 0;
camera.rotation.z = 0;
},
});
Okay I know you might feel a little overwhelmed right now by all this
copy-pasted code. But remember, you won’t understand everything in one
go. You have to go step by step or bird by bird, like Anne Lamott in
her book. Here is a quote from that book btw: "Thirty years ago my
older brother, who was ten years old at the time, was trying to get a
report on birds written that he'd had three months to write. It was
due the next day. We were out at our family cabin in Bolinas, and he
was at the kitchen table close to tears, surrounded by binder paper
and pencils and unopened books on birds, immobilized by the hugeness
of the task ahead. Then my father sat down beside him, put his arm
around my brother's shoulder, and said, 'Bird by bird, buddy. Just
take it bird by bird.”
Ready to finish your first three.js page? Call those functions and you
should be good to start your journey with three.js:
function animate() {
requestAnimationFrame(animate);
playScrollAnimations();
render();
}
function render() {
renderer.render(scene, camera);
}
window.scrollTo({ top: 0, behavior: "smooth" });
animate();