Created
February 26, 2024 14:57
-
-
Save allen-munsch/456b7fef390d1e5cd7f50f3c78f9f9cc to your computer and use it in GitHub Desktop.
quick 3js example of directory tree file browsing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Import Three.js | |
import * as THREE from "three"; | |
import { OrbitControls } from "three/addons/controls/OrbitControls"; | |
var scene = new THREE.Scene(); | |
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | |
var renderer = new THREE.WebGLRenderer(); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
document.body.appendChild(renderer.domElement); | |
// Handle user interaction (e.g., mouse click) | |
const raycaster = new THREE.Raycaster(); | |
const mouse = new THREE.Vector2(); | |
const createText = (label) => { | |
const cv = document.createElement( 'canvas' ); | |
cv.width = 1536 // 3 * 512 | |
cv.height = 512; | |
const ctx = cv.getContext( '2d' ); | |
ctx.fillStyle = '#fefefe'; | |
ctx.fillRect( 0, 0, cv.width, cv.height ); | |
ctx.fillStyle = '#129912'; | |
ctx.textAlign = 'left'; | |
ctx.textBaseline = 'middle'; | |
ctx.font = 'bold 6vh Arial'; | |
ctx.fillText( `Tree | ${label}` , 0, 0.1 * cv.height ); | |
const txtGeometry = new THREE.BoxGeometry( 2.4, 0.8, 0.1 ); // w 3 : h 1 | |
const cvTexture = new THREE.Texture( cv ); | |
cvTexture.needsUpdate = true; // otherwise all black only | |
return cvTexture | |
} | |
// Create a cube representing a file icon | |
var createCube = (x, y, z, color, depth, label) => { | |
var cubeGeometry = new THREE.BoxGeometry(depth, depth, ); | |
var cubeMaterial = new THREE.MeshBasicMaterial({ map: createText(label) }); | |
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); | |
cube.position.set(x, y, z); | |
scene.add(cube); | |
// Create a label above the cube | |
function onMouseClick(event) { | |
// Calculate mouse position in normalized device coordinates | |
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; | |
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; | |
// Update the picking ray | |
raycaster.setFromCamera(mouse, camera); | |
// Check for intersections with the file cube | |
const intersects = raycaster.intersectObject(cube); | |
if (intersects.length > 0) { | |
// User clicked on the file cube | |
alert(`What would you like to do with ${label}`); | |
// TODO hookup to LLM agent executors etc | |
} | |
} | |
// Listen for mouse clicks | |
window.addEventListener('click', onMouseClick); | |
return cube; | |
}; | |
// Define your tree structure | |
var treeData = ['a -> b', 'b -> c', 'd -> null', 'e -> f']; | |
// Create cubes and labels | |
var cubes = {}; | |
let yOffset = 2; // Vertical spacing between levels | |
let parentOffset = 0; | |
treeData.forEach((item) => { | |
var [parent, child] = item.split(' -> '); | |
if (!cubes[parent]) { | |
cubes[parent] = createCube(parentOffset,parentOffset,parentOffset, 0x00ff00, 1, parent); // Green for directories | |
parentOffset += 1 | |
} | |
if (child) { | |
cubes[child] = createCube(1, yOffset, 0, 0xff0000, .5); // Red for files | |
yOffset += 2; // Increase vertical spacing for the next level | |
// Create a line connecting parent and child | |
var lineGeometry = new THREE.Geometry(); | |
lineGeometry.vertices.push(cubes[parent].position, cubes[child].position); | |
var lineMaterial = new THREE.LineBasicMaterial({ color: 0xffffff }); | |
var line = new THREE.Line(lineGeometry, lineMaterial); | |
scene.add(line); | |
} | |
}); | |
// Set camera position | |
camera.position.z = 5; | |
// Add mouse controls | |
console.log(OrbitControls) | |
var controls = new OrbitControls(camera, renderer.domElement); | |
controls.enableDamping = true; | |
controls.dampingFactor = 0.05; | |
controls.update(); // Update mouse controls | |
// Create an animation loop | |
function animate() { | |
requestAnimationFrame(animate); | |
// Rotate the cubes | |
for (var cube of Object.values(cubes)) { | |
cube.rotation.x += 0.0001; | |
cube.rotation.y += 0.0001; | |
} | |
renderer.render(scene, camera); | |
} | |
animate(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment