< Back

Three.js + Webflow = 😍

We add the awesome Threejs WebGL framework into Webflow and build out all the necessary components to adding into Webflow (Part 1).

Threejs: https://threejs.org

Codesandbox: https://codesandbox.io

My Website: https://jupiterandthegiraffe.com

Transcript

All right, hopefully you can hear me I seem to have lost the tripod to my microphone. Seems to have disappeared along with my dignity.

So I’ve been a fan of Three.js for quite some time, in fact my company website is built in Three.js.

Recently I’ve been getting more into it and trying to understand a lot more about what three.js is and what makes it tick. In order to reaffirm my knowledge I thought I would begin to build a three.js website inside of Webflow although we’ll be building this outside of Webflow there are certain workflows and things that are specific to Webflow.

So we’re gonna dive in and I’m going to start putting together a three.js website inside of Webflow.

I would suggest using Codesandbox and that’s mainly because you can actually access the entire raw HTML files so if you haven’t got a Codesandbox account you can sign up, it’s free and we’re just starting with a basic template.

With three.js there is going to be a base set of code that you’re going to use for absolutely every single project. It’s going to be basically setting up a scene, the camera and the renderer I think and then of course like lighting and obviously the objects that you’re in it. And that’s what we’re going to cover today is just getting a basic scene loading inside of Webflow and that you’ve kind of got a bit of a workflow where you can build it in Code Sandbox and transfer the code over so we’re just going to do something very very basic right now but hopefully get you set up and using three.js.

If you want to see more of this sort of stuff let me know because I’ll teach as I refresh my knowledge on three.js so I can bring you along for the ride a little bit with me so do let me know if you want to see more three.js tutorials but of course this is going to be more than enough fo some people just to get it up and running and then of course three.js is their oyster.

I’m just going to refer to the three.js docs here so if I jump into threej.s docs, let’s get it loading in a way that we know it’s going to load inside of Webflow and what we’re going to do we’re going to use this “Install CDN or Static Hosting” because of course we can’t store JavaScript files on our Webflow server yet so let’s use a the CDN hosting version of three.js.

So the first thing we’re going to do is copy this and what this is it’s basically a it’s a polyfill that enables us to do all this fruity stuff here like the type module import map and various things like that. It’s nothing to do with three.js it’s simply to enable older browsers to use this newer technology which maybe by the time you’re watching it we won’t need to import that and for that I would suggest just diving into the installation on threejs.org and just seeing what they suggest basically but at this point as of the 9th of February 2023 we need to import this polyfill.

Jumping in to Code sandbox let’s go into the body and there’s copier and that polyfill.

<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>

The next thing we’re going to do, this is basically what libraries we want to load into our JavaScript and what do we want to pipe the the name of that to and that’ll make sense in just a second so let’s just copy it return enter that.

Basically what we’re saying we’re going to load this Library here and you’ll see we need to see specify the version we’re going to load this Library here and we’re going to pipe it into the name or Library file of ‘three’ right and we’re going to use that in a second but let’s sort this version out here.

The easiest way to do that is probably to go to or to understand what the latest version is probably go to threejs npm here we go so on the npm page here you’ve got the 0.149.0 so if we copy that place it in the version here and save that.

<script type="importmap">
  {
    "imports": {
      "three": "https://unpkg.com/[email protected]/build/three.module.js"
    }
  }
</script>

The final thing we’re going to want to do is actually load in three.js so let’s just copy this piece of code here on there and script of type module this means it’s going to use the new module definition system I actually don’t know a lot about that but ultimately you look more familiar with some of the code that you would write when you’re bundling all this JavaScript together.

So you’ll see I’m importing start as three so I’m basically importing everything as this kind of capitalized three variable from a library called three and that will match the Imports here.

So if I save that and actually look into our page here Network refresh that we should see three.js loading in which is exactly what we want.

<script type="module">
  import * as THREE from "three";

  const scene = new THREE.Scene();
</script>

That’s the raw setup we’re going to go a lot further and create the scene right now but this if we were to copy and paste this into an embed element, let’s just do that actually, let’s copy and paste this into an embed element on our Webflow website.

Just as a point before we just do this the general idea behind a three.js website is it I think of it kind of like an illusion what you’ll see if you’re going to Jupiter and the Giraffe’s website you’ll see I have kind of a background there that the logo rotates towards the mouse and does this filtering thing as you as you move the mouse towards the edges it’s a fixed canvas in the back and although the design stipulates that everything is just on the the sort of page there other websites where you scroll down and you can see things happening and 3D models moving and whatever interacting what that is is a fixed canvas behind a fixed element behind a normal HTML page so you’ll build your HTML page as normal and you place a canvas behind it which will which we’ll go into now and then as you scroll down that page you’re moving a camera and you’re you’re triggering elements and things like that to the scroll position of the the page and so it looks like you’re scrolling through a long three.js scene or something like that but it is it’s an illusion. You’re just fixing a canvas element and playing through and doing all sorts of nonsense which you may or may not get to in the future but that just just to kind of clear up what inevitably is a three.js website.

Right so let’s dive into here and let’s create an embed element and just paste that code that we’ve gone and done and if I save and close that publish this and go visit this page. Refresh that. You’ll see that we we’re bringing in three.js.

So we’ve done the groundwork here and now we’re ready to build out our scene so we’re importing three.js and we’re instantiating a new scene, right. This is the scene iswhere everything lives and where you’re going to be importing cameras and lights and various things like that.

So what we first need to do is actually create an element to almost bind this stuff into so once again if I create a canvas HTML element and give that some sort of ID as webgl there’s like a common convention here we, just uh had a yogurt by the way and moved the camera a little bit.

// HTML
<canvas id="webgl"></canvas>

// JavaScript
const canvas = document.getElementById("webgl");

Grab our canvas element and load our scene into it so equals canvas canvas equals document dot get webgl and then we’re going to create a renderer that’s going to render everything inside of this canvas element equals new three top web GL renderer and we’re going to provide it with a canvas and you can either go canvas Canvas OR because they’re the same we can just leave it like that and then we can just clean that up there.

const renderer = new THREE.WebGLRenderer({ canvas });

The next thing we’re going to want to do is actually set the pixel density of our scene now there’s no point in rendering unnecessary pixels so we can do that by setting this the the pixel ratio on our renderer so render rot set pixel ratio and we’re going to use a bit of JavaScript which is going to choose the lesser of two numbers so we’re going to do that by going math dot Min so the the lesser of a given set of numbers so we’re going to provide it at number two and we’re going to give it the actual density of the device itself and we can get that by going window dot device pixel ratio and so this means if your pixel ratio is one then that is the lesser of two or one then it’s going to set the pixel ratio to that is 1.5 obviously that’s less than two if it’s two then it’s gonna just choose two if it’s six then two is less than six so it’s going to choose two in that respect so it’s just plain old JavaScript nothing fancy there. Just making sure that we don’t render too many pixels because above two and you’re getting into goo-goo land there’s nothing really beneficial of rendering for a pixel density of six or something like that at all it’s all snake oil.

renderer.setPixelRatio(Math.min(2, window.devicePixelRatio));

Then we’re going to set the size of the renderer to window dot inner width and window dot in a height.

renderer.setSize(window.innerWidth, window.innerHeight);

Now we need to create a camera for our scene so that we can see everything that’s been created in there so we do const camera and we’re going to do a perspective camera which is like a basic perspective camera a basic camera and we’re going to set the field of view as 75 which seems quite natural we need to set a a ratio or an aspect ratio and we’re going to do that by going window dot in a width divided by window dot in height (corrected) and then we’re going to go we’re going to set a near and a far value and you have to worry about these too much this is just to get the scene working but as you dip into more advanced three.js you’re probably going to care a lot about the near and the far and the the field of view and various things like that.

So we’ve created our camera we’re just going to move it back a little bit and we’ll get into why a little bit later on. we’ll set the Z which is the x y z so we’re going to set this to 5 and then as with everything we’re going to create from this point onwards we need to add it to the scene so we simply do that by going scene add camera.

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
scene.add(camera);

Now with all that being said we need to bring these together now let’s bring the scene and the camera together now in fact it probably makes more sense to do that and then we’re going to go renderer dot render scene camera.

renderer.render(scene, camera);

Brilliant that’s kind of exactly what we expected obviously nothing is in the scene right now but you’re seeing that something is happening right now so now you should add some stuff to the scene and this confused me no end when I first started out learning three.js. There’s basically two elements that make up things within the scene. You’ve got the geometry itself and then you’ve got material that you apply onto the geometry and then you bind them together using a mesh. You mesh them together basically.

This would always confused me for some reason but just know that we need to create the geometry we need to create the material and then we need to bind them together so let’s just do that now by creating a simple square or a box rather. So const John tree equals new three dot box geometry and the Box geometry takes three values it’s the width and the height and the the depth so we’re just going to put one one one right now.

So there’s our geometry and now we need to create a material so const material equals new three mesh basic material.

There’s a bunch of pre-built materials that you can use but we’re just going to use mesh basic material at the moment and we want to give it a colour of red and now we want to bind these together using a mesh so const box equals new three mesh and then we take the geometry and the material and then we add that mesh to the scene so scene add box. Refresh this. And Viola!

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const box = new THREE.Mesh(geometry, material);

We can see it’s a little bit stretch and I think I know why we’ve got these the wrong way around. refresh and there you go there’s our box.

Wonderful now this is not much fun right now because we have a box or a cube in our scene and we’re rendering out and then we’re kind of leaving it be and the beauty of obviously 3GS is that we can animate things and move things so the final piece to our puzzle will be to create a what’s known as a tick function or an animate function which runs on every refresh cycle of the screen so I’ve got 120 hertz monitor here going to run 120 times a second and whatever your refresh rate is on your screen will run that many times.

Then we’re going to update the graphics on each of these ticks or animations or whatever it is you want to call them so first of all we need to create the function that should be called on every render so let’s call this “tick” and simple function and the next thing we’re going to want to do is just render our scene inside of that function as opposed to just once on on load and the next thing we’re going to want to do is recall this function on the next animation tick so we do this with a JavaScript function called requestAnimationFrame and then we’re going to provide it a function with which is itself so it’s a self-looping function.

if I save this and and refresh that you’ll see that nothing is happening right now that’s because we’re not giving we’re not calling this function an initial time so once you set it off it’s going then baby, it’s going.

If I refresh that you’ll see that the cube is back in there and to really show that we’re rendering this scene we’re going to animate this Cube by simply going to box dot rotation dot X plus equals five let’s just do that let’s say– that’s a bit fast Isn’t it. let’s do 0.01 be a bit more sensible and you’ll see our box now is rotating!

const tick = () => {
  camera.rotation.y += 0.001;

  renderer.render(scene, camera);

  window.requestAnimationFrame(tick);
};

tick();

// OR (Updated)

renderer.setAnimationLoop( tick );

function tick() {
  camera.rotation.y += 0.001;

  renderer.render(scene, camera);
};

Actually, to be fair, the final bit of the puzzle is what you’ll see is if we refresh the resize this you can see that we’re getting some problems here so we need to now resize this window or our canvas on whenever the window is resized so we can do that with a plain old JavaScript function window and event listener resize call this function here and we want to resize this renderer so we can do that with camera dot object updateProjectionMatrix, set size of window dot in a which window dot in a height and then we want to set the aspect ratio of the camera once again to window in it anyway it’s divided by window dot innerHeight, so the same thing we saw in our camera up here refresh that we’re going to listen out for that and you’ll see that it resizes and everything is hunky-dory.

window.addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);
});

So that is basically our foundational project there we’ve got some geometry we’ve got a camera we’ve got a scene we’ve got an animate function and we’ve got a resize function and this again will be used on every single project every single three.js project you’ll ever use minus obviously the geometry and all the rest of it we can get into that in a later episode so make sure you let me know if you want that.

So let’s get this into Webflow just to show that it’s working I’m going to copy and paste all that so we’ve got our webgl element loading all that in save and close. Publish. And there you have it we have a three.js scene loading inside of Webflow and now the world is our oyster.

So let me know what you think of this episode by hit me up with a like if you’re interested in discussing more about this then do join my Discord it’s a thriving Community there where we all chat about anything from three.js to general no code tools that people are bringing to the table. I’ll leave a link down in the description if you want to see more of this stuff then obviously subscribe and with that I will see you in the next one. Boom.