Skip to content

Commit 6f8a5a3

Browse files
feat: enable dragging and downloading for mermaid image
Change-Id: Ibc352b70eb663c694f06378e1d7b1ae18e6e187b
1 parent 91618d8 commit 6f8a5a3

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

assets/js/mermaid.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
'<button type="button" class="btn btn-sm btn-light" id="mermaidZoomIn">+</button>' +
4646
'<button type="button" class="btn btn-sm btn-light" id="mermaidZoomOut">-</button>' +
4747
'<button type="button" class="btn btn-sm btn-light" id="mermaidZoomReset">Reset</button>' +
48+
'<button type="button" class="btn btn-sm btn-light" id="mermaidDownload">Download</button>' +
4849
'</div>' +
4950
'<div class="mermaid-zoom-wrapper"><div class="mermaid-zoom-content"></div></div>' +
5051
'</div>' +
@@ -89,6 +90,63 @@
8990
scale = Math.max(0.2, Math.min(5, scale));
9091
applyScale();
9192
});
93+
94+
var isDragging = false;
95+
var startX = 0;
96+
var startY = 0;
97+
var scrollLeft = 0;
98+
var scrollTop = 0;
99+
100+
$(document).on('mousedown touchstart', '.mermaid-zoom-wrapper', function(e) {
101+
var $wrap = $(this);
102+
isDragging = true;
103+
$wrap.addClass('dragging');
104+
var ev = e.type === 'touchstart' ? e.originalEvent.touches[0] : e;
105+
startX = ev.pageX - $wrap.offset().left;
106+
startY = ev.pageY - $wrap.offset().top;
107+
scrollLeft = $wrap.scrollLeft();
108+
scrollTop = $wrap.scrollTop();
109+
});
110+
111+
$(document).on('mousemove touchmove', '.mermaid-zoom-wrapper', function(e) {
112+
if (!isDragging) return;
113+
var $wrap = $(this);
114+
var ev = e.type === 'touchmove' ? e.originalEvent.touches[0] : e;
115+
var x = ev.pageX - $wrap.offset().left;
116+
var y = ev.pageY - $wrap.offset().top;
117+
var dx = x - startX;
118+
var dy = y - startY;
119+
$wrap.scrollLeft(scrollLeft - dx);
120+
$wrap.scrollTop(scrollTop - dy);
121+
});
122+
123+
$(document).on('mouseup mouseleave touchend', '.mermaid-zoom-wrapper', function() {
124+
isDragging = false;
125+
$(this).removeClass('dragging');
126+
});
127+
128+
$(document).on('click', '#mermaidDownload', function() {
129+
var $svg = $('#mermaidModal .mermaid-zoom-content svg');
130+
if (!$svg.length) return;
131+
var node = $svg.get(0);
132+
if (!node.getAttribute('xmlns')) {
133+
node.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
134+
}
135+
var serializer = new XMLSerializer();
136+
var source = serializer.serializeToString(node);
137+
var blob = new Blob([source], { type: 'image/svg+xml;charset=utf-8' });
138+
var url = URL.createObjectURL(blob);
139+
var a = document.createElement('a');
140+
var name = (document.title || 'diagram') + '-' + Date.now() + '.svg';
141+
a.href = url;
142+
a.download = name;
143+
document.body.appendChild(a);
144+
a.click();
145+
setTimeout(function() {
146+
URL.revokeObjectURL(url);
147+
a.remove();
148+
}, 0);
149+
});
92150
})(jQuery);
93151
{{ end }}
94152
{{ end }}

assets/scss/_styles_project.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,18 @@ pre.mermaid {
3939
.mermaid-zoom-wrapper {
4040
overflow: auto;
4141
max-height: 85vh;
42+
cursor: grab;
43+
user-select: none;
4244
}
4345

4446
.mermaid-zoom-content {
4547
transform-origin: 0 0;
4648
}
4749

50+
.mermaid-zoom-wrapper.dragging {
51+
cursor: grabbing;
52+
}
53+
4854
.mermaid-zoom-controls {
4955
position: absolute;
5056
right: 1rem;

0 commit comments

Comments
 (0)