Guide / Article

Grid to Fullscreen Animation

CJ Hersh
February 19, 2020
Grid to Fullscreen Animation

Creating Grid-to-Fullscreen Animations with Three.js in Webflow

Learn how to integrate a mind-bending Three.js animation in your Webflow project.


In a future tutorial, I’ll go into more detail about the custom CSS and Javascript - specifically, how you can further integrate and customize with Webflow’s native interactions. Make sure the CSS settings for each element match that found in the demo project.

1.0 Create Layout in Webflow

  • “Main” - This will be your top-level wrapper. In the element settings menu, make sure you change the tag from the default ‘div’ to ‘main’.
  • “app” - This is where the Three.js canvas will render after publishing the project.
  • “grid” - The grid will hold your grid items. If we expand the “grid” div, you will see three grid items. Each grid item contains the following:
  • 2 embedded thumbnail images (small and large)

In order to bypass CrossOrigin issues, it is imperative that your image embed code includes the attribute crossorigin="anonymous" as well as a “?” after the image URL.

  • The grid items caption
  • “fullview” - This holds the content for each item’s fullscreen state (title, link), as well as the button trigger to transition back to thumbnail.

2.0 Add custom CSS

<style>
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-y: overlay;
}
#app {
pointer-events: none;
}
.fullview {
pointer-events: none;
 -webkit-overflow-scrolling: touch;
}
.fullview__item--current {
pointer-events: auto;
}
.fullview__item-title {
 opacity: 0;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.link {
 opacity: 0;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.fullview__close {
pointer-events: none;
opacity: 0;
 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.fullview__item--current ~ .fullview__close {
pointer-events: auto;
}
.fullview__close:focus {
outline: none;
}
.grid__item-img {
max-width: 100%;
display: block;
cursor: pointer;
}
.grid__item-img--large {
pointer-events: none;
position: fixed;
opacity: 0;
}
</style>
  1. Add custom Javascript scripts and code
< script src = "https://assets.website-files.com/5ce62dab952a22dd060278e3/5ce62dbe5375ca4e2e927f78_three-bundle.txt" > < /script>
< script src = "https://assets.website-files.com/5ce62dab952a22dd060278e3/5ce62e295375ca5dfd927fc8_demo-core.txt" > < /script>
< script src = "https://assets.website-files.com/5ce62dab952a22dd060278e3/5ce62e29952a223c080279af_demo.txt" > < /script> < script >

let currentIndex;
const itemsWrapper = document.getElementById("itemsWrapper");
const thumbs = [...itemsWrapper.querySelectorAll("img.grid__item-img:not(.grid__item-img--large)")];
const fullviewItems = [...document.querySelectorAll(".fullview__item")];
const backToGridCtrl = document.querySelector(".fullview__close");
const transitionEffectDuration = 1.2;
const transitionEffect = createDemoEffect({
activation: {
type: "mouse"
},
timing: {
duration: transitionEffectDuration
},
transformation: {
type: "simplex",
props: {
seed: "8000",
frequencyX: 0.2,
frequencyY: 0.2,
amplitudeX: 0.3,
amplitudeY: 0.3
}
},
onToFullscreenStart: ({
index
}) => {
currentIndex = index;
thumbs[currentIndex].style.opacity = 0;
transitionEffect.uniforms.uSeed.value = index * 10;
toggleFullview();
},
onToGridFinish: ({
index,
lastIndex
}) => {
thumbs[lastIndex].style.opacity = 1;
fullviewItems[currentIndex].classList.remove("fullview__item--current");
},
seed: 800,
easings: {
toFullscreen: Power1.easeOut,
toGrid: Power1.easeInOut
}
});
transitionEffect.init();
const toggleFullview = () => {
if (transitionEffect.isFullscreen) {
TweenLite.to(fullviewItems[currentIndex].querySelector(".fullview__item-title"), 0.2, {
ease: Quad.easeOut,
opacity: 0,
x: "5%"
});
TweenLite.to(fullviewItems[currentIndex].querySelector(".link"), 0.2, {
ease: Quad.easeOut,
opacity: 0,
x: "5%"
});
TweenLite.to(backToGridCtrl, 0.2, {
ease: Quad.easeOut,
opacity: 0,
scale: 0
});
transitionEffect.toGrid();
} else {
fullviewItems[currentIndex].classList.add("fullview__item--current");
TweenLite.to(fullviewItems[currentIndex].querySelector(".fullview__item-title"), 1, {
ease: Expo.easeOut,
startAt: {
x: "5%"
},
opacity: 1,
x: "0%",
delay: transitionEffectDuration * 0.6
});
TweenLite.to(fullviewItems[currentIndex].querySelector(".link"), 1, {
ease: Expo.easeOut,
startAt: {
x: "5%"
},
opacity: 1,
x: "0%",
delay: transitionEffectDuration * 0.9
});
TweenLite.to(backToGridCtrl, 1, {
ease: Expo.easeOut,
startAt: {
scale: 0
},
opacity: 1,
scale: 1,
delay: transitionEffectDuration * 0.6
});
}
};
backToGridCtrl.addEventListener("click", () => {
if (transitionEffect.isAnimating) {
return;
}
toggleFullview();
});
imagesLoaded(document.querySelectorAll(".grid__item-img"), instance => {
document.body.classList.remove("loading");
let images = [];
for (var i = 0, imageSet = {}; i < instance.elements.length; i++) {
let image = {
element: instance.elements[i],
image: instance.images[i].isLoaded ? instance.images[i].img : null
};
if (i % 2 === 0) {
imageSet = {};
imageSet.small = image;
}
if (i % 2 === 1) {
imageSet.large = image;
images.push(imageSet);
}
}
transitionEffect.createTextures(images);
}); < /script>


  1. Publish



This guide has been developed by CJhersh.

https://www.cjhersh.com
https://webflow.com/cjhersh



Original Author: Daniel Velasquez

More Technical Details: Here  


CJ Hersh
February 19, 2020

Recieve webflow resources directly to your mailbox.

Sign up to get weekly insights & inspiration in your inbox.

OTHER GUIDES & LESSONS

Boost your webflow site further.