Search the Community
Showing results for tags 'threejs'.
-
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
- 4 replies
-
- scrolltriger
- react
-
(and 3 more)
Tagged with:
-
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") `
-
I use MotionPathPlugin but i can't change path style, and don't know to move 3d model into path by scrolling
-
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
-
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
-
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.
-
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.
-
-
I was trying to do directional rotations in Three.js and encountered some weird/interesting behaviors... Using "_ccw" will actually result in clockwise rotation while "_cw" lead to counterclockwise rotation. That effect is happening regardless of whether I put positive/negative radians before the string. I have checked this plugin "whipped together" by the almighty code god but it doesn't cover directional rotations in Three.js. Anyways.. at least I could do directional rotations now!! Just wanna share. Maybe it's because how Three.js use positive number for counterclockwise rotation and negative number for clockwise?
-
I'm trying to create randomly placed circles with each render loop. I can't seem to animate a fade out opacity for each circle one after another(as a new circle would start with a opacity of 1). It seems to animate the opacity of them all at once. Any help would be appreciated
-
Hi everybody, im new on gsap...playing with threejs, tween and audio visualizer. I have a group with some mesh as child 1 - I would like to animate each element of the mesh with a value created in RAF . 2 - I would like to make endless tween on rotation (unfortunally , "repeat: -1" its not working). Is there another elegant / better solution for do that. Thanks in advance for any help... On RAF i have some function: 1 for render() three scene and one for analyze the sound and pass the value on tween. So this... // The sound analyzer . function soundAnalyzer() { if ((cristal)&&(frequencyData)){ tl_cristal_rotationX = new TimelineMax({repeat:-1 }); analyser.getByteFrequencyData(frequencyData); if(typeof frequencyData === 'object' && frequencyData.length > 0) { scale_value = 9000 - frequencyData[1] * 35 ; scale_value_Low = 1800 - frequencyData[1] * 5 ; cristal.traverse( function ( child ) { if ( child instanceof THREE.Mesh ) { tl_cristal_rotation = new TimelineMax(); tl_cristal_rotation.to(child.rotation, scale_value_Low, { ease: Linear.easeNone, x: -360 , y: -360, repeat:-1 }) } }); tl_cristal_rotationX.to(cristal.rotation, scale_value , { ease: Linear.easeNone, x: -360 }) } } } // and here RAF loop and Render // animation loop function animate() { if(dae) { soundAnalyzer() } requestAnimationFrame( animate ); render(); stats.update(); } TweenLite.ticker.addEventListener("tick", render); //and render the scene function render() { renderer.clear(); camera.position.x += ( mouseX - camera.position.x ) * .015; camera.position.y += ( - mouseY - camera.position.y ) * .015; camera.lookAt(scene.position); composer.reset(); composer.render(scene, camera); composer.pass(OldVideoPass); composer.pass(BrightnessContrastPass); composer.pass(RGBSplitPass); composer.toScreen(); } Thank u very much and sorry for my English.. hope is readable..
-
Hi all, first of all congrats on the great animation engine. I am using GreenSock, mainly TimelineMax and TweenMax for timing and tweening positions, rotations etc. of my WebGL / ThreeJS scene objects. The resulting format is always an interactive (Apple) iBook for children - basically a compressed website that runs with a WebKit standard similar to the one used in Safari Mobile. Performance was never a real issue until a colleague recently discovered that certain animations freeze or behave different (jumpy, stuttery) after running for several minutes (about 10-15 minutes dependent on the device) while others still run smoothly. It occurs only on the mobile device and only on generations < iPhone 6. What helps is to throttle the TweenMax ticker fps down to 30, but of course this doesn't look as smooth. I also tried playing with the lagSmoothing - with no success. Do you have an idea where these freezes come from? Since they occur only after a certain amount of time.. could it be that the JS execution stack suddenly becomes too big because the device isn't really capable of doing 60fps? Turning RAF on and of also didn't change much. Thanks for any hints or input.
- 10 replies
-
- performance
- lags
-
(and 6 more)
Tagged with:
-
Hi I would like to tween the scale of an array of Three JS objects. I am able to do this on requestAnimationFrame, but I would like to use Tweenmax: for ( var i = 0; i < meshes.length; i ++ ) { meshes.scale.x = meshes.scale.y = meshes.scale.z = boost; } Any idea how to? Thanks!
-
Hello, A few weeks ago I started with GSAP and now I also learned some basic skills in Three.js I have made a object and I am able to rotate it with GSAP, but I would like to make it draggable with the mouse. Can anyone help me making this happen? When I create a drag for the mesh ( the object). The object dissapears. This is my Codepen: http://codepen.io/xleooow/pen/YGvjNA Any help is appreciated.
-
Hello everyone, I am new to this place and I'm quite new to the GSAP world. I'm very excited about working with this library and watching the examples I was really impressed with this one. I have seen that there is a huge use of three.js library and I was wondering about how three.js and GSAP works togheter. For example, the camera movements are just made with three.js or there is a way to replicate that animation only with GSAP or both? I'm just looking for some hints! Thank you in advance! P.S. If I'm in the wrong section or off-topic, please forgive me!
-
I recently started using GSAP for animating three.js as an alternative to https://github.com/sole/tween.js, commonly used for this. It made it really easy to do something like: make a cube spin and when it stops, wait until one of the faces are square (through a 90 degree rotation with repeat -1 switched on/off). However, I'm struggling with severe performance issues in tweening many objects at a time. I think this has to do with having to create a duplicate copy of the objects to store the tween data rather than just being able to directly tween object variables without having to write in onUpdate. This makes writing the tween a tad more tedious than tween.js, and it has been no easy task to convert from tween.js to GSAP. Once I finally did figure out how to do this, I found the performance was severely worse than using tween.js. I created an example modification of a three.js example which closely relates to the project I'm working on: Original, using tween.js: http://jsfiddle.net/justin_hackin/J3k9N/ (Tweening @ 292) Single variable for closure in loop, not working: http://jsfiddle.net/justin_hackin/dHLcg/ TweenMax demo: http://jsfiddle.net/justin_hackin/6bFJc/ (Tweening @ 298) I'm wondering, are these performance issues happening because each TweenMax closure is trying to store the whole object copy array ? I don't quite understand the deeper aspects of JS, excuse my ignorance. Am I doing something wrong here ? I really love these GSAP libraries so I hope I can make it work for the project I'm working on. If not, I really hope the developers will consider making the code more friendly to this kind of use. The project I'm working on might eventually be willing to invest in such a feature if it would take some efforts to implement, please let me know what could be possible. Thanks, ~Justin
-
Hi, I'm trying to use GSAP to animate objects in a ThreeJS project, within the requestAnimationFrame loop. Obviously this loop is firing much faster than the time it takes each tween to complete. I'm getting lots of overlapping Tweens on each object and I'm trying to figure out the best way to have each Tween run and then run it's onComplete function to tween itself back properly without losing it's references. Would TimelineLite be better suited for this or is there a better approach using TweenLite? Thanks in advance! function animate() { if(animation === true ) requestAnimationFrame( animate ); TweenLite.killTweensOf(object); TweenLite.to(object, 0.5, { x: _radius * Math.cos( num ), y: _radius * Math.sin( num ), ease: Expo.easeOut, onComplete: function(_this,_x,_y) { // animate the object properties back to what they were before we started this tween }, onCompleteParams: ["{self}",object.position.x,object.position.y] }); }
- 9 replies
-
- requestanimationframe
- threejs
-
(and 1 more)
Tagged with: