🚀 Features implemented: - IndexedDB local database for trace storage and management - Drag & drop trace file upload with validation - HTTP Request viewer with advanced filtering and analysis - CDN provider detection (Cloudflare, Akamai, CloudFront, etc.) - Queue time analysis with bottleneck detection - Visual highlighting for file sizes and request durations - Priority-based request analysis - Phase event viewer with detailed trace exploration - Filmstrip screenshot integration (with debugging) - 3D Babylon.js viewer component 📊 Analysis capabilities: - HTTP/1.1 vs HTTP/2 performance comparison - CDN edge vs origin detection - Connection limit bottleneck identification - Priority queue analysis - Visual correlation with network requests - Performance bottleneck identification 🛠️ Technical stack: - React 19.1.0 + TypeScript 5.8.3 - Vite build system - IndexedDB for local storage - Babylon.js 8+ for 3D visualization - Chrome DevTools trace format support 🎨 User experience: - Clean, professional interface design - Color-coded performance indicators - Expandable detailed views - Search and filtering capabilities - Responsive grid layouts - Intuitive navigation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
77 lines
1.9 KiB
TypeScript
77 lines
1.9 KiB
TypeScript
import { useEffect, useRef } from 'react'
|
|
import {
|
|
Engine,
|
|
Scene,
|
|
ArcRotateCamera,
|
|
Vector3,
|
|
HemisphericLight,
|
|
MeshBuilder,
|
|
StandardMaterial,
|
|
Color3
|
|
} from 'babylonjs'
|
|
|
|
interface BabylonViewerProps {
|
|
width?: number
|
|
height?: number
|
|
}
|
|
|
|
export default function BabylonViewer({ width = 800, height = 600 }: BabylonViewerProps) {
|
|
const canvasRef = useRef<HTMLCanvasElement>(null)
|
|
const engineRef = useRef<Engine | null>(null)
|
|
const sceneRef = useRef<Scene | null>(null)
|
|
|
|
useEffect(() => {
|
|
if (!canvasRef.current) return
|
|
|
|
const canvas = canvasRef.current
|
|
const engine = new Engine(canvas, true)
|
|
engineRef.current = engine
|
|
|
|
const scene = new Scene(engine)
|
|
sceneRef.current = scene
|
|
|
|
const camera = new ArcRotateCamera('camera1', -Math.PI / 2, Math.PI / 2.5, 10, Vector3.Zero(), scene)
|
|
camera.attachControl(canvas, true)
|
|
scene.activeCamera = camera
|
|
|
|
const light = new HemisphericLight('light', new Vector3(0, 1, 0), scene)
|
|
light.intensity = 0.7
|
|
|
|
const sphere = MeshBuilder.CreateSphere('sphere', { diameter: 2 }, scene)
|
|
sphere.position.y = 1
|
|
|
|
const ground = MeshBuilder.CreateGround('ground', { width: 6, height: 6 }, scene)
|
|
|
|
const sphereMaterial = new StandardMaterial('sphereMaterial', scene)
|
|
sphereMaterial.diffuseColor = new Color3(1, 0, 1)
|
|
sphere.material = sphereMaterial
|
|
|
|
const groundMaterial = new StandardMaterial('groundMaterial', scene)
|
|
groundMaterial.diffuseColor = new Color3(0.5, 0.5, 0.5)
|
|
ground.material = groundMaterial
|
|
|
|
engine.runRenderLoop(() => {
|
|
scene.render()
|
|
})
|
|
|
|
const handleResize = () => {
|
|
engine.resize()
|
|
}
|
|
|
|
window.addEventListener('resize', handleResize)
|
|
|
|
return () => {
|
|
window.removeEventListener('resize', handleResize)
|
|
engine.dispose()
|
|
}
|
|
}, [])
|
|
|
|
return (
|
|
<canvas
|
|
ref={canvasRef}
|
|
width={width}
|
|
height={height}
|
|
style={{ width: '100%', height: '100%', display: 'block' }}
|
|
/>
|
|
)
|
|
} |