WIP: put everything on the same hex in a group together; get rid of x and y coordinates on counters completely

This commit is contained in:
Catalin Constantin Mititiuc 2025-06-16 22:41:28 -07:00
parent 82e55333bb
commit da6916c0e6
2 changed files with 126 additions and 36 deletions

107
index.js
View File

@ -348,8 +348,10 @@ function ptGrpToSvgPt(x, y) {
return svgP; return svgP;
} }
const grid = document.getElementById('grid');
const Counter = new function() { const Counter = new function() {
let container = cntrGrp, let container = ptGrp,
selectedClass = 'selected', selectedClass = 'selected',
dataSelector = function(troopNumber, allegiance) { dataSelector = function(troopNumber, allegiance) {
@ -361,6 +363,10 @@ const Counter = new function() {
}, },
position = function(x, y) { position = function(x, y) {
return `g[data-x="${x}"][data-y="${y}"]`;
},
counterPosition = function(x, y) {
return `use.counter[data-x="${x}"][data-x="${y}"]`; return `use.counter[data-x="${x}"][data-x="${y}"]`;
}, },
@ -370,19 +376,19 @@ const Counter = new function() {
clickClone = function() { clickClone = function() {
let { troopNumber, troopAllegiance, x, y } = this.dataset, let { troopNumber, troopAllegiance, x, y } = this.dataset,
xAttr = this.getAttribute('x'), [xAttr, yAttr] = this.parentElement.getAttribute('transform').match(/-?\d+\.?\d*/g);
yAttr = this.getAttribute('y');
if (Counter.isSelected(troopNumber, troopAllegiance)) { if (Counter.isSelected(troopNumber, troopAllegiance)) {
let trace = container.querySelector(traceSelector(troopNumber, troopAllegiance)), let trace = grid.querySelector(traceSelector(troopNumber, troopAllegiance)),
points = trace.getAttribute('points').split(' '); points = trace.getAttribute('points').split(' ');
if (`${xAttr},${yAttr}` == points.at(0)) { if (`${xAttr},${yAttr}` == points.at(0)) {
let counter = Counter.get(troopNumber, troopAllegiance); let counter = Counter.get(troopNumber, troopAllegiance);
counter.setAttributeNS(null, 'x', xAttr); counter.setAttributeNS(null, 'x', 0);
counter.setAttributeNS(null, 'y', yAttr); counter.setAttributeNS(null, 'y', 0);
counter.dataset.x = x; counter.dataset.x = x;
counter.dataset.y = y; counter.dataset.y = y;
container.querySelector(`g[data-x="${x}"][data-y="${y}"]`).appendChild(counter);
Counter.removeClones(this); Counter.removeClones(this);
trace.remove(); trace.remove();
@ -396,15 +402,19 @@ const Counter = new function() {
} }
}, },
pointerOver = function() {
// console.log('pointer over counter', this);
},
click = function() { click = function() {
if (this.classList.contains(selectedClass)) { if (this.classList.contains(selectedClass)) {
let { troopNumber, troopAllegiance } = this.dataset, let { troopNumber, troopAllegiance } = this.dataset,
trace = container.querySelector(traceSelector(troopNumber, troopAllegiance)); trace = grid.querySelector(traceSelector(troopNumber, troopAllegiance));
if (trace) { if (trace) {
let points = trace.getAttribute('points').split(' '), let points = trace.getAttribute('points').split(' '),
[xAttr, yAttr] = points.at(-2).split(','), [xAttr, yAttr] = points.at(-2).split(','),
clone = container.querySelector(`${dataSelector(troopNumber, troopAllegiance)}[x="${xAttr}"][y="${yAttr}"].clone`); clone = container.querySelector(`g[transform="translate(${xAttr} ${yAttr})"] ${dataSelector(troopNumber, troopAllegiance)}.clone`);
points.pop(); points.pop();
@ -419,6 +429,8 @@ const Counter = new function() {
this.dataset.x = clone.dataset.x; this.dataset.x = clone.dataset.x;
this.dataset.y = clone.dataset.y; this.dataset.y = clone.dataset.y;
container.querySelector(`g[data-x="${this.dataset.x}"][data-y="${this.dataset.y}"]`).appendChild(this);
clone.remove(); clone.remove();
} }
} }
@ -427,7 +439,7 @@ const Counter = new function() {
dblClick = function() { dblClick = function() {
if (this.classList.contains(selectedClass)) { if (this.classList.contains(selectedClass)) {
let { troopNumber, troopAllegiance } = this.dataset, let { troopNumber, troopAllegiance } = this.dataset,
trace = container.querySelector(traceSelector(troopNumber, troopAllegiance)); trace = grid.querySelector(traceSelector(troopNumber, troopAllegiance));
if (!trace) { if (!trace) {
Counter.remove(this); Counter.remove(this);
@ -441,7 +453,7 @@ const Counter = new function() {
}; };
this.getAt = function(x, y) { this.getAt = function(x, y) {
return container.querySelector(`${position(x, y)}:not(.clone)`); return container.querySelector(`${counterPosition(x, y)}:not(.clone)`);
}; };
this.select = function({ dataset: { troopNumber, troopAllegiance }}) { this.select = function({ dataset: { troopNumber, troopAllegiance }}) {
@ -484,34 +496,45 @@ const Counter = new function() {
if (counterNodeList.length > 0) { if (counterNodeList.length > 0) {
let counters = Array.from(counterNodeList), let counters = Array.from(counterNodeList),
original = counters.find(el => !el.classList.contains('clone')), original = counters.find(el => !el.classList.contains('clone')),
trace = container.querySelector(traceSelector(troopNumber, troopAllegiance)); trace = grid.querySelector(traceSelector(troopNumber, troopAllegiance));
// let ptContainers = counters.map(c => ptGrp.querySelector(position(c.dataset.x, c.dataset.y)));
let current = { let current = {
x: point.dataset.x, x: point.dataset.x,
y: point.dataset.y, y: point.dataset.y,
xAttr: point.getAttribute('x'), // xAttr: point.getAttribute('x'),
yAttr: point.getAttribute('y') // yAttr: point.getAttribute('y'),
transform: container.querySelector(position(point.dataset.x, point.dataset.y)).getAttribute('transform')
}, },
previous = { previous = {
x: original.dataset.x, x: original.dataset.x,
y: original.dataset.y, y: original.dataset.y,
xAttr: original.getAttribute('x'), // xAttr: original.getAttribute('x'),
yAttr: original.getAttribute('y') // yAttr: original.getAttribute('y'),
transform: container.querySelector(position(original.dataset.x, original.dataset.y)).getAttribute('transform')
} }
console.log(current.transform, previous.transform);
[current.xAttr, current.yAttr] = current.transform.match(/-?\d+\.?\d*/g);
[previous.xAttr, previous.yAttr] = previous.transform.match(/-?\d+\.?\d*/g);
counter = original.cloneNode(); counter = original.cloneNode();
counter.setAttributeNS(null, 'x', previous.xAttr); counter.setAttributeNS(null, 'x', 0);
counter.setAttributeNS(null, 'y', previous.yAttr); counter.setAttributeNS(null, 'y', 0);
counter.dataset.x = previous.x; counter.dataset.x = previous.x;
counter.dataset.y = previous.y; counter.dataset.y = previous.y;
counter.classList.remove(selectedClass); counter.classList.remove(selectedClass);
counter.classList.add('clone'); counter.classList.add('clone');
original.setAttributeNS(null, 'x', current.xAttr); original.setAttributeNS(null, 'x', 0);
original.setAttributeNS(null, 'y', current.yAttr); original.setAttributeNS(null, 'y', 0);
original.dataset.x = current.x; original.dataset.x = current.x;
original.dataset.y = current.y; original.dataset.y = current.y;
container.querySelector(`g[data-x="${current.x}"][data-y="${current.y}"]`).appendChild(original);
if (!trace) { if (!trace) {
trace = document.createElementNS(svgns, 'polyline'); trace = document.createElementNS(svgns, 'polyline');
points = `${previous.xAttr},${previous.yAttr} ${current.xAttr},${current.yAttr}`; points = `${previous.xAttr},${previous.yAttr} ${current.xAttr},${current.yAttr}`;
@ -520,12 +543,14 @@ const Counter = new function() {
trace.dataset.troopAllegiance = troopAllegiance; trace.dataset.troopAllegiance = troopAllegiance;
trace.classList.add('move-trace'); trace.classList.add('move-trace');
container.prepend(trace); grid.prepend(trace)
// container.prepend(trace);
} else { } else {
points = `${trace.getAttribute('points')} ${current.xAttr},${current.yAttr}`; points = `${trace.getAttribute('points')} ${current.xAttr},${current.yAttr}`;
} }
trace.setAttributeNS(null, 'points', points); trace.setAttributeNS(null, 'points', points);
counter.addEventListener('pointerover', pointerOver);
counter.addEventListener('click', clickClone); counter.addEventListener('click', clickClone);
} else { } else {
counter = document.createElementNS(svgns, 'use'), counter = document.createElementNS(svgns, 'use'),
@ -540,11 +565,14 @@ const Counter = new function() {
counter.dataset.y = point.dataset.y; counter.dataset.y = point.dataset.y;
counter.style.pointerEvents = 'auto'; counter.style.pointerEvents = 'auto';
counter.addEventListener('pointerover', pointerOver);
counter.addEventListener('click', click); counter.addEventListener('click', click);
counter.addEventListener('dblclick', dblClick); counter.addEventListener('dblclick', dblClick);
} }
container.appendChild(counter); container.querySelector(`g[data-x="${counter.dataset.x}"][data-y="${counter.dataset.y}"]`).appendChild(counter);
// container.appendChild(counter);
}; };
this.remove = function({ dataset: { troopNumber, troopAllegiance }}) { this.remove = function({ dataset: { troopNumber, troopAllegiance }}) {
@ -619,17 +647,36 @@ const RecordSheet = new function() {
POINTS.forEach((row, index) => row.forEach(([x, y]) => { POINTS.forEach((row, index) => row.forEach(([x, y]) => {
var cx = x * INRADIUS * 2 + (isEven(index) ? INRADIUS : 0), var cx = x * INRADIUS * 2 + (isEven(index) ? INRADIUS : 0),
cy = y * 3 / 2 * CIRCUMRADIUS, cy = y * 3 / 2 * CIRCUMRADIUS,
point = document.createElementNS(svgns, 'use'); point = document.createElementNS(svgns, 'use'),
group = document.createElementNS(svgns, 'g');
cx = parseFloat(cx.toFixed(1)); cx = parseFloat(cx.toFixed(1));
cy = parseFloat(cy.toFixed(1)); cy = parseFloat(cy.toFixed(1));
point.setAttributeNS(null, 'href', `#point`); point.setAttributeNS(null, 'href', `#point`);
point.setAttributeNS(null, 'x', cx); // point.setAttributeNS(null, 'x', cx);
point.setAttributeNS(null, 'y', cy); // point.setAttributeNS(null, 'y', cy);
point.setAttributeNS(null, 'x', 0);
point.setAttributeNS(null, 'y', 0);
point.dataset.x = x; point.dataset.x = x;
point.dataset.y = y; point.dataset.y = y;
group.setAttributeNS(null, 'transform', `translate(${cx} ${cy})`);
group.dataset.x = x;
group.dataset.y = y;
group.appendChild(point);
group.addEventListener('pointerover', e => {
group.classList.add('hover');
});
group.addEventListener('pointerout', e => {
group.classList.remove('hover');
});
point.addEventListener('click', e => { point.addEventListener('click', e => {
let selectedSoldier = document.querySelector('.soldier-record.selected'); let selectedSoldier = document.querySelector('.soldier-record.selected');
let existingOccupant = let existingOccupant =
@ -643,7 +690,7 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
if (sl) { if (sl) {
sl.classList.add('active'); sl.classList.add('active');
point.dispatchEvent(new MouseEvent('mouseout')); point.dispatchEvent(new MouseEvent('mouseout'));
point.dispatchEvent(new MouseEvent('mouseover')); point.dispatchEvent(new MouseEvent('pointerover'));
} }
} }
}); });
@ -657,12 +704,12 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
if (sl.classList.contains('active')) { if (sl.classList.contains('active')) {
point.dispatchEvent(new MouseEvent('mouseout')); point.dispatchEvent(new MouseEvent('mouseout'));
point.dispatchEvent(new MouseEvent('mouseover')); point.dispatchEvent(new MouseEvent('pointerover'));
} }
} }
}); });
point.addEventListener('mouseover', e => { point.addEventListener('pointerover', e => {
let selected = RecordSheet.getSelected(); let selected = RecordSheet.getSelected();
if (selected) { if (selected) {
@ -702,7 +749,7 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
let lineCoords = linedraw(...coords); let lineCoords = linedraw(...coords);
lineCoords.shift(); lineCoords.shift();
let s = lineCoords.map(([x, y]) => `use[data-x="${x}"][data-y="${y}"]`).join(', '); let s = lineCoords.map(([x, y]) => `use[href="#point"][data-x="${x}"][data-y="${y}"]`).join(', ');
ptGrp.querySelectorAll(s).forEach(p => p.classList.add('active')); ptGrp.querySelectorAll(s).forEach(p => p.classList.add('active'));
} }
} }
@ -720,7 +767,7 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
} }
}); });
ptGrp.appendChild(point); ptGrp.appendChild(group);
})); }));
document.querySelectorAll('.soldier-record').forEach(el => document.querySelectorAll('.soldier-record').forEach(el =>
@ -752,7 +799,7 @@ document.querySelector('#grid').addEventListener('click', e => {
if (sl) { if (sl) {
sl.classList.add('active'); sl.classList.add('active');
point.dispatchEvent(new MouseEvent('mouseout')); point.dispatchEvent(new MouseEvent('mouseout'));
point.dispatchEvent(new MouseEvent('mouseover')); point.dispatchEvent(new MouseEvent('pointerover'));
} }
}); });

View File

@ -228,11 +228,54 @@ g.troop-counter [href="#counter-prone"] {
transform: translate(-5px, 6px); transform: translate(-5px, 6px);
} }
g#points g use.counter {
r: 5px;
}
g#points g.hover use[href="#point"] {
opacity: 1;
fill: orange;
}
g#points g.hover use.counter {
stroke-width: 2px;
r: 7px;
}
g#points g.hover use.counter:not(.clone) {
stroke: orange;
}
g#points use.counter[data-troop-allegiance="davion"] {
fill: red;
}
g#points use.counter[data-troop-allegiance="liao"] {
fill: green;
}
g#points use.clone {
stroke: white;
stroke-width: 0.5px;
stroke-dasharray: 1;
}
g#points use[data-troop-allegiance="davion"].clone {
fill: rgb(255, 126, 126);
}
g#points use[data-troop-allegiance="liao"].clone {
fill: rgb(130, 190, 130);
}
/* ======================================================= */
g#counters { g#counters {
pointer-events: none; pointer-events: none;
} }
g#counters use { /* g#counters use {
r: 5px; r: 5px;
} }
@ -240,17 +283,17 @@ g#counters use:hover {
stroke: orange; stroke: orange;
stroke-width: 2px; stroke-width: 2px;
r: 8px; r: 8px;
} } */
g#counters use[data-troop-allegiance="davion"] { /* g#counters use[data-troop-allegiance="davion"] {
fill: red; fill: red;
} }
g#counters use[data-troop-allegiance="liao"] { g#counters use[data-troop-allegiance="liao"] {
fill: green; fill: green;
} } */
g#counters use.clone { /* g#counters use.clone {
stroke: white; stroke: white;
stroke-width: 0.5px; stroke-width: 0.5px;
stroke-dasharray: 1; stroke-dasharray: 1;
@ -262,7 +305,7 @@ g#counters use[data-troop-allegiance="davion"].clone {
g#counters use[data-troop-allegiance="liao"].clone { g#counters use[data-troop-allegiance="liao"].clone {
fill: rgb(130, 190, 130); fill: rgb(130, 190, 130);
} } */
text.counter, #troop-counter text { text.counter, #troop-counter text {
font-size: 12px; font-size: 12px;