Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ShaneBrumback/8e05a9dcf4f810c7688ac95c80aba6fc to your computer and use it in GitHub Desktop.
Save ShaneBrumback/8e05a9dcf4f810c7688ac95c80aba6fc to your computer and use it in GitHub Desktop.
Threejs Examples Interactive Image Particle System
<!--////////////////////////////////////////////////////////////////////////////////////////
/// ///
/// Example Using Three.js Library, HTML, CSS & JavaScript ///
// 3D Interactive Web Apps & Games 2021-2024 ///
/// Contact Shane Brumback https://www.shanebrumback.com ///
/// Send a message if you have questions about this code ///
/// I am a freelance developer. I develop any and all web. ///
/// Apps Websites 3D 2D CMS Systems etc. Contact me anytime :) ///
/// ///
////////////////////////////////////////////////////////////////////////////////////////////-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three.js Examples - Interactive Image Particle System</title>
<style>
body {
color: white;
text-align: center;
margin: 0;
background-color: black
}
a {
text-decoration: none;
color: white;
}
h1 {
padding: 10px;
}
</style>
</head>
<body>
<!--Load the latest version of Three.js from CDN-->
<script src="https://cdn.jsdelivr.net/npm/three@latest/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@latest/examples/js/controls/OrbitControls.js"></script>
<script type="module">
// Initialize variables
var scene, camera, renderer;
var particles = [];
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
// Initialize Three.js scene
function initScene() {
// Create the scene
scene = new THREE.Scene();
// Create the camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
// Create the renderer
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ReinhardToneMapping;
renderer.setClearColor(0x000000);
renderer.domElement.style.position = 'fixed';
renderer.domElement.style.zIndex = '0';
renderer.domElement.style.left = '0';
renderer.domElement.style.top = '0';
document.body.appendChild(renderer.domElement);
// Add ambient light to the scene
var ambientLight = new THREE.AmbientLight(0xffffff, 5); // White light with intensity 1
scene.add(ambientLight);
window.addEventListener('pointermove', onPointerMove);
// Add event listener for mouse movement
document.addEventListener('mousemove', onMouseMove, false);
window.addEventListener('resize', onWindowResize);
//handles pc and mobile pointer movement
function onPointerMove(event) {
if (event.isPrimary === false) return;
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
}
//handles window resize events
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
// composer.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Add particles to the scene
for (var i = 0; i < 75; i++) {
var particle = new THREE.Mesh(
new THREE.PlaneGeometry(.75, .75), // Use PlaneGeometry instead of SphereGeometry
new THREE.MeshPhongMaterial({
color: getRandomColor(),
transparent: true,
depthTest: true
})
);
// Load the texture
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('../images/smiley.png');
particle.material.map = texture;
particle.position.set(Math.random() * 8 - 4, Math.random() * 8 - 4, Math.random() * 6 - 3);
particle.velocity = new THREE.Vector3();
// Initialize originalPosition property
particle.originalPosition = particle.position.clone();
particle.position.set(Math.random() * 8 - 4, Math.random() * 8 - 4, Math.random() * 6 - 3);
particle.velocity = new THREE.Vector3();
particles.push(particle);
scene.add(particle);
}
function getRandomColor() {
var colors = ['red', 'yellow', 'green', 'blue', 'orange', 'purple'];
var weights = [1, 5, 1, 1, 1, 1]; // Adjust the weights to prioritize yellow (increase its value)
// Generate a weighted random index
var totalWeight = weights.reduce((a, b) => a + b, 0);
var randomWeight = Math.random() * totalWeight;
var cumulativeWeight = 0;
var randomIndex = 0;
for (var i = 0; i < colors.length; i++) {
cumulativeWeight += weights[i];
if (randomWeight < cumulativeWeight) {
randomIndex = i;
break;
}
}
return colors[randomIndex];
}
}
// Handle mouse movement event
function onMouseMove(event) {
var mouse = new THREE.Vector2();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// Create a raycaster from the mouse coordinates
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
// Check for intersection between the raycaster and particles
var intersects = raycaster.intersectObjects(particles);
if (intersects.length > 0) {
// Move particles away from the mouse position if the ray intersects with them
intersects.forEach(function (intersect) {
var particle = intersect.object;
var distance = particle.position.distanceTo(intersect.point);
if (distance < 0.5) {
var direction = new THREE.Vector3().subVectors(particle.position, intersect.point).normalize();
particle.velocity.copy(direction).multiplyScalar(0.02);
}
});
}
}
// Update particle positions
function updateParticles() {
particles.forEach(function (particle) {
particle.position.add(particle.velocity);
particle.velocity.multiplyScalar(0.98);
// Calculate the displacement factor based on time
var displacementFactor = Math.sin(Date.now() * 0.002);
// Calculate the target position
var targetPosition = new THREE.Vector3(
particle.originalPosition.x + displacementFactor * 0.04,
particle.originalPosition.y + displacementFactor * 0.1,
particle.originalPosition.z + displacementFactor * 0.04
);
// Adjust the target position based on mouse position
var mouseDistance = particle.position.distanceTo(new THREE.Vector3(mouseX, mouseY, 0));
if (mouseDistance < 2) {
var direction = new THREE.Vector3().subVectors(particle.position, new THREE.Vector3(mouseX, mouseY, 0)).normalize();
targetPosition.addScaledVector(direction, 0.2);
}
// Adjust the lerp factor for smoother movement
var lerpFactor = 0.003; // Experiment with different values (e.g., 0.001, 0.005) for desired smoothness
// Check if particle has reached the target position
if (particle.position.distanceTo(targetPosition) < 0.01) {
// Particle has reached the target, reset to original position
targetPosition.copy(particle.originalPosition);
}
particle.position.lerp(targetPosition, lerpFactor);
});
}
// Render the scene
function render() {
requestAnimationFrame(render);
updateParticles();
renderer.render(scene, camera);
}
// Call the initialization function and start rendering
initScene();
render();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment