Jump to content

Search the Community

Showing results for tags 'threejs'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • GreenSock Forums
    • GSAP
    • Banner Animation
    • Jobs & Freelance
  • Flash / ActionScript Archive
    • GSAP (Flash)
    • Loading (Flash)
    • TransformManager (Flash)

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge


There are no results to display.

Find results in...

Find results that contain...

Date Created

  • Start


Last Updated

  • Start


Filter by number of...


  • Start



Personal Website



Company Website



  1. Hello, so I have a 3D element made with Three.JS that is perfect. I try to modify it with gsap and scrollTrigger. I tried to do it with one trigger first and it worked perfectly. But when I try to to multiple changes to that element at different time with scrollTrigger it changes the original element's value. Like in the codePen when you first scroll you see that the square is not really a square at the begining but when you scroll a bit more It jumps to a square. And I don't know at all why it happens. I also tried to put a fromTo to all but did not change a thing. I really need help plz :))
  2. I want to change the widthSegments of my box using a gsap timeline, but when I try it's doing nothing. For now, I've tried this: const tl = gsap.timeline(); tl.fromTo( cubeGeo.parameters, { widthSegments: 1, yoyo: true, repeat: -1, }, { widthSegments: 2, yoyo: true, repeat: -1, } );
  3. Hi, Its been a week since I started working with GSAP, so I am very noob, I came across this animation in ThreeJs and I was wondering if such thing is possible with GSAP.
  4. Hi, I'm trying to achieve a basic threejs animation using GSAP scroll trigger. but its not working here (codepen sample).
  5. Hi , have a nice day any one know how we can play gltf animation with scroll use scroll trigger ??
  6. const assetLoader = new GLTFLoader(); var mixer; var model; assetLoader.load("https://cdn.glitch.global/5213cd0b-d594-4b34-9064-2f1f38b42c78/cube33.glb?v=1665271977633", function(gltf) { gltf.scene.traverse(function (node) { if (node instanceof THREE.Mesh) { object.frustumCulled = false; node.castShadow = true; node.material.side = THREE.DoubleSide; } }); model = gltf.scene; model.scale.set(1,1,1) model.position.setY(-1); model.position.setX(2); model.position.setZ(-2); model.rotation.x = Math.PI / 2; model.rotation.y = Math.PI / 2; model.rotation.z = Math.PI / -2; scene.add(model); camera.position.z = 4; /// MIXER&ACTION CONFIG/// mixer = new THREE.AnimationMixer(model); var action = mixer.clipAction(gltf.animations[1]); action.play(); var actiona = mixer.clipAction(gltf.animations[1]); action.play(); createAnimation(mixer, action, gltf.animations[1]); } ); var clock = new THREE.Clock(); function render() { requestAnimationFrame(render); var delta = clock.getDelta(); if (mixer != null) mixer.update(delta); renderer.render(scene, camera); } render(); function createAnimation(mixer, action, clip) { let proxy = { get time() { return mixer.time; }, set time(value) { action.paused = false; mixer.setTime(value); action.paused = true; } }; /// GSAP CONFIG/// function GSAP(){ gsap.registerPlugin(ScrollTrigger) ScrollTrigger.defaults({ scrub: 3, }) gsap.set(model.position, {x:-0.70,y:-1.80 ,},) gsap.to(model.position, { scrollTrigger: { trigger: ".section-four", start: "top top", toggleActions: "restart play none reset", //onLeave: myLeaveFunc, //onLeaveBack: myLeaveFunc end: '+=2000px', }, x:-1, y:-3 , }); let scrollingTL = gsap.timeline({ scrollTrigger: { trigger: ".section-four", ease: "Power4", end: '+=5000px', pin: true, scrub: 2, onUpdate: function () { camera.updateProjectionMatrix(); } } }); scrollingTL.to(proxy, { time: clip.duration, repeat: 0, }) /// I NEED TO RUN ANIMATION [1] HERE /// let scrollingTL1 = gsap.timeline({ scrollTrigger: { trigger: ".section-five", ease: "Power4", end: '+=5000px', pin: true, scrub: 2, onUpdate: function () { camera.updateProjectionMatrix(); } } }); scrollingTL1.to(proxy, { time: clip.duration, repeat: 0, }) } GSAP() }
  7. My camera lags very much.. I dont know why. When its reaches trigger 5 its rotates and then it becomes normal. and when its reaches trigger 7 its lives own life:(
  8. Hi, I'm new to this area of gsap, I was looking for projects that had Threejs and Gsap as tools. Reference: https://architect-opinion.art I was thinking of doing something similar/prototype for the above reference. His concept of "camera" following a path that was "modeled", "generated", and having some interactions within that "trip". But I don't know where to start, and I don't know the "names" people give to this kind of programming or modeling inside threejs and Gsap. Could you help me find the "names" (3d scene, scene interaction) of these codes and where possibly they are done in threejs or gsap?
  9. Hi there lovely developer community. I‘m looking for a front end dev to do a cool little website project. It’s something along the lines of: https://croing.com/ It’s just a one pager with 2 other pages. The rest is external links. It’s pretty simple/straightforward in general, I think. But it has some 3D obj or fbx elements which need to spin around and the site should have nice transitions, UI/ rollover animations and feel fluent/responsive. If you know what I mean? I’m a creative designer. Not a developer but I imagine it's WebGL using ThreeJS or some sorts. I have figma design and all the 3D assets etc. ready to go If you are interested please get in touch Thank you very much Sebastian
  10. Hi Everyone, I have been working on the project involving WebXR, using ThreeJs and Gsap 3. And I have notice that when you initialize webXR session (clicking on 'Enter VR' button) update of Gsap's timelines just stops. They mention in How to create VR content on ThreeJs' website that you need to call setAnimationLoop() from their renderer and to pass callback and that you can't use window.requestAnimationFrame() function (I need to investigate this topic more). The problem was solved calling gsap.ticker.tick() from the callback function. For testing, I have added listener to gsap.ticker and it was working fine when webXR session is not initialized. Is there a better method to update gsap timelines, and am I missing something? I used Oculus Quest for headset and Oculus Browser which is based on Chromium.
  11. Hey guys, I'm having some trouble on something this evening, was wondering if you guys could help. Given that this uses a 3d model, I can't attach a codepen unfortunately. But I'll do the best to include all relevant code snippets and give all the details I can. I've been working on a website that uses scroll trigger to move content around, and also to move around this 3D car model that I have. I have 4 different slides, and for the sake of simplicity, I've gone ahead and recoloured them. Slide 1: Blue, start slide Slide 2: Pink, slides in from the right Slide 3: Yellow, slides in from bottom Slide 4: Green, slides in from the right Now Slide 4 is the main culprit, I'm trying to move this car around to have the car in the 4th slide look like the image below: However, the transition to the image is a little less than sleek. I've attached a video of how the transitions currently look, scrolling between these different slides. Ignore the music, I just recorded this very quickly on my ShadowPlay. Now let's talk about the code I've got. I'm trying to use ScrollTrigger to move between all of these, and I created a variable for a timeline just so I could keep it all in check (or so I thought). Here's what I have thusfar. scene.rotation.set(0, 9.8, 0) camera.position.set(-1.2,0,5) let car_anim = gsap.timeline() // Slide 2 car_anim.to(scene.rotation, {y: 4.79, easing: Power1.easeInOut, scrollTrigger: { trigger: "#slide2", scrub: 1, }}, 0) car_anim.to(camera.position, {x: -0.1, easing: Power1.easeInOut, scrollTrigger: { trigger: "#slide2", scrub: 1, start: "right right" }}, 0) // Slide 3 car_anim.to(scene.rotation, {z: 1.6, easing: Power1.easeInOut, scrollTrigger: { trigger: "#slide3", scrub: 1, start: "top top" }}, 0) // Slide 4 - The problem child car_anim.to(scene.rotation, {z: 0.02, y: 3.1, easing: Power1.easeInOut, scrollTrigger: { trigger: "#slide4", scrub: 1, start: "right+=2500 right" }}, 0) car_anim.to(camera.position, {x: 0.16, easing: Power1.easeInOut, scrollTrigger: { trigger: "#slide4", scrub: 1, start: "right+=2500 right" }}) I start out with setting a base camera position and scene position. The scene position refers to the car, and the camera just refers to the camera. The first three slides work well. I have another video somewhere of all of those working just fine. I'm just having trouble of smoothly continuing the movements of the car. It's not a ThreeJS issue I don't think. I'm pretty sure it's just the start of the scroll trigger, given that the other ones have worked fine. I guess it's as I've started making more complex movements. So yeah, how do you think I could get these working at all? I'm not entirely sure what I'm doing wrong to be very honest with you. Thanks in advance, and sorry for the lack of codepen - it's a little hard to do with all the technical set up. UPDATE: Just an edit after I've played around with it a bit more. I think it's becoming less and less of a gsap issue, but I'll keep this thread up in case anyone else knows how to solve it / it can be used as a future reference. It seems as if when I modify a different axis more than once (i.e. the y-axis), it updates the value weirdly. I don't have console log proof, but I messed around with the 4th slide and it seems to transition fine when I set it to affect the x-axis - a property that has yet to be used with the scene rotation.
  12. Hello, So i used the ScrollTrigger skew example to tilt the three js camera instead the image skew property. Apart from that, a text div is being translated and sphereGroup is being rotated using gsap value & it is working nicely The problems i face with velocity are: 1 ) there is no smoothing happening when going to the calculated position 2) the above problem also leads to jerk when scroll direction is switched it 3) with mouse wheel the the incremental jumps does not look nice (which could also be solved with better smoothing maybe?) any tips ? suggestions for better gsap to three logic also welcome last function in codpen has all the gsap properties
  13. Guest

    Add some parallax effect threejs

    Hello , i try to add some parallax effect between camera and cube , like make the cube faster than camera any tips ?, then how i can make scroll smooth ?
  14. Hi ! Apologies in advance, I'm a musician / digital artist and a total beginner with gsap (like 2 days ago) but also very new to Js, React and Three.js. I'm really amazed how easily gsap handles animation of any params compared to other solutions I found in the past. It will make my life so much easier, I'm already considering to join the Greensock club soon...! Since yesterday I've been hitting my head against the wall and I can't figure this out. Here's the sandbox : https://7cuco.csb.app I have this button that triggers random variations of color and rotation speed of a cube. I wanted gsap to smooth every random value by a few seconds. I managed to make this happen very easily for the rotation speed (I guess because I worked from a simple object) but for some reason it doesn't work as excepted with the Three.color object. Every click resets the color to black, before moving gradually to the selected color. Almost... I'm really sorry in advance, I expect this to be a really stupid mistake. Thanks in advance for your help !
  15. Hi everyone! Working on a threejs project, so I need to animate an group of values or some Vector3. In tween I used to do but with gsap it dont work, what I'm doing wrong? There are two cases. 1. Is there any difference betwenn an array or an obj? // as Array const startValues = { a: 0, b: 10, c: 20 } // as Obj const startValues = [ 0, 10, 20 ] // as Array const endValues = { a: 20, b: 50, c: 40 } // as Obj const endValues = [ 20, 50, 40 ] gsap.to(startValues, { endValues, onUpdate() { // How reach those values in both cases? }, duration: 6 }) 2. const startValue = { a: new THREE.Vector3(0,0,0) } gsap.to(startValue, { a: new THREE.Vector3(1,10,5), onUpdate() { console.log( this.targets()[0].a ) // Logs me [Object object] }, duration: 6 }) Thanks for helping!
  16. Hello , i try to change light intensity on scroll with some fade using scroll trigger ``` gsap.to(nightShadowLight.intensity, { intensity:0, scrollTrigger: { trigger: renderer.domElement, start: 'top top', end: '+=500%', pin: true, scrub: true }, onUpdate: function () { }, }) ```
  17. So i would like to animate this model along a path: https://codepen.io/uiunicorn/pen/abJmVwo but it doesn't seem to work and i am getting this in console: Uncaught TypeError: Cannot assign to read only property 'rotation' of object '#<Group>' at Plugin._setterPlain [as rSet] (gsap-core.js:3367) at PropTween.render [as r] (MotionPathPlugin.js:301) at Tween.render (gsap-core.js:3163) at _lazyRender (gsap-core.js:187) at _lazySafeRender (gsap-core.js:193) at Array.updateRoot (gsap-core.js:2564) at _tick (gsap-core.js:1252) and ideas of what the problem is? here is the original pen that works: (my pen uses modules): https://codepen.io/uiunicorn/pen/zYZoYpV
  18. Hi everyone! I was user of tween, there I can do something like this. Where e is the current value throung the time... so if I log in onUpdate the e value logs the exactly value in time. const n2bt = new TWEEN.Tween({x: 0}) .to({x:1}, 1650) .onUpdate((e) => { console.log(e.x) }) .start() } How can I do this with gsap?
  19. My goal is update a Three JS scene (colors, camera position, material properties, etc.) based on state properties set by the timeline. My scene is rendered inside of the BlobScene component which accepts an intensity prop. In the sample below, I'd like to update the intensity as the timeline is scrubbed which then updates the light intensity of my scene. In the pinned section, there are two columns: the left column contains text that will be translated into view and the right column contains the BlobScene. My ultimate goal is to change the color of the blob for each corresponding text section. So when the user scrolls from the red section to the green section, for example, the blob mesh would smoothly transition it's material color from red to green. Am I going about this the wrong way? I can create a minimal demo if needed. import React, { useState, useEffect } from "react" import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import BlobScene from '../components/blob-scene' function Index() { let [intensity, setIntensity] = useState({value: 1.5}) useEffect(() => { gsap.registerPlugin(ScrollTrigger) // Verticals Pinned Section Story const tl = gsap.timeline() tl.from(".red", {y: "100%"}) .from(".green", {y: "100%"}) .from(".blue", {y: "100%"}); // PROBLEM LINE tl.to(intensity, { value: setIntensity(0.5) }) ScrollTrigger.create({ animation: tl, trigger: "#verticals", scroller: "#___gatsby", start: "top top", end: "+=4000", scrub: true, pin: true, anticipatePin: 1 }); // each time the window updates, we should refresh ScrollTrigger and then update LocomotiveScroll. ScrollTrigger.addEventListener('refresh', () => window.scroll.update()) ScrollTrigger.refresh() }, [intensity]); return ( <React.Fragment> <div className="page"> <section id="verticals" className="h-screen flex items-center relative w-full overflow-hidden"> <div className="grid grid-cols-2 gap-6 h-full w-full"> {/* Grid Column 1 */} <div className="flex items-center"> <div className="relative w-full overflow-hidden h-80"> <div className="panel absolute h-full w-full red bg-red-500 text-black"> <h2>Panel 1</h2> </div> <div className="panel absolute h-full w-full green bg-green-500"> <h2>Panel 2</h2> </div> <div className="panel absolute h-full w-full blue bg-blue-500"> <h2>Panel 3</h2> </div> </div> </div> {/* Grid Column 2 */} <div className="flex items-center"> <BlobScene intensity={intensity.value}></BlobScene> </div> </div> </section> </div> </React.Fragment> ) } export default Index
  20. Guest

    ThreeJs with gsap

    Hello, have a nice day , i have problem with control in three js and gsap , any one know tutorial for this? for example i want to zoom camera with scrolling but i don't know how , and many thing like this , this is my code ` .to(camera.position, 2, { y: -11.1, duration: 2, }, "simultaneously") `
  21. I use MotionPathPlugin but i can't change path style, and don't know to move 3d model into path by scrolling
  22. Hello everyone, Let explain my problem, I am currently moving an object a long a x,y,z axis (in threejs). I want to have complex trajectory, like a looping : i tried to use the motion path plugin in order to do interpolation across multiple point. So far so good, but i need to use the bezier type in order to make it as a real looping (not a cubic one :) ) but bezier type seems supporting only x and y axis. The other main problem is to slow down the moving element on mouse hover, i think using the timeScale function on hover will do the job perfectly. Do you have any hints ? Thanks a lot
  23. Hello, I am trying to create an explosion on one button click and reverse of another button click of particles on three.js and TimelineMax, is there a simple example or place i can learn from? Please kindly let me know Thank you
  24. Hi everybody! I'm trying to display a three.js scene inside a div in my html, but i can't figure out how. I've posted in the three.js forums, but it seems it's an UI issue and not a three.js one so.. here i am! Here is a jsfiddle trying to replicate the issue : JSFIDDLE So i want my three.js animation to appear in my <div id="canvas-projects"></div>, but my images don't appear. If i put my section containing the <div id="canvas-projects"></div>as my first html element, it works fine and the images appears. But it's supposed to be in the middle of my page. So my guess i that my positioning isn't good somehow. But i can't figure out how to make it work! If anybody could take a look at this and help me, i'd be super greatful! Here is my current javascript code : const store = { ww: window.innerWidth, wh: window.innerHeight, isDevice: navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i) }; class Slider { constructor(el, opts = {}) { this.bindAll(); this.el = el; this.opts = Object.assign( { speed: 2, threshold: 50, ease: 0.075 }, opts ); this.ui = { items: this.el.querySelectorAll('.p-js-slide'), titles: document.querySelectorAll('.p-js-title'), lines: document.querySelectorAll('.p-js-progress-line') }; this.state = { target: 0, current: 0, currentRounded: 0, y: 0, on: { x: 0, y: 0 }, off: 0, progress: 0, diff: 0, max: 0, min: 0, snap: { points: [] }, flags: { dragging: false } }; this.items = []; this.events = { move: store.isDevice ? 'touchmove' : 'mousemove', up: store.isDevice ? 'touchend' : 'mouseup', down: store.isDevice ? 'touchstart' : 'mousedown' }; this.init(); } bindAll() { ['onDown', 'onMove', 'onUp'].forEach(fn => (this[fn] = this[fn].bind(this))); } init() { return gsap.utils.pipe(this.setup(), this.on()); } destroy() { this.off(); this.state = null; this.items = null; this.opts = null; this.ui = null; } on() { const { move, up, down } = this.events; window.addEventListener(down, this.onDown); window.addEventListener(move, this.onMove); window.addEventListener(up, this.onUp); } off() { const { move, up, down } = this.events; window.removeEventListener(down, this.onDown); window.removeEventListener(move, this.onMove); window.removeEventListener(up, this.onUp); } setup() { const { ww } = store; const state = this.state; const { items, titles } = this.ui; const { width: wrapWidth, left: wrapDiff } = this.el.getBoundingClientRect(); // Set bounding state.max = -(items[items.length - 1].getBoundingClientRect().right - wrapWidth - wrapDiff); state.min = 0; // Global timeline this.tl = gsap .timeline({ paused: true, defaults: { duration: 1, ease: 'linear' } }) .fromTo( '.p-js-progress-line-2', { scaleX: 1 }, { scaleX: 0, duration: 0.5, ease: 'power3' }, 0 ) .fromTo( '.p-js-titles', { yPercent: 0 }, { yPercent: -(100 - 100 / titles.length) }, 0 ) .fromTo( '.p-js-progress-line', { scaleX: 0 }, { scaleX: 1 }, 0 ); // Cache stuff for (let i = 0; i < items.length; i++) { const el = items[i]; const { left, right, width } = el.getBoundingClientRect(); // Create webgl plane const plane = new Plane(); plane.init(el); // Timeline that plays when visible const tl = gsap.timeline({ paused: true }).fromTo( plane.mat.uniforms.uScale, { value: 0.65 }, { value: 1, duration: 1, ease: 'linear' } ); // Push to cache this.items.push({ el, plane, left, right, width, min: left < ww ? ww * 0.775 : -(ww * 0.225 - wrapWidth * 0.2), max: left > ww ? state.max - ww * 0.775 : state.max + (ww * 0.225 - wrapWidth * 0.2), tl, out: false }); } } calc() { const state = this.state; state.current += (state.target - state.current) * this.opts.ease; state.currentRounded = Math.round(state.current * 100) / 100; state.diff = (state.target - state.current) * 0.0005; state.progress = gsap.utils.wrap(0, 1, state.currentRounded / state.max); this.tl && this.tl.progress(state.progress); } render() { this.calc(); this.transformItems(); } transformItems() { const { flags } = this.state; for (let i = 0; i < this.items.length; i++) { const item = this.items[i]; const { translate, isVisible, progress } = this.isVisible(item); item.plane.updateX(translate); item.plane.mat.uniforms.uVelo.value = this.state.diff; if (!item.out && item.tl) { item.tl.progress(progress); } if (isVisible || flags.resize) { item.out = false; } else if (!item.out) { item.out = true; } } } isVisible({ left, right, width, min, max }) { const { ww } = store; const { currentRounded } = this.state; const translate = gsap.utils.wrap(min, max, currentRounded); // console.log(translate); const threshold = this.opts.threshold; const start = left + translate; const end = right + translate; const isVisible = start < threshold + ww && end > -threshold; const progress = gsap.utils.clamp(0, 1, 1 - (translate + left + width) / (ww + width)); return { translate, isVisible, progress }; } clampTarget() { const state = this.state; state.target = gsap.utils.clamp(state.max, 0, state.target); } getPos({ changedTouches, clientX, clientY, target }) { const x = changedTouches ? changedTouches[0].clientX : clientX; const y = changedTouches ? changedTouches[0].clientY : clientY; return { x, y, target }; } onDown(e) { const { x, y } = this.getPos(e); const { flags, on } = this.state; flags.dragging = true; on.x = x; on.y = y; } onUp() { const state = this.state; state.flags.dragging = false; state.off = state.target; } onMove(e) { const { x, y } = this.getPos(e); const state = this.state; if (!state.flags.dragging) return; const { off, on } = state; const moveX = x - on.x; const moveY = y - on.y; if (Math.abs(moveX) > Math.abs(moveY) && e.cancelable) { e.preventDefault(); e.stopPropagation(); } state.target = off + moveX * this.opts.speed; } } /** */ /** * GL STUFF *** */ /** */ const backgroundCoverUv = ` (...) `; const vertexShader = ` (...) `; const fragmentShader = ` (...) `; const loader = new THREE.TextureLoader(); loader.crossOrigin = 'anonymous'; class Gl { constructor() { this.scene = new THREE.Scene(); this.camera = new THREE.OrthographicCamera( store.ww / -2, store.ww / 2, store.wh / 2, store.wh / -2, 1, 10 ); this.camera.lookAt(this.scene.position); this.camera.position.z = 1; this.renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); this.renderer.setPixelRatio(1.5); this.renderer.setSize(store.ww, store.wh); this.renderer.setClearColor(0xffffff, 0); this.init(); } render() { this.renderer.render(this.scene, this.camera); } init() { const container = document.getElementById('canvas-projects'); const domEl = this.renderer.domElement; domEl.classList.add('dom-gl'); // document.body.appendChild(domEl); container.appendChild(domEl); } } class GlObject extends THREE.Object3D { init(el) { this.el = el; this.resize(); } resize() { this.rect = this.el.getBoundingClientRect(); const { left, top, width, height } = this.rect; this.pos = { x: left + width / 2 - store.ww / 2, y: top + height / 2 - store.wh / 2 }; this.position.y = this.pos.y; this.position.x = this.pos.x; this.updateX(); } updateX(current) { current && (this.position.x = current + this.pos.x); } } const planeGeo = new THREE.PlaneBufferGeometry(1, 1, 32, 32); const planeMat = new THREE.ShaderMaterial({ transparent: true, fragmentShader, vertexShader }); class Plane extends GlObject { init(el) { super.init(el); this.geo = planeGeo; this.mat = planeMat.clone(); this.mat.uniforms = { uTime: { value: 0 }, uTexture: { value: 0 }, uMeshSize: { value: new THREE.Vector2(this.rect.width, this.rect.height) }, uImageSize: { value: new THREE.Vector2(0, 0) }, uScale: { value: 0.75 }, uVelo: { value: 0 } }; this.img = this.el.querySelector('img'); this.texture = loader.load(this.img.src, texture => { texture.minFilter = THREE.LinearFilter; texture.generateMipmaps = false; this.mat.uniforms.uTexture.value = texture; this.mat.uniforms.uImageSize.value = [this.img.naturalWidth, this.img.naturalHeight]; }); this.mesh = new THREE.Mesh(this.geo, this.mat); this.mesh.scale.set(this.rect.width, this.rect.height, 1); this.add(this.mesh); gl.scene.add(this); } } /** */ /** * INIT STUFF *** */ /** */ const gl = new Gl(); const slider = new Slider(document.querySelector('.p-js-slider')); const tick = () => { gl.render(); slider.render(); }; gsap.ticker.add(tick); Here is my html (... bunch of other html sections) <section class="section section-larger section-more-projects" data-scroll-section> <div id="canvas-projects"></div> <div class="p-slider | p-js-drag-area"> (...) </div> <div class="p-titles"> (...) </div> <div class="p-progress"> (...) </div> </section> (... bunch of other html sections) And here is my css $easeOutExpo: cubic-bezier(0.2, 1, 0.2, 1); .dom-gl { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; } .p-slider { position: relative; padding: 0 22.5vw; display: flex; align-items: center; height: 100%; user-select: none; cursor: grab; z-index: 2; &__inner { display: flex; position: relative; } } .p-slide { overflow: hidden; &:first-child { position: relative; } &:not(:first-child) { position: absolute; top: 0; height: 100%; } &__inner { position: relative; overflow: hidden; width: 55vw; padding-top: 56.5%; } img { display: none; } } .p-titles { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); overflow: hidden; pointer-events: auto; z-index: 9999999999; &__list { position: absolute; top: 0; left: 0; } &__title { display: flex; align-items: center; justify-content: center; font-size: 6vw; font-weight: bold; letter-spacing: -0.1vw; color: #fff; &--proxy { visibility: hidden; } } } .p-progress { position: absolute; bottom: 0; left: 0; width: 100%; height: 0.25rem; overflow: hidden; pointer-events: none; &__line { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform: scaleX(0); transform-origin: left; background-color: #fff; &:nth-child(2) { transform-origin: right; } } } By the way, i'm also using Locomotive Scroll on my page for creating smooth inertia scrolling.
  25. I'm working on animating a grid of threejs boxes and I would like to implement the grid option available in the stagger object of the timeline, but when doing so I get an error: The example code only shows how to use the stagger options applied to DOM elements so I wonder if I'll need to create my own objects with properties that the grid optins will understand, which I can easly do, but I dont know what it is required. Hope that makes sense. Here is my setup: - There is an array of threejs Meshes layout in a grid - I want to create a timeline to animate all elements in the grid using the stagger grid options like: stagger: { amount: 1.5, grid: "auto", from: "center" } - But I'm getting the error quoted above Any help will be much appreciated.