Three.js - Scroll Based Animation: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
Zeile 154: Zeile 154:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
=== Scroll Trigger ===
 +
Wir nutzen GSAP aber nur für die Animation, nicht für den Trigger:
 +
<syntaxhighlight lang="javascript">
 +
/**
 +
* Sizes
 +
*/
 +
const sizes = {
 +
    width: window.innerWidth,
 +
    height: window.innerHeight
 +
}
  
<syntaxhighlight lang="javascript">
+
window.addEventListener('resize', () =>
</syntaxhighlight>
+
{
<syntaxhighlight lang="javascript">
+
    // Update sizes
</syntaxhighlight>
+
    sizes.width = window.innerWidth
<syntaxhighlight lang="javascript">
+
    sizes.height = window.innerHeight
 +
    //...
 +
})
 +
// ...
 +
 
 +
/**
 +
* Scroll
 +
*/
 +
let scrollY = window.scrollY
 +
let currentSection = 0
 +
 
 +
window.addEventListener('scroll', () =>
 +
{
 +
    scrollY = window.scrollY
 +
    const newSection = Math.round(scrollY / sizes.height) //liefert 0,1,2...
 +
    if(newSection != currentSection)
 +
    {
 +
        console.log('changed', currentSection)
 +
        currentSection = newSection
 +
        // Section Trigger
 +
        gsap.to(
 +
            sectionMeshes[currentSection].rotation,
 +
            {
 +
                duration: 1.5,
 +
                ease: 'power2.inOut',
 +
                x: '+=6',
 +
                y: '+=3',
 +
                z: '+=1.5'
 +
            }
 +
        )
 +
    }
 +
})
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
</syntaxhighlight>
 
</syntaxhighlight>

Version vom 11. Februar 2022, 20:58 Uhr

Snippets

Check Scroll Position

 let scrollY = window.scrollY
 window.addEventListener('scroll', () =>
 {
     scrollY = window.scrollY
 
     console.log(scrollY)
 })

Scroll objects in sync to html scroll

// position objects
const objectsDistance = 4
mesh1.position.y = - objectsDistance * 0
mesh2.position.y = - objectsDistance * 1
mesh3.position.y = - objectsDistance * 2
//...
// Calc sizes (HINT-no resize event in this example)
const sizes = {
    width: window.innerWidth,
    height: window.innerHeight
}

//...
// Base camera
const camera = new THREE.PerspectiveCamera(35, sizes.width / sizes.height, 0.1, 100)
camera.position.z = 6
scene.add(camera)

// Control Scrolling
let scrollY = window.scrollY
window.addEventListener('scroll', () => { scrollY = window.scrollY })

// ...

// tick function
const tick = () =>
{
// ...
    // Animate camera
    camera.position.y = - scrollY / sizes.height * objectsDistance // scroll objects in sync to html
// ...
}

tick()

Cursor based Parallax

// ...
/**
 * Camera
 */
// Group (used to apply camara parallax without interfering the camera scroll)
const cameraGroup = new THREE.Group()
scene.add(cameraGroup)

// Base camera
const camera = new THREE.PerspectiveCamera(35, sizes.width / sizes.height, 0.1, 100)
camera.position.z = 6
cameraGroup.add(camera)

// ...

const tick = () =>
{
    // Animate camera
    // scroll objects in sync to html
    camera.position.y = - scrollY / sizes.height * objectsDistance 

    // cameraGroup parallax on cursor movement
    const parallaxX = cursor.x
    const parallaxY = - cursor.y
    cameraGroup.position.x = parallaxX
    cameraGroup.position.y = parallaxY
}
// ...

Parallax with easing

Variation von oben

// ...
/**
 * Animate
 */
const clock = new THREE.Clock()
let previousTime = 0

const tick = () =>
{
    const elapsedTime = clock.getElapsedTime()
    // we need deltaTime to calc correct timbased (not fps based) movement for our easing
    const deltaTime = elapsedTime - previousTime
    previousTime = elapsedTime
    
    //...

    // Animate camera
    // scroll objects in sync to html
    camera.position.y = - scrollY / sizes.height * objectsDistance 

    // camera parallax on cursor movement
    const parallaxX = cursor.x * 0.5
    const parallaxY = - cursor.y * 0.5
    //cameraGroup.position.x = parallaxX
    //cameraGroup.position.y = parallaxY
    // add some easing
    cameraGroup.position.x += (parallaxX - cameraGroup.position.x) * 5 * deltaTime
    cameraGroup.position.y += (parallaxY - cameraGroup.position.y) * 5 * deltaTime

    // Render
    renderer.render(scene, camera)

    // Call tick again on the next frame
    window.requestAnimationFrame(tick)
}

tick()

Partikel für zusätzliche Räumlichkeit einsetzen

/**
 * Particles
 */
const particlesCount = 200

const positions = new Float32Array(particlesCount * 3)
for(let i = 0; i < particlesCount; i++)
{
    positions[i * 3 + 0] = (Math.random() - 0.5) * 10
    positions[i * 3 + 1] = objectsDistance * 0.5 - Math.random() * objectsDistance * sectionMeshes.length
    positions[i * 3 + 2] = (Math.random() - 0.5) * 10
}

// Geometry
const particlesGeometry = new THREE.BufferGeometry()
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))

// Material
const particlesMaterial = new THREE.PointsMaterial({
    color: parameters.materialColor,
    sizeAttenuation: true,
    size: 0.03
})

// Points
const particles = new THREE.Points(particlesGeometry, particlesMaterial)
scene.add(particles)

Scroll Trigger

Wir nutzen GSAP aber nur für die Animation, nicht für den Trigger:

/**
 * Sizes
 */
const sizes = {
    width: window.innerWidth,
    height: window.innerHeight
}

window.addEventListener('resize', () =>
{
    // Update sizes
    sizes.width = window.innerWidth
    sizes.height = window.innerHeight
    //...
})
// ...

/**
 * Scroll
 */
 let scrollY = window.scrollY
 let currentSection = 0

 window.addEventListener('scroll', () =>
 {
     scrollY = window.scrollY
     const newSection = Math.round(scrollY / sizes.height) //liefert 0,1,2...
     if(newSection != currentSection)
    {
        console.log('changed', currentSection)
        currentSection = newSection
        // Section Trigger
        gsap.to(
            sectionMeshes[currentSection].rotation,
            {
                duration: 1.5,
                ease: 'power2.inOut',
                x: '+=6',
                y: '+=3',
                z: '+=1.5'
            }
        )
    }
 })

Complete Example (three.js journey)

Magnetic Sections - Todo