Alex got his trails
This commit is contained in:
parent
0627dfb29a
commit
66ed711fec
5 changed files with 90 additions and 4 deletions
|
|
@ -20,6 +20,7 @@
|
|||
<div id="mapContainer">
|
||||
<div id="mapGroup">
|
||||
<img id="map" src="dereth.png" alt="Dereth map">
|
||||
<svg id="trails"></svg>
|
||||
<div id="dots"></div>
|
||||
</div>
|
||||
<div id="tooltip" class="tooltip"></div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ const wrap = document.getElementById('mapContainer');
|
|||
const group = document.getElementById('mapGroup');
|
||||
const img = document.getElementById('map');
|
||||
const dots = document.getElementById('dots');
|
||||
const trailsContainer = document.getElementById('trails');
|
||||
const list = document.getElementById('playerList');
|
||||
const btnContainer = document.getElementById('sortButtons');
|
||||
const tooltip = document.getElementById('tooltip');
|
||||
|
|
@ -130,11 +131,17 @@ function hideTooltip() {
|
|||
/* ---------- polling and initialization -------------------------- */
|
||||
async function pollLive() {
|
||||
try {
|
||||
const { players } = await (await fetch('/live/')).json();
|
||||
const [liveRes, trailsRes] = await Promise.all([
|
||||
fetch('/live/'),
|
||||
fetch('/trails/?seconds=600'),
|
||||
]);
|
||||
const { players } = await liveRes.json();
|
||||
const { trails } = await trailsRes.json();
|
||||
currentPlayers = players;
|
||||
renderTrails(trails);
|
||||
renderList();
|
||||
} catch (e) {
|
||||
console.error('Live fetch failed:', e);
|
||||
console.error('Live or trails fetch failed:', e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -147,6 +154,12 @@ function startPolling() {
|
|||
img.onload = () => {
|
||||
imgW = img.naturalWidth;
|
||||
imgH = img.naturalHeight;
|
||||
// size the SVG trails container to match the map dimensions
|
||||
if (trailsContainer) {
|
||||
trailsContainer.setAttribute('viewBox', `0 0 ${imgW} ${imgH}`);
|
||||
trailsContainer.setAttribute('width', `${imgW}`);
|
||||
trailsContainer.setAttribute('height', `${imgH}`);
|
||||
}
|
||||
fitToWindow();
|
||||
startPolling();
|
||||
};
|
||||
|
|
@ -204,6 +217,27 @@ function render(players) {
|
|||
});
|
||||
}
|
||||
|
||||
/* ---------- rendering trails ------------------------------- */
|
||||
function renderTrails(trailData) {
|
||||
trailsContainer.innerHTML = '';
|
||||
const byChar = trailData.reduce((acc, pt) => {
|
||||
(acc[pt.character_name] = acc[pt.character_name] || []).push(pt);
|
||||
return acc;
|
||||
}, {});
|
||||
for (const [name, pts] of Object.entries(byChar)) {
|
||||
if (pts.length < 2) continue;
|
||||
const points = pts.map(pt => {
|
||||
const { x, y } = worldToPx(pt.ew, pt.ns);
|
||||
return `${x},${y}`;
|
||||
}).join(' ');
|
||||
const poly = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
|
||||
poly.setAttribute('points', points);
|
||||
poly.setAttribute('stroke', hue(name));
|
||||
poly.setAttribute('fill', 'none');
|
||||
poly.setAttribute('class', 'trail-path');
|
||||
trailsContainer.appendChild(poly);
|
||||
}
|
||||
}
|
||||
/* ---------- selection centering, focus zoom & blink ------------ */
|
||||
function selectPlayer(p, x, y) {
|
||||
selected = p.character_name;
|
||||
|
|
|
|||
|
|
@ -202,3 +202,17 @@ body {
|
|||
/* hover & selected states */
|
||||
#playerList li:hover { background: var(--card-hov); }
|
||||
#playerList li.selected { background: #454545; }
|
||||
/* trails paths */
|
||||
#trails {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.trail-path {
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
stroke-opacity: 0.7;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue