“使用 Three.js 的 WebGL 小实验。霓虹灯跟随鼠标光标。”
HTML:
<script async src="https://ga.jspm.io/npm:es-module-shims@1.5.1/dist/es-module-shims.js" crossorigin="anonymous"></script>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.169.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.169.0/examples/jsm/"
}
}
</script>
body {
overflow: hidden;
margin: 0;
}
JAVASCRIPT:
// https://discourse.threejs.org/t/neon-light-following-mouse-cursor/73727
import * as THREE from "three";
// general setup, boring, skip to the next comment (line 68)
console.clear( );
var scene = new THREE.Scene();
scene.background = new THREE.Color( 'black' );
var camera = new THREE.OrthographicCamera( -innerWidth/2, innerWidth/2, innerHeight/2, -innerHeight/2, 1, 1000 );
camera.position.set( 0, 0, 500 );
var renderer = new THREE.WebGLRenderer( {antialias: true} );
renderer.setSize( innerWidth, innerHeight );
renderer.setAnimationLoop( animationLoop );
document.body.appendChild( renderer.domElement );
window.addEventListener( "resize", (event) => {
camera.left = -innerWidth/2;
camera.right = innerWidth/2;
camera.top = innerHeight/2;
camera.bottom = -innerHeight/2;
camera.updateProjectionMatrix( );
renderer.setSize( innerWidth, innerHeight );
});
var light = new THREE.DirectionalLight( 'white', 3 );
light.position.set( 0, 0, 10 );
scene.add( light );
class Platon extends THREE.Mesh
{
constructor( radius, level )
{
super(
new THREE.TetrahedronGeometry( 1, 3 ),
new THREE.MeshStandardMaterial( {color: 0x3c3cff, metalness: 0.47, roughness: 0.53, flatShading: true} )
);
var platon1 = new THREE.Mesh(
new THREE.TetrahedronGeometry( 1, 2 ),
new THREE.MeshStandardMaterial( {color: 0xffffff, metalness: 0.95, roughness: 0.05, flatShading: true} )
);
platon1.scale.setScalar( 0.995 );
var platon2 = new THREE.Mesh(
new THREE.TetrahedronGeometry( 1, 4 ),
new THREE.MeshStandardMaterial( {color: 0x0e0e0c, metalness: 0.47, roughness: 0.53, flatShading: true } )
);
platon2.scale.setScalar( 0.973 );
this.add( platon1, platon2 );
}
}
var object = new Platon( );
object.scale.setScalar( 100 );
scene.add( object );
// next comment
// cursor
var cursor = new THREE.Mesh(
new THREE.CircleGeometry( 7 ),
new THREE.MeshBasicMaterial( 'white' )
);
cursor.position.set( 0, 0, 120 );
scene.add( cursor );
// create a gradient background
var canvas = document.createElement( 'CANVAS' );
canvas.width = 256;
canvas.height = 256;
var context = canvas.getContext( '2d' ),
gradient = context.createRadialGradient( 128, 128, 0, 128, 128, 120 );
gradient.addColorStop( 0, 'midnightblue' );
gradient.addColorStop( 1, 'black' );
context.fillStyle = gradient;
context.fillRect( 0, 0, 256, 256 );
var background = new THREE.Mesh(
new THREE.PlaneGeometry( 600, 600 ),
new THREE.MeshBasicMaterial( {
map: new THREE.CanvasTexture( canvas ),
transparent: true,
opacity: 0.35,
dithering: true,
} )
);
background.position.z = -100;
scene.add( background );
// desired target positions
var targetBackground = background.position.clone( ),
targetCursor = cursor.position.clone( );
// capture mouse motion
window.addEventListener( 'pointermove', pointerMove );
// set new target position of the background
function pointerMove( event )
{
targetCursor.x = event.clientX - innerWidth/2;
targetCursor.y = -event.clientY + innerHeight/2;
}
function animationLoop( t )
{
// move the background and the cursor towards the current target posotions
background.position.lerp( targetCursor, 0.01 );
background.position.z = -100;
cursor.position.lerp( targetCursor, 0.08 );
object.rotation.x = Math.sin( t/700 );
object.rotation.y = Math.sin( t/700 );
renderer.render( scene, camera );
}
源码:
https://codepen.io/boytchev/pen/MWNPVzM
体验:
https://codepen.io/boytchev/full/MWNPVzM