diff --git a/bzGraflow.js b/bzGraflow.js index 352a92e..17247ae 100644 --- a/bzGraflow.js +++ b/bzGraflow.js @@ -1332,69 +1332,25 @@ class BZgraflow extends Buildoz{ return(crossLayerLinks) } - /** - * Union bounding boxes of nodes and wires (viewport coords). - * Same measurement strategy as autofit(). Call with transform cleared for stable sizes. - */ - getContentSize(){ - let left = Infinity - let top = Infinity - let right = -Infinity - let bottom = -Infinity - - const includeBB = (bb) => { - if(!bb) return - left = Math.min(left, bb.left) - top = Math.min(top, bb.top) - right = Math.max(right, bb.right) - bottom = Math.max(bottom, bb.bottom) - } - - this.nodesContainer?.querySelectorAll?.('.bzgf-node').forEach(nodeEl => includeBB(nodeEl.getBoundingClientRect())) - this.wiresContainer?.querySelectorAll?.('path.bzgf-wire').forEach(path => includeBB(path.getBoundingClientRect())) - - const gapx = parseInt(this.getBZAttribute('gapx')) || 80 - const gapy = parseInt(this.getBZAttribute('gapy')) || 80 - const hasBounds = Number.isFinite(left) && Number.isFinite(right) && Number.isFinite(top) && Number.isFinite(bottom) - const rawWidth = hasBounds ? Math.max(right - left, 1) : Math.max(this.mainContainer?.clientWidth || this.offsetWidth || 1, 1) - const rawHeight = hasBounds ? Math.max(bottom - top, 1) : Math.max(this.mainContainer?.clientHeight || this.offsetHeight || 1, 1) - - return({ - left: hasBounds ? left : null, - top: hasBounds ? top : null, - right: hasBounds ? right : null, - bottom: hasBounds ? bottom : null, - rawWidth, - rawHeight, - width: rawWidth + (2 * gapx), - height: rawHeight + (2 * gapy), - gapx, - gapy, - }) - } - - autofit(percent=100){ - if(!this.parentElement) return - - const prevTransformOrigin = this.style.transformOrigin - this.style.transform = 'none' - this.style.transformOrigin = 'top left' - - const { left, top, width: contentW, height: contentH, gapx, gapy } = this.getContentSize() - const parentBB = this.parentElement.getBoundingClientRect() - const sx = parentBB.width / contentW - const sy = parentBB.height / contentH - const scale = Math.min(sx, sy)*(percent/100) // uniform scale to fit inside parent - const tx = left != null ? (-left + gapx) : gapx - const ty = top != null ? (-top + gapy) : gapy - if(!this.isSubflow) { - this.style.transformOrigin = prevTransformOrigin || 'top left' - this.style.transform = `scale(${scale}) translate(${tx}px, ${ty}px)` - } else { - this.style.transform = `scale(${scale})` - this.style.width = `calc(100% / ${scale})` // means 100% of the parent node DESPITE the scaling - this.style.height = `calc(100% / ${scale})` // means 100% of the parent node DESPITE the scaling + autofit(percent=100){ + const outwidth = Math.max(this.clientWidth, 1) + const outheight = Math.max(this.clientHeight, 1) + let inwidth = this.nodesContainer.scrollWidth + let inheight = this.nodesContainer.scrollHeight + try { // SVG scrollWidth ignores overflowing paths; getBBox() covers wire extent. + const wireBB = this.wiresContainer.getBBox() + if(wireBB.width > 0 || wireBB.height > 0){ + inwidth = Math.max(inwidth, wireBB.x + wireBB.width) + inheight = Math.max(inheight, wireBB.y + wireBB.height) + } + } catch(_){ // getBBox throws if SVG not rendered yet, but should not happen as we have _canRunAutoPlace() / _scheduleLayoutWhenReady() + return } + const ratio = Math.min( (outwidth / inwidth), (outheight / inheight) ) * (percent / 100) + this.nodesContainer.style.scale = ratio + this.wiresContainer.style.scale = ratio + this.nodesContainer.style.transformOrigin = 'top left' + this.wiresContainer.style.transformOrigin = 'top left' } } Buildoz.define('graflow', BZgraflow) diff --git a/graflow_examples/test4.html b/graflow_examples/test4.html index 2afbc2e..b15af88 100644 --- a/graflow_examples/test4.html +++ b/graflow_examples/test4.html @@ -45,19 +45,25 @@ font-size: 1em; } bz-graflow{ - overflow: scroll; border: 2px solid black; } - bz-graflow.icmp{ grid-column: 1 / -1; width: 100vw; height: 80vh; background: var(--eicui-base-color-grey-10); } + /* Fill the demo frame — autofit sizes to the graflow box, not the parent */ + bz-graflow.icmp{ + width: 100%; + height: 100%; + background: var(--eicui-base-color-grey-10); + } .container { resize: both; - overflow: auto; /* required in practice */ - min-width: 800px; - min-height: 300px; - border: 1px solid #999; + overflow: hidden; + width: 90vw; + height: 80vh; + min-width: 400px; + min-height: 240px; padding: 0; position: relative; - border:2px solid #A00 + border: 2px solid #A00; + box-sizing: border-box; } .container::after { content: ""; @@ -102,11 +108,10 @@ ) const el = document.querySelector('.container') - let timer = null // debounce const ro = new ResizeObserver(([entry]) => { const grfl = entry.target.querySelector('bz-graflow') grfl.autofit() - }) + }) ro.observe(el) let aifmi = null; let sidx=0;