Something went wrong. Try again.
[PRE-ALPHA] an open source web-based 2D/3D graphing calculator cartesium.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142import { describe, expect, it } from 'vitest';
import { graphTextScreenBounds, graphTextTopLeftAnchor, moveGraphTextAnchor, resizeGraphTextFromBottomRight, setGraphTextAnchor, type GraphTextElement} from './text-elements';import { mathToPixel, pixelToMath } from './viewport';
const viewport = { x_min: -10, x_max: 10, y_min: -10, y_max: 10, width: 800, height: 600};
const text: GraphTextElement = { id: 'label-1', source: 'A point', position: { x: 0, y: 0 }, anchor: { horizontal: 'center', vertical: 'middle' }, widthPx: 240, heightPx: 96, fontSizePx: 16, color: null, align: 'left'};
describe('graph text geometry', () => { it('keeps the display box in CSS pixels as the camera zooms', () => { const wide = graphTextScreenBounds(text, viewport);
const zoomed = graphTextScreenBounds(text, { ...viewport, x_min: -2, x_max: 2, y_min: -2, y_max: 2 });
expect([wide.width, wide.height]).toEqual([240, 96]); expect([zoomed.width, zoomed.height]).toEqual([240, 96]); expect([zoomed.left, zoomed.top]).toEqual([280, 252]); });
it('moves the graph-coordinate anchor under the grabbed screen point', () => { const initialAnchor = mathToPixel(viewport, text.position.x, text.position.y); const pointerStart = { x: initialAnchor.x + 30, y: initialAnchor.y - 8 };
const anchorOffset = { x: initialAnchor.x - pointerStart.x, y: initialAnchor.y - pointerStart.y };
const pointerEnd = { x: pointerStart.x + 160, y: pointerStart.y + 75 }; const movedAnchor = moveGraphTextAnchor(viewport, pointerEnd, anchorOffset);
expect(movedAnchor).toEqual(pixelToMath(viewport, initialAnchor.x + 160, initialAnchor.y + 75)); });
it('keeps the screen box fixed when switching to another anchor point', () => { const before = graphTextScreenBounds(text, viewport);
for (const vertical of ['top', 'middle', 'bottom'] as const) { for (const horizontal of ['left', 'center', 'right'] as const) { const reanchored = setGraphTextAnchor(text, { horizontal, vertical }, viewport); const after = graphTextScreenBounds(reanchored, viewport); const xFraction = horizontal === 'left' ? 0 : horizontal === 'right' ? 1 : 0.5; const yFraction = vertical === 'top' ? 0 : vertical === 'bottom' ? 1 : 0.5;
const zoomed = { ...viewport, x_min: -2, x_max: 2, y_min: -2, y_max: 2 };
const zoomedBounds = graphTextScreenBounds(reanchored, zoomed); const zoomedAnchor = mathToPixel(zoomed, reanchored.position.x, reanchored.position.y);
expect(after.left).toBeCloseTo(before.left); expect(after.top).toBeCloseTo(before.top); expect(reanchored.position).toEqual( pixelToMath(viewport, before.left + before.width * xFraction, before.top + before.height * yFraction) ); expect(zoomedBounds.left + zoomedBounds.width * xFraction).toBeCloseTo(zoomedAnchor.x); expect(zoomedBounds.top + zoomedBounds.height * yFraction).toBeCloseTo(zoomedAnchor.y); } } });
it('keeps the existing anchor when a change would exceed the supported coordinate range', () => { const wideViewport = { ...viewport, x_min: -1e12, x_max: 1e12, y_min: -1e12, y_max: 1e12 };
const nearLimit: GraphTextElement = { ...text, position: { x: 8e11, y: 0 }, anchor: { horizontal: 'left', vertical: 'middle' } };
expect(setGraphTextAnchor( nearLimit, { horizontal: 'right', vertical: 'middle' }, wideViewport )).toBe(nearLimit); });
it('resizes from the bottom-right while preserving the graph-coordinate top-left for each anchor', () => { for (const vertical of ['top', 'middle', 'bottom'] as const) { for (const horizontal of ['left', 'center', 'right'] as const) { const anchored = setGraphTextAnchor(text, { horizontal, vertical }, viewport); const fixedTopLeft = graphTextTopLeftAnchor(anchored, viewport); const startBounds = graphTextScreenBounds(anchored, viewport);
const resized = resizeGraphTextFromBottomRight( anchored, fixedTopLeft, { x: startBounds.left + 310, y: startBounds.top + 145 }, viewport );
expect(resized.widthPx).toBe(310); expect(resized.heightPx).toBeCloseTo(145); expect(graphTextTopLeftAnchor(resized, viewport).x).toBeCloseTo(fixedTopLeft.x); expect(graphTextTopLeftAnchor(resized, viewport).y).toBeCloseTo(fixedTopLeft.y); } } });});