“使用 Three.js 的 WebGL 小实验。很酷的灯光跟随光标位置之蜘蛛侠。”
HTML:
<div id="loading">
<h1 id="loadingtext">LOADING 0%</h1>
</div>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.165.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.165.0/examples/jsm/"
}
}
</script>
<script type="module" src="script.js"></script>
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,200..800&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
body {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Bricolage Grotesque, 'Poppins', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
overflow: hidden;
}
canvas {
display: block;
width: 100vw;
height: 100vh;
}
#loading {
position: absolute;
height: 100vh;
width: 100vw;
background: black;
z-index: 5;
display: flex;
align-items: center;
justify-content: center;
}
#loading h1 {
text-align: center;
color: white;
}
JAVASCRIPT:
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
// Create the scene
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
// Create the camera
const camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 1, 3);
// Create the renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true; // Enable shadows
document.body.appendChild(renderer.domElement);
// Add point light
const pointLight = new THREE.PointLight(0xffffff, 4, 100);
pointLight.position.set(656 * 2 + 1, 114 * 2 + 1, 3);
pointLight.castShadow = true; // Allow the light to cast shadows
scene.add(pointLight);
// Set up shadow properties for the light
pointLight.shadow.mapSize.width = 1024;
pointLight.shadow.mapSize.height = 1024;
pointLight.shadow.camera.near = 0.5;
pointLight.shadow.camera.far = 500;
pointLight.shadow.bias = -0.000512
// Load the GLB model
const loader = new GLTFLoader();
loader.load(
'https://raw.githubusercontent.com/vaibhav1663/boat30/master/models/spidy.glb',
async function (gltf) {
const model = gltf.scene;
model.position.set(-0.6, -7.75, 0);
model.scale.set(0.3, 0.3, 0.3);
model.traverse(function (node) {
if (node.isMesh) {
node.castShadow = true; // The model will cast shadows
node.receiveShadow = true; // The model will receive shadows
}
});
scene.add(model);
document.getElementById('loading').style.display = 'none';
},
(onProgress) => {
console.log(onProgress.loaded);
document.getElementById('loadingtext').innerText = `LOADING ${(onProgress.loaded / 78644.36).toFixed(2)}%`;
},
function (error) {
console.error(error);
}
);
// Update light position based on mouse movement
function onMouseMove(event) {
console.log(event.clientX, event.clientY);
pointLight.position.set(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1,
2
);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Add event listener for mouse movement
window.addEventListener('mousemove', onMouseMove);
源码:
https://codepen.io/vaibhav-khating/pen/poXeEwg
体验:
https://codepen.io/vaibhav-khating/full/poXeEwg