-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathviewer.html
More file actions
114 lines (96 loc) · 3.45 KB
/
Copy pathviewer.html
File metadata and controls
114 lines (96 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>SVG Viewer</title>
<style>
html, body { margin:0; height:100%; overflow:hidden; background:#111; }
iframe { width:100%; height:100%; border:none; }
.hud {
position:fixed; top:10px; left:10px; z-index:10;
font:14px system-ui; color:#eee; background:#000a; padding:6px 8px; border-radius:8px;
}
button { margin-right:6px; }
</style>
</head>
<body>
<div class="hud">
<button id="zin">+</button>
<button id="zout">−</button>
<button id="reset">reset</button>
<span id="zread">100.0%</span>
</div>
<iframe id="svgFrame" src="diagram.svg"></iframe>
<script>
const frame = document.getElementById('svgFrame');
const zread = document.getElementById('zread');
let state = { scale: 1, x: 0, y: 0 };
let svg, g;
function apply() {
if (!g) return;
g.setAttribute('transform', `translate(${state.x},${state.y}) scale(${state.scale})`);
zread.textContent = (state.scale * 100).toFixed(1) + '%';
}
frame.addEventListener('load', () => {
try {
svg = frame.contentDocument || frame.contentWindow.document;
console.log('Frame loaded, document:', svg);
if (!svg) {
console.error('Cannot access frame document');
zread.textContent = 'Error: Cannot access SVG';
return;
}
const root = svg.documentElement;
console.log('SVG root:', root);
// Wrap all contents in a group
g = svg.createElementNS('http://www.w3.org/2000/svg', 'g');
while (root.firstChild) {
g.appendChild(root.firstChild);
}
root.appendChild(g);
apply();
let dragging = false, lastX = 0, lastY = 0;
// Zoom
root.addEventListener('wheel', (e) => {
e.preventDefault();
const factor = e.deltaY < 0 ? 1.12 : 0.89;
// cursor position in screen coords (relative to iframe content)
const cx = e.clientX;
const cy = e.clientY;
// adjust translation so point under cursor stays put
state.x = cx - factor * (cx - state.x);
state.y = cy - factor * (cy - state.y);
state.scale *= factor;
apply();
}, { passive: false });
// Pan
root.addEventListener('mousedown', (e) => {
dragging = true;
lastX = e.clientX;
lastY = e.clientY;
e.preventDefault();
});
root.addEventListener('mousemove', (e) => {
if (!dragging) return;
// Scale pan speed by current zoom level for more responsive panning
const panSpeed = Math.max(1, state.scale * 2);
state.x += (e.clientX - lastX) * panSpeed;
state.y += (e.clientY - lastY) * panSpeed;
lastX = e.clientX;
lastY = e.clientY;
apply();
});
root.addEventListener('mouseup', () => { dragging = false; });
root.addEventListener('mouseleave', () => { dragging = false; });
} catch(err) {
console.error('Error accessing frame:', err);
zread.textContent = 'Error: ' + err.message;
}
});
// Buttons
document.getElementById('zin').onclick = () => { state.scale *= 1.25; apply(); };
document.getElementById('zout').onclick = () => { state.scale /= 1.25; apply(); };
document.getElementById('reset').onclick = () => { state = {scale:1,x:0,y:0}; apply(); };
</script>
</body>
</html>