You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: multi-diagram support with vector-based zoom/pan engine
Replace CSS zoom with direct SVG sizing. Closure-based initDiagram() pattern
supports unlimited diagrams per page with no ID collisions. Includes adaptive
viewport height, smart fit algorithm, touch pinch-to-zoom, and double-click
to fit.
Co-authored-by: David Abraham <dave@springbasemedia.com>
CSS `transform: scale()` only changes visual appearance — the element's layout box stays the same size. When you scale from `center center`, content expands upward and leftward into negative coordinate space. Scroll containers can't scroll to negative positions, so the top and left of the zoomed content get clipped.
612
+
**How the new zoom/pan engine works:**
598
613
599
-
CSS `zoom` actually changes the element's layout size. The content grows downward and rightward like any other growing element, staying fully scrollable.
614
+
The SVG is rendered into `.mermaid-canvas` which is absolutely positioned inside `.mermaid-viewport`. Zooming sets the SVG's `width` and `height` styles directly. Panning applies `transform: translate()` to the canvas. The viewport has `overflow: hidden` to clip the panned content. This approach avoids CSS `zoom` (which had cross-browser quirks) and gives precise control over the diagram's size and position.
<buttontype="button"data-action="zoom-expand"title="Open full size">⛶</button>
630
+
<spanclass="zoom-label">Loading...</span>
631
+
</div>
632
+
<divclass="mermaid-viewport">
633
+
<divclass="mermaid mermaid-canvas"></div>
634
+
</div>
610
635
</div>
611
-
<preclass="mermaid">
636
+
<scripttype="text/plain"class="diagram-source">
612
637
graph TD
613
638
A-->B
614
-
</pre>
615
-
</div>
639
+
</script>
640
+
</section>
616
641
```
617
642
618
-
**Click to expand.** Clicking anywhere on the diagram (without dragging) opens it full-size in a new tab. The expand button (⛶) in the zoom controls does the same thing.
643
+
Use one `.diagram-shell` per diagram. The source Mermaid text lives in `<script type="text/plain" class="diagram-source">`, so multiple diagrams can coexist on a page without ID collisions.
619
644
620
645
### JavaScript
621
646
622
-
Add once at the end of the page. Handles button clicks and scroll-to-zoom on all `.mermaid-wrap` containers:
647
+
Use a closure-based initializer. Per-diagram state lives inside `initDiagram(shell)`, while shared drag listeners stay at module scope:
623
648
624
649
```javascript
625
-
// Match this to the CSS zoom value (or 1 if not set)
626
-
varINITIAL_ZOOM=1.4;
627
-
628
-
functionzoomDiagram(btn, factor) {
629
-
var wrap =btn.closest('.mermaid-wrap');
630
-
var target =wrap.querySelector('.mermaid');
631
-
var current =parseFloat(target.dataset.zoom||INITIAL_ZOOM);
632
-
var next =Math.min(Math.max(current * factor, 0.5), 5);
633
-
target.dataset.zoom= next;
634
-
target.style.zoom= next;
635
-
}
636
-
637
-
functionresetZoom(btn) {
638
-
var wrap =btn.closest('.mermaid-wrap');
639
-
var target =wrap.querySelector('.mermaid');
640
-
target.dataset.zoom=INITIAL_ZOOM;
641
-
target.style.zoom=INITIAL_ZOOM;
642
-
}
643
-
644
-
functionopenDiagramFullscreen(btn) {
645
-
var wrap =btn.closest('.mermaid-wrap');
646
-
openMermaidInNewTab(wrap);
647
-
}
648
-
649
-
functionopenMermaidInNewTab(wrap) {
650
-
var svg =wrap.querySelector('.mermaid svg');
651
-
if (!svg) return;
652
-
653
-
// Clone the SVG and remove any inline transforms from zoom
654
-
var clone =svg.cloneNode(true);
655
-
clone.style.zoom='';
656
-
clone.style.transform='';
657
-
658
-
// Get computed styles for theming
659
-
var styles =getComputedStyle(document.documentElement);
660
-
var bg =styles.getPropertyValue('--bg').trim() ||'#ffffff';
Scroll-to-zoom requires Ctrl/Cmd+scroll to avoid hijacking normal page scroll. Cursor changes to `grab`/`grabbing` to signal pan mode. The zoom range is capped at 0.5x–5x. **Clicking without dragging opens the diagram full-size in a new browser tab.**
704
+
This pattern removes all hardcoded IDs and supports unlimited diagrams per page. For the full implementation (including smart fit, pinch zoom, and shared drag state), use `templates/mermaid-flowchart.html` as the canonical source.
0 commit comments