<html>
<title>Visualizer</title>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
</head>
<script>
window.onload = () => {
var board = document.getElementById('board');
var fileInput = document.getElementById('fileInput');
var desc = document.getElementById('desc');
var hRange = document.getElementById('hRange');
var vRange = document.getElementById('vRange');
var lastColor = undefined;
var lastElem = undefined;
var scale = 1;
var svg = undefined;
var svgWidth = undefined;
var svgHeight = undefined;
var resetBtn = document.getElementById('resetBtn');
var relocBtn = document.getElementById('relocBtn');
var loadDesc = (svgElem) => {
var mgeType = svgElem.attributes['tag:type'];
if (mgeType === undefined) {
return;
}
var elemList = [];
for (attrName of svgElem.getAttributeNames()) {
var prefix = 'tag:';
if (!attrName.startsWith(prefix)) {
continue;
}
var elem = '<p>' + attrName.substr(prefix.length) + ': ' + svgElem.attributes[attrName].value + '</p>'
elemList.push(elem);
}
desc.innerHTML = elemList.join('');
};
var selectElem = svgElem => {
loadDesc(svgElem);
lastColor = svgElem.attributes['fill'].value;
lastElem = svgElem;
svgElem.attributes['fill'].value = 'green';
};
var unselectLast = svgElem => {
if (lastElem) {
lastElem.attributes['fill'].value = lastColor;
}
lastElem = undefined;
lastColor = undefined;
};
var recLoadSVG = svgElem => {
if (svgElem.children === undefined) {
return;
}
svgElem.onmousedown = e => {
var mgeType = svgElem.attributes['tag:type'];
if (mgeType === undefined) {
return;
}
unselectLast();
selectElem(svgElem);
e.stopPropagation();
};
for (child of svgElem.children) {
recLoadSVG(child);
}
}
var scaleBoard = (x, y) => {
var transform = 'scale(' + x + ',' + y + ')';
svg.setAttribute('transform', transform);
board.style['width'] = svgWidth * x;
board.style['height'] = svgHeight * y;
}
var autoScaleBoard = () => {
var hRangeValue = Math.sqrt(Number(hRange.value) / 10);
var vRangeValue = Math.sqrt(Number(vRange.value) / 10);
scaleBoard(Number(hRangeValue), Number(vRangeValue));
}
var zoomBoard = dScale => {
scale *= dScale;
scaleBoard(scale, scale);
};
var reset = () => {
if (!svgHeight || !svgWidth) {
return;
}
var vScale = window.screen.availHeight / svgHeight;
var hScale = window.screen.availWidth / svgWidth;
var minScale = Math.min(hScale, vScale);
zoomBoard(minScale / scale);
window.scrollTo({
top: 0,
left: 0,
});
};
var loadSVG = () => {
var file = fileInput.files[0];
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = e => {
board.innerHTML = '<p style="margin: 0;">' + e.target.result + '</p>';
svg = board.children[0].children[0];
svgWidth = svg.attributes['width'].value;
svgHeight = svg.attributes['height'].value;
for (child of board.children) {
recLoadSVG(child);
var svgInfo = child.attributes['svg:info'];
if (svgInfo !== undefined) {
var elemList = [];
for (attrName of child.getAttributeNames()) {
var prefix = 'svg:';
if (!attrName.startsWith(prefix)) {
continue;
}
var elem = '<p>' + attrName.substr(prefix.length) + ': ' + child.attributes[attrName].value + '</p>'
elemList.push(elem);
}
info.innerHTML = elemList.join('');
}
}
setTimeout(reset, 1);
};
}
window.addEventListener('wheel', e => {
if (e.ctrlKey) {
e.preventDefault();
e.stopPropagation();
var factor = 1;
if (e.deltaY < 0) {
factor = 1.1;
} else if (e.deltaY > 0) {
factor = 1 / 1.1;
}
zoomBoard(factor);
var newPageX = e.pageX * factor;
var newPageY = e.pageY * factor;
x = newPageX - e.x;
y = newPageY - e.y;
window.scrollTo({
top: y,
left: x,
});
} else if (e.altKey) {
}
}, { 'passive': false });
fileInput.onchange = loadSVG;
resetBtn.onclick = reset;
relocBtn.onclick = () => {
if (!lastElem) {
return;
}
y = scale * lastElem.attributes['y'].value;
x = scale * lastElem.attributes['x'].value;
window.scrollTo({
top: y - window.screen.availHeight/2,
left: x - window.screen.availWidth/2,
behavior: 'smooth',
});
};
};
</script>
<body>
<p id="board"
style="white-space: nowrap; display: flex; justify-content: center; align-content: center; align-items: center; margin: 0; left: 0;">
</p>
<div style="display: flex; position: fixed; top: 0; left: 0; right: 0; background-color: white; flex-grow: 2;">
<input type='file' id='fileInput'></input>
<div style="flex-grow: 1;"></div>
<button id='resetBtn'>reset</button>
<button id='relocBtn'>reloc</button>
</div>
<p id="desc" style="position: fixed; bottom: 0; background-color: white;">desc</p>
<p id="info" style="position: fixed;top: 0; right: 0; background-color: white;">info</p>
</body>
</html>