效果演示

源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js Particle Example</title>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// examples
// https://threejs.org/examples/?q=particle#webgl_points_billboards
let camera
let scene
let renderer
let material
let mouseX = 0
let mouseY = 0
let windowHalfX = window.innerWidth / 2
let windowHalfY = window.innerHeight / 2
init()
animate()
function init () {
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 20000)
camera.position.z = 500
scene = new THREE.Scene()
scene.fog = new THREE.FogExp2(0x000088, 0.001)
const geometry = new THREE.BufferGeometry()
const vertices = []
const size = 2000
for (let i = 0; i < 2000; i ++) {
const x = (Math.random() * size + Math.random() * size) / 2 - size / 2
const y = (Math.random() * size + Math.random() * size) / 2 - size / 2
const z = (Math.random() * size + Math.random() * size) / 2 - size / 2
vertices.push(x, y, z)
}
for (let j = 0; j < 100; j++) {
const positionX = Math.random() * 3000 - 1500
const positionY = Math.random() * 3000 - 1500
const positionZ = Math.random() * 3000 - 1500
const r = Math.random() * 300 + 50
for (let i = 0; i < 20000; i++) {
const radian1 = Math.PI / Math.random() * 360
const radian2 = Math.PI / Math.random() * 360
let x = Math.cos(radian1) * Math.cos(radian2) * r + positionX
let y = Math.cos(radian1) * Math.sin(radian2) * r + positionY
let z = Math.sin(radian1) * r + positionZ
vertices.push(x, y, z)
}
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3))
material = new THREE.PointsMaterial({
size: 2,
color: 0xffffff,
})
const particles = new THREE.Points(geometry, material)
scene.add(particles)
renderer = new THREE.WebGLRenderer()
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
document.body.style.touchAction = 'none'
document.body.addEventListener('pointermove', onPointerMove)
window.addEventListener('resize', onWindowResize)
}
function onWindowResize () {
windowHalfX = window.innerWidth / 2
windowHalfY = window.innerHeight / 2
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
}
function onPointerMove (event) {
mouseX = event.clientX - windowHalfX
mouseY = event.clientY - windowHalfY
}
function animate () {
requestAnimationFrame(animate)
render()
}
function render () {
camera.position.x += (mouseX * 4 - camera.position.x) * 0.02
camera.position.y += (-mouseY * 4 - camera.position.y) * 0.02
camera.lookAt(scene.position)
renderer.render(scene, camera)
scene.rotation.x += 0.001
scene.rotation.y += 0.002
}
</script>
</body>
</html>