diff options
| author | LalleSX | 2026-10-24 14:18:00 +0200 |
|---|---|---|
| committer | LalleSX | 2026-10-24 14:18:00 +0200 |
| commit | 389fb3a592832092835da0c2cc1608a57ba5f629 (patch) | |
| tree | ad1f89333ec3c84b906fb6546cee7824f58236fa /src/scene/primitives.ts | |
| parent | init (diff) | |
| download | 3D-Electrophysics-389fb3a592832092835da0c2cc1608a57ba5f629.tar.gz 3D-Electrophysics-389fb3a592832092835da0c2cc1608a57ba5f629.zip | |
Add tests for math rendering and interactive scenes; update navigation and viewport handling
- Updated `lab.spec.ts` to navigate directly to the field lesson.
- Created `math.spec.ts` with tests for math rendering, error checking, and responsive design.
- Added `test4.spec.ts` for interactive scenes, ensuring all questions are functional and accessible.
- Modified `vite.config.ts` to keep original question/answer links navigable in production.
Diffstat (limited to 'src/scene/primitives.ts')
| -rw-r--r-- | src/scene/primitives.ts | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/src/scene/primitives.ts b/src/scene/primitives.ts index bce9113..384ea1d 100644 --- a/src/scene/primitives.ts +++ b/src/scene/primitives.ts @@ -1,4 +1,6 @@ import * as THREE from 'three'; +import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js'; +import { renderProse } from '../math'; import type { Point } from '../physics/electricField'; export const colours = { positive: '#ff967b', negative: '#73d7ff', field: '#91e2cb', gold: '#f5d58b', muted: '#8294a8' }; @@ -25,7 +27,20 @@ export function arrow(group: THREE.Group, origin: Point, direction: Point, lengt if (dir.lengthSq() < 1e-24) return; group.add(new THREE.ArrowHelper(dir.normalize(), vector(origin), length, colour, Math.min(0.16, length * 0.3), Math.min(0.1, length * 0.2))); } -export function label(group: THREE.Group, text: string, position: Point, colour: string = '#dbe7f0', width = 2): THREE.Sprite { +export function label(group: THREE.Group, text: string, position: Point, colour: string = '#dbe7f0', width = 2, minViewportWidth = 0): THREE.Sprite | CSS2DObject { + if (text.includes('$')) { + const element = document.createElement('div'); + element.className = 'scene-math-label'; + element.style.color = colour; + renderProse(element, text); + const annotation = new CSS2DObject(element); + annotation.position.copy(vector(position)); + annotation.onBeforeRender = () => { + element.style.visibility = (element.parentElement?.clientWidth ?? Infinity) < minViewportWidth ? 'hidden' : 'visible'; + }; + group.add(annotation); + return annotation; + } const canvas = document.createElement('canvas'); const context = canvas.getContext('2d')!; context.font = '500 44px system-ui, sans-serif'; @@ -52,7 +67,9 @@ export function label(group: THREE.Group, text: string, position: Point, colour: if (!(camera instanceof THREE.PerspectiveCamera)) return; sprite.getWorldPosition(cameraPosition).applyMatrix4(camera.matrixWorldInverse); renderer.getSize(viewportSize); - const worldHeight = 2 * Math.abs(cameraPosition.z) * Math.tan(THREE.MathUtils.degToRad(camera.getEffectiveFOV()) / 2) * screenHeight / Math.max(1, viewportSize.y); + sprite.material.opacity = viewportSize.x < minViewportWidth ? 0 : 1; + const responsiveHeight = viewportSize.x < 600 ? screenHeight * 0.78 : screenHeight; + const worldHeight = 2 * Math.abs(cameraPosition.z) * Math.tan(THREE.MathUtils.degToRad(camera.getEffectiveFOV()) / 2) * responsiveHeight / Math.max(1, viewportSize.y); sprite.scale.set(worldHeight * aspect, worldHeight, 1); sprite.updateMatrixWorld(); }; |