1
0
forked from BRT/arc

Add UI dump visualizer with HTML, CSS, and JS components

Introduced a new tool for visualizing UI dumps, enabling users to upload XML and image files for inspection. The implementation includes an HTML structure, styled with CSS, and JavaScript for processing files and rendering elements dynamically onto a canvas. This provides a lightweight and functional interface for visual analysis.
This commit is contained in:
trnsmkot 2025-06-16 20:55:55 +07:00
parent fc2f319da2
commit 9ef2ba6315
3 changed files with 170 additions and 0 deletions

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>UI Dump Viewer</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="layout">
<div id="sidebar">
<h3>UIDump Viewer</h3>
<label>XML файл:</label><br>
<input type="file" id="xmlInput" accept=".xml"><br><br>
<label>Скриншот:</label><br>
<input type="file" id="imgInput" accept="image/*">
</div>
<div id="content">
<div id="canvas"></div>
<div id="screenshot-container">
<img id="screenshot" alt="screenshot">
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>

View File

@ -0,0 +1,70 @@
let dumpWidth = 1080;
let dumpHeight = 1920;
document.getElementById('xmlInput').addEventListener('change', handleXml);
document.getElementById('imgInput').addEventListener('change', handleImage);
function handleImage(event) {
const file = event.target.files[0];
if (!file) return;
const url = URL.createObjectURL(file);
document.getElementById('screenshot').src = url;
}
async function handleXml(event) {
const file = event.target.files[0];
if (!file) return;
const text = await file.text();
const parser = new DOMParser();
const xml = parser.parseFromString(text, "text/xml");
const nodes = Array.from(xml.querySelectorAll("node"));
const canvas = document.getElementById("canvas");
canvas.innerHTML = "";
// Автоопределение размеров дампа
let maxX = 0, maxY = 0;
for (const node of nodes) {
const bounds = node.getAttribute("bounds");
const match = bounds && bounds.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/);
if (!match) continue;
const [, , , x2, y2] = match.map(Number);
if (x2 > maxX) maxX = x2;
if (y2 > maxY) maxY = y2;
}
dumpWidth = maxX;
dumpHeight = maxY;
// Масштабирование по высоте экрана с отступами
const padding = 100;
const displayHeight = window.innerHeight - padding;
const scale = displayHeight / dumpHeight;
const displayWidth = dumpWidth * scale;
// Установка размеров canvas
canvas.style.width = `${displayWidth}px`;
canvas.style.height = `${displayHeight}px`;
for (const node of nodes) {
const bounds = node.getAttribute("bounds");
const match = bounds && bounds.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/);
if (!match) continue;
const [, x1, y1, x2, y2] = match.map(Number);
const div = document.createElement("div");
div.className = "rect";
div.style.left = `${x1 * scale}px`;
div.style.top = `${y1 * scale}px`;
div.style.width = `${(x2 - x1) * scale}px`;
div.style.height = `${(y2 - y1) * scale}px`;
const text = (node.getAttribute("text") || '').trim();
if (text) div.innerText = text;
canvas.appendChild(div);
}
}

View File

@ -0,0 +1,72 @@
body, html {
margin: 0;
height: 100%;
font-family: sans-serif;
background-color: #f4f4f4; /* вернули светлый фон */
color: #333;
}
#layout {
display: flex;
height: 100vh;
}
#sidebar {
width: 250px;
padding: 20px;
background: #ffffff; /* светлая боковая панель */
border-right: 1px solid #ccc;
box-sizing: border-box;
}
#sidebar h3, label {
color: #333;
}
#sidebar input[type="file"] {
background: #fff;
color: #000;
border: 1px solid #ccc;
padding: 6px;
margin-top: 4px;
width: 100%;
}
#content {
display: flex;
flex: 1;
align-items: center;
justify-content: space-around;
overflow: auto;
padding: 50px 20px;
box-sizing: border-box;
gap: 20px;
background-color: #f4f4f4;
}
#canvas {
position: relative;
background: #2a2a2a; /* серый фон области дампа */
border: 1px solid #444;
flex-shrink: 0;
}
#screenshot-container {
flex-shrink: 0;
}
#screenshot {
max-height: calc(100vh - 100px);
border: 1px solid #ccc;
}
.rect {
position: absolute;
border: 1px dashed #ff9800;
background: transparent;
color: #ff9800;
font-size: 11px;
font-weight: bold;
}