I have a really large mermaid flowchart and I can't read the text unless I zoom in. I've tried some VS Code extensions, but they weren't that great.
What are some ways to view/pan a large mermaid diagram?
If you don't mind pasting the data onto the mermaid live editor - they have a Pan & Zoom toggle which makes use of svg-pan-zoom
You can also rip the Javascript code out, which someone has already done. I went ahead and modified it so that you can highlight the text in the Node labels as well.
Here is what I cobbled together after reading a suggestion from the author of svg-pan-zoom.
Here's hoping someone can take this and make pan and zoom easier for end users of mermaid diagrams.
<html>
<head>
<style type="text/css">
#mySvgId {
height: 90%;
width: 100%;
}
</style>
</head>
<body>
<div id="graphDiv"></div>
<script src="https://bumbu.me/svg-pan-zoom/dist/svg-pan-zoom.min.js"></script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: false });
const drawDiagram = async function () {
const element = document.querySelector('#graphDiv');
const graphDefinition = `
flowchart LR
a(mermaid) --> b(flowchart) --> c(flowchart) --> d(flowchart) --> e(flowchart) --> f(flowchart)
`;
const { svg } = await mermaid.render('mySvgId', graphDefinition);
element.innerHTML = svg.replace(/( )*max-width:( 0-9\.)*px;/i, '');
var doPan = false;
var eventsHandler;
var panZoom;
var mousepos;
eventsHandler = {
haltEventListeners: ['mousedown', 'mousemove', 'mouseup']
, mouseDownHandler: function (ev) {
if (event.target.className == "[object SVGAnimatedString]") {
doPan = true;
mousepos = { x: ev.clientX, y: ev.clientY }
};
}
, mouseMoveHandler: function (ev) {
if (doPan) {
panZoom.panBy({ x: ev.clientX - mousepos.x, y: ev.clientY - mousepos.y });
mousepos = { x: ev.clientX, y: ev.clientY };
window.getSelection().removeAllRanges();
}
}
, mouseUpHandler: function (ev) {
doPan = false;
}
, init: function (options) {
options.svgElement.addEventListener('mousedown', this.mouseDownHandler, false);
options.svgElement.addEventListener('mousemove', this.mouseMoveHandler, false);
options.svgElement.addEventListener('mouseup', this.mouseUpHandler, false);
}
, destroy: function (options) {
options.svgElement.removeEventListener('mousedown', this.mouseDownHandler, false);
options.svgElement.removeEventListener('mousemove', this.mouseMoveHandler, false);
options.svgElement.removeEventListener('mouseup', this.mouseUpHandler, false);
}
}
panZoom = svgPanZoom('#mySvgId', {
zoomEnabled: true
, controlIconsEnabled: true
, fit: 1
, center: 1
, customEventsHandler: eventsHandler
})
};
await drawDiagram();
</script>
</body>
</html>
A simple solution using https://github.com/timmywil/panzoom
Add a div wrapper around the mermaid syntax
<div class="diagram-container" id="diagram-container">
<pre class="mermaid">
flowchart TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
</pre>
</div>
Set up a callback after the SVG is rendered to initialize panzoom and zoom using the mouse wheel.
mermaid.initialize({ startOnLoad: false });
await mermaid.run({
querySelector: '.mermaid',
postRenderCallback: (id) => {
const container = document.getElementById("diagram-container");
const svgElement = container.querySelector("svg");
// Initialize Panzoom
const panzoomInstance = Panzoom(svgElement, {
maxScale: 5,
minScale: 0.5,
step: 0.1,
});
// Add mouse wheel zoom
container.addEventListener("wheel", (event) => {
panzoomInstance.zoomWithWheel(event);
});
}
});
Basic CSS to style the container
.diagram-container {
width: 100%;
height: 100%;
overflow: hidden;
border: 1px solid #ccc;
position: relative;
margin-bottom: 10px;
}
svg {
cursor: grab;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With