< Back

Threejs + Webflow = ๐Ÿ’™ (Part 2)

Continuing our journey of understanding Three.js and Webflow we look into how we combine our Three.js scene with HTML and using JavaScript to manipulate Three.js objects in the scene.

—– Journaling for Clarity —-
Signupย  and get LIFETIME access for only ยฃ4.99
Support our crowdfunding and
upcoming features for the product

Codepen: https://codesandbox.io/s/three-js-in-webflow-part-2-5z1oi8


Hello and welcome to another episode of Webflow and Code, where I teach you the underlying code you’re writing in Webflow.

Now this is going to be the second episode in our Three.js- I’m not going to call it a series for now, my goal is just to introduce you to Three.js and how to get it specifically inside of Webflow. So, with that we’re going to take a little bit further today and we’re going to actually start interacting with our Three.js scene from outside of Three.js and give you an idea of what I explained in the last episode which was that we’re kind of creating a bit of an illusion that the website itself is built inside of Three.js.

So let’s just dive right into it so, just to remind us of what we have going on, we have this basic scene where we’ve built the foundations of every single Three.js project which includes a scene, a camera, some geometry or parts of your scene seen in a renderer and then we’ve got our animate function here and we stuck a little box in there and we’ve started to rotate it baby, spin me round. The spinning is a bit boring or whatever and we can get rid of that.

What I’m going to do is show you how we can start to build an actual page out and then have our have it look like it’s part of our Three.js scenes.

Let’s pop into Webflow and let’s start building out our page.

Imagine this to be our kind of basic page here. I’ve made all of them 100 Heights so we can scroll through and this is our page.

So the next thing we need to do is make sure our webgl canvas element is kind of floating or is fixed behind our contents so if we do this by this webgl so I’ve just positioned it fixed and spread it across the screen if we save this perfect so if we scroll down then you’ll see that fixed background there.

#webgl {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: -1;

Now it’s the glorious task of creating the illusionโ€“ just make that whiteโ€“ creating the illusion that we’re interacting with our 3D elements in the background so what I’m going to do… I’ve recreated what we have going on in our Webflow document so I can have a good idea what’s going on so, what I’m going to do is position our box just slightly down so what the aim is here is that it’s going to look like we’re scrolling past that box. Wust a basic example and that should give us what we need so position our position y I’m going to make that 2.5. So you can see our box is kind of slightly down a little bit.

Now we need to track our position and this is combining the “real world” the website world into our Three.js world.

The first thing we’re going to do is bind a scroll event scroll event to the window, we’re going to fire this function on each scroll event and I’m just going to get the scroll position. We’re going to set that to the camera (dot) position (dot) y. So, it’s got a default position and I’m going to set that to the scroll position of the page so you can still see nothing’s going on, console log scroll position and you can see that we’re scrolling down the page.

window.addEventListener("scroll", () => {
  scrollPos = (window.pageYOffset || document.scrollTop) - (document.clientTop || 0) || 0;

Here it’s not a number (NaN) so what I need to do then make sure that it’s at least zero. There we go.

The next thing I’m going to do is actually animate the camera position so that as I scroll down the page the camera is moving down that page. Camera position y equals scroll position.

camera.position.y = scrollPosition;

Let’s just have a look at that. This is going to mess up because you can see that it goes way too fast and it’s actually going the opposite direction so the first thing we want to do is reverse our position, we’re starting to get somewhere, but it’s going too fast so we need to times this by 0.005 now this is going to be specific to the the project and the size of your web page as well so you want to play around with this number here to make sure it fits your scene and what you’ll see as we scroll down the page it looks like we’re interacting with our Three.js project. That’s exactly what we want.

[Journaling for Clarity Sponsorship – https://journalingforclarity.vercel.app]

Let’s take this a little bit step further to, again, just drive the idea home that all we’re doing is taking plain regular JavaScript and applying it to values inside of Three.js so what I’m going to do is every time we hover over one of these titles here well actually first of all let’s get this into Webflow. I’m sure there’s everything there. Publish. Here we go, perfect.

Let’s grab each of our H2S and we’ve made that into an array I know it works just loop through DOM elements but I just want to be double sure and make this into an array and with each of the titles we’re going to add event listener and we’re just going to do a mouseover… and we want to do a mouseleave and when we Mouse over we’re going to set a flag on isHovering true and we’re going to set that to false now we haven’t got it isHovering yet so it is we just create that and we’ll make it false.

let isHovering = false;

const titles = Array.from(document.querySelectorAll("h2"));
titles.forEach((title) => {
  title.addEventListener("mouseover", () => {
    isHovering = true;
  title.addEventListener("mouseleave", () => {
    isHovering = false;

So, we’ve got a basic hovering mechanism here that if we’re hovering over a title then we set this to True else we set it to false and then once again in our animate function all we’re going to do is go box dot material because it’s the material that has the colour value…and we’re going to say if is hovering then we want to do a new three dot colour let’s set it to blue and then…else we’ll set the colour back to Red.

box.material.color = isHovering
 ? new THREE.Color(0.0, 1.0, 0.0)
 : new THREE.Color(1.0, 0.0, 0.0);

For every title because if we’re hovering over one of them once we’re setting value to True when it’s leaving it we’re going to set it to false, if it’s true this is what this ternary statement is if it’s true? I think of it like if I’m asking the question, is it hovering? is this thing true? then it’s that otherwise set it to red here…oh something’s going on there I think I can see that it’s blue but it’s super dark for some bizarre reason let’s make it into green there you go so let me go in here. BOOM BOOM BOOM.

Before I wrap up let’s do one final thing and that is get have the Square Face the mouse position of the window so once again we want to go window out event listener, mouse, move and we want to store the mouse position inside of a variable so once again we’re going to go mouse equals X, Y so we’ve just got an object of X and Y setting the default values as zero and we want to on the mouse move we want to go Mouse dot X we want to set that to e dot client X, now the problem with this is is that over here it’s going to be zero and over here it’s going to be whatever the width of the window is and we don’t want that we want to normalize value between minus 0.5 and positive 0.5 so what we’re going to do is divide that by window dot inner width and the same with the mouse.y we’re going to go Y and then divide that by in a height minus 0.5 limit.

const mouse = {
  x: 0,
  y: 0

window.addEventListener("mousemove", (e) => {
  mouse.x = e.clientX / window.innerWidth - 0.5;
  mouse.y = e.clientY / window.innerHeight - 0.5;

The left hand value is the x value so it’s 0.5 over here and then a minus 0.5 over here and then mine and then 0.5 over on the right hand side same with top and bottom so we’ve got our values and once again we’re going to bring in GSAP so if we go GSAP docs, we’ve got GSAP the latest version of GSAP. We’re going to go GSAP dot two so we’re going to animate a property what property we’re going to animate the camera dot position…and we’re going to animate the X and Y values two Mouse dot X and mouse dot one.

Oh uh, we’re going to write the Box dot rotation sorry that I don’t know what I was thinking that so now our box is…so, it looks like the x is affecting the Y and the Y is affecting the X so. Let’s understand why what’s going on there..

gsap.to(box.rotation, {
  x: mouse.y * 0.5,
  y: mouse.x * 0.5

Editing Sam here: So what’s happening is you’ve got to imagine if a cube has two sticks running through it so a stick that’s going through it horizontally and it’s rotating around the x-axis that’s why it’s going kind of vertically and if there’s a stick going through the vertical axis then it’s rotating around that axis and it’s going side to side just figure that out so now we have our box that’s kind of rotating…based on our mouse position it’s kind of always looking at our mouse and again these numbers probably could be played with so we can halve it make it a little bit more smooth.

But you can see that once again we’re using JavaScript functions to manipulate our Three.js elements obviously the final thing to do right now then is to move all of this code into our old friend website and then we of course want GSAP in our script here. Publish. And here we have our moving box scrolling with our page.

So, I hope you enjoyed this short little tutorial if you want more of these or if you have certain questions about certain things I’ll do my best to answer them and if you want me to kind of go over something then do actually let me know join my Discord like subscribe and until next time happy no coding.