36 lines
1.4 KiB
JavaScript
36 lines
1.4 KiB
JavaScript
import * as THREE from 'three';
|
|
|
|
// Keeps the gradient's bright spot gravitating toward the projection wall as
|
|
// the camera orbits: the wall centre (x = -10 in every scene) is projected into
|
|
// screen space each frame and eased into the CSS gradient position.
|
|
const WALL_CENTRE = new THREE.Vector3( -10, 0, 0 );
|
|
|
|
export function bindGlow( camera ) {
|
|
const projected = new THREE.Vector3();
|
|
let x = 12;
|
|
let y = 50;
|
|
let writtenX = null;
|
|
let writtenY = null;
|
|
|
|
return function update() {
|
|
projected.copy( WALL_CENTRE ).project( camera );
|
|
|
|
// when the wall goes behind the camera the projection flips sides;
|
|
// leave the glow where it last was until the wall swings back
|
|
if ( projected.z < 1 ) {
|
|
const targetX = THREE.MathUtils.clamp( ( projected.x + 1 ) * 50, -40, 140 );
|
|
const targetY = THREE.MathUtils.clamp( ( 1 - projected.y ) * 50, -40, 140 );
|
|
x += ( targetX - x ) * 0.08;
|
|
y += ( targetY - y ) * 0.08;
|
|
}
|
|
|
|
// writing the property repaints the whole gradient, so only touch the
|
|
// DOM while the glow is actually moving
|
|
if ( writtenX !== null && Math.abs( x - writtenX ) < 0.05 && Math.abs( y - writtenY ) < 0.05 ) return;
|
|
writtenX = x;
|
|
writtenY = y;
|
|
document.body.style.setProperty( '--glow-x', `${x.toFixed( 2 )}%` );
|
|
document.body.style.setProperty( '--glow-y', `${y.toFixed( 2 )}%` );
|
|
};
|
|
}
|