mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 03:54:17 +02:00
Stop the G-code preview from sizing the box that sizes it (issue #2887)
Opening a 3D Preview from Archives left an empty white pane with the legend and the layer slider drawn over it, and the page's scrollbar shrank for as long as it stayed open -- about 190px of page height a second, with no limit. The viewer appends its canvas into the very element it measures with clientWidth/clientHeight and watches with a ResizeObserver. setSize writes each new size onto the canvas as inline style, and three.js leaves the canvas display:inline, so the line box adds descender space on top of the height just set. Where that element takes its height from its contents, the canvas sizes the box that sizes the canvas and gains a fixed 33px every round -- the reporter measured container = canvas + 33 on every sample. The page gave it no height to take instead. The viewer pane is flex-1 min-h-0, which divides nothing unless the column above it is a definite height, and h-full is a percentage resolved against a main area whose own height comes from a min-height -- a floor, not a size. So it fell through to the content, and the content was the canvas. Nothing was ever drawn because of the same loop, not a second fault: every observer callback reallocated and cleared the frame buffer, and an antialiased render of what had grown to roughly 18 megapixels never finished before the next one arrived. The data path was fine throughout, which the legend and the 1..57 layer slider both prove -- they are built from the parsed toolpath. The canvas is now positioned out of flow, so it cannot contribute to the height of the element that measures it on any page, and that element takes a definite height from the pane around it rather than a percentage. display:block goes on too, for the case where something overrides the positioning. The page is sized from the viewport the way the File Manager page already was. Either change alone stops the growth, but the structural one alone would trade it for a collapsed pane: an out-of-flow canvas contributes nothing to content height, so with no definite height above it the pane becomes clientHeight || 1. They belong together. The same viewer in the File Manager dialog was never affected -- a dialog gives it a fixed height, so neither fault could arise there. jsdom does no layout, so the loop cannot be reproduced in a test. The structure that forbids it can: the new cases assert the canvas is out of flow, that the measured element is definite-height rather than h-full, and that the pane stays positioned so inset-0 resolves against it. Reverting either change fails exactly those.
This commit is contained in:
@@ -256,6 +256,19 @@ export function GcodeToolpathViewer({
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||
renderer.setSize(width, height);
|
||||
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
||||
// Take the canvas out of flow before it is ever in the document (#2887).
|
||||
// `setSize` writes the size onto the canvas as inline width/height, and the
|
||||
// canvas lives inside the very element we measure and observe — so on a page
|
||||
// where that element's height comes from its content, each resize grew the
|
||||
// container, which fired the observer, which resized again. three.js leaves
|
||||
// the canvas `display: inline`, so the line box added its descender space
|
||||
// (~33px) every round and the page climbed without limit. Out of flow it
|
||||
// cannot contribute to the container's height at all; `display: block` is
|
||||
// belt and braces for the same descender, and matters if this is ever
|
||||
// rendered somewhere the absolute positioning is overridden.
|
||||
renderer.domElement.style.display = 'block';
|
||||
renderer.domElement.style.position = 'absolute';
|
||||
renderer.domElement.style.inset = '0';
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
@@ -437,7 +450,18 @@ export function GcodeToolpathViewer({
|
||||
|
||||
return (
|
||||
<div className={`relative ${className}`}>
|
||||
<div ref={containerRef} className="w-full h-full" />
|
||||
{/*
|
||||
Absolute, not `w-full h-full` (#2887). The canvas is appended here and
|
||||
this element is what the ResizeObserver watches, so its height must come
|
||||
from the pane above it and never from what it contains. `h-full` is a
|
||||
percentage, which resolves to `auto` unless every ancestor has a definite
|
||||
height — on the full-page route none does, so the height fell through to
|
||||
the content and the canvas ended up sizing the box that sizes the canvas.
|
||||
`inset-0` against the `relative` parent is a definite height whatever the
|
||||
page does, which also keeps this working if a future caller forgets to
|
||||
give the pane a height of its own.
|
||||
*/}
|
||||
<div ref={containerRef} className="absolute inset-0" />
|
||||
|
||||
{loading && (
|
||||
<div className="absolute inset-0 flex items-center justify-center gap-2 bg-bambu-dark/60 text-sm text-bambu-gray">
|
||||
|
||||
Reference in New Issue
Block a user