+ Davion
+
- Davion
@@ -244,10 +278,13 @@
+ Liao
+
- Liao
diff --git a/index.js b/index.js
index b316a24..f9e4ba8 100644
--- a/index.js
+++ b/index.js
@@ -64,9 +64,13 @@ const svgns = "http://www.w3.org/2000/svg",
map = document.querySelector('rect#map'),
hex = document.getElementById('point'),
ptGrp = document.getElementById('points'),
+ cntrGrp = document.getElementById('counters'),
settingsPanel = document.getElementById('panel'),
recordSheetVisibility = document.querySelector('#content input[type="checkbox"].visible');
+const q = s => document.querySelector(s),
+ qA = s => document.querySelectorAll(s);
+
const { x: VIEWBOX_X, y: VIEWBOX_Y, width: VIEWBOX_WIDTH, height: VIEWBOX_HEIGHT } =
svg.viewBox.baseVal;
@@ -135,7 +139,7 @@ let info = document.getElementById('status');
return acc;
}, {});
- let transform = `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) scale(${scale}) `
+ let transform = `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) scale(${scale})`;
target.style.transform = transform;
});
@@ -177,27 +181,22 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
{troopNumber, troopAllegiance} = selectedSoldier.dataset,
selector = troopSelector(troopNumber, troopAllegiance);
- let transProp = getComputedStyle(ptGrp).transform.match(/-?\d+\.?\d*/g),
- mtx = new DOMMatrix(transProp || ''),
- pt = new DOMPoint(point.x.baseVal.value, point.y.baseVal.value),
- svgP = pt.matrixTransform(mtx);
-
info.querySelector('#hex-count').textContent = '-';
info.style.display = 'none';
ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
svg.querySelectorAll('.sight-line').forEach(el => el.remove());
- counter.setAttributeNS(null, 'cx', svgP.x);
- counter.setAttributeNS(null, 'cy', svgP.y);
- counter.setAttributeNS(null, 'r', '0.25in');
+ counter.setAttributeNS(null, 'cx', cx);
+ counter.setAttributeNS(null, 'cy', cy);
+ counter.setAttributeNS(null, 'r', '5');
counter.dataset.troopNumber = troopNumber;
counter.dataset.troopAllegiance = troopAllegiance;
counter.dataset.x = point.dataset.x;
counter.dataset.y = point.dataset.y;
counter.classList.add('counter');
- text.setAttributeNS(null, 'x', svgP.x);
- text.setAttributeNS(null, 'y', svgP.y);
+ text.setAttributeNS(null, 'x', cx);
+ text.setAttributeNS(null, 'y', cy);
text.dataset.troopNumber = troopNumber;
text.dataset.troopAllegiance = troopAllegiance;
text.textContent = troopNumber;
@@ -205,7 +204,7 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
document.querySelectorAll(`.counter${selector}`).forEach(el => el.remove());
- counter.addEventListener('click', e => {
+ counter.addEventListener('dblclick', e => {
let selectedSoldier = document.querySelector('.soldier-record.selected');
if (selectedSoldier) {
@@ -223,40 +222,50 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
}
});
- counter.addEventListener('mouseenter', e => {
- let selectedSoldier = document.querySelector('.soldier-record.selected');
+ // counter.addEventListener('mouseenter', e => {
+ // let selectedSoldier = document.querySelector('.soldier-record.selected');
- if (selectedSoldier) {
- let {troopNumber, troopAllegiance} = selectedSoldier.dataset,
- selector = troopSelector(troopNumber, troopAllegiance),
- source = document.querySelector(`circle.counter${selector}`),
+ // if (selectedSoldier) {
+ // let {troopNumber, troopAllegiance} = selectedSoldier.dataset,
+ // selector = troopSelector(troopNumber, troopAllegiance),
+ // source = document.querySelector(`circle.counter${selector}`),
- // TODO: use isEqualNode() method instead
- sourceAndTargetAreNotTheSame = [
- troopNumber != e.target.dataset.troopNumber,
- troopAllegiance != e.target.dataset.troopAllegiance
- ].some(el => el);
+ // // TODO: use isEqualNode() method instead
+ // sourceAndTargetAreNotTheSame = [
+ // troopNumber != e.target.dataset.troopNumber,
+ // troopAllegiance != e.target.dataset.troopAllegiance
+ // ].some(el => el);
- if (source && sourceAndTargetAreNotTheSame) {
- let sightLine = document.createElementNS(svgns, 'line');
+ // if (source && sourceAndTargetAreNotTheSame) {
+ // let sightLine = document.createElementNS(svgns, 'line');
- sightLine.classList.add('sight-line');
- sightLine.setAttributeNS(null, 'x1', source.getAttribute('cx'));
- sightLine.setAttributeNS(null, 'y1', source.getAttribute('cy'));
- sightLine.setAttributeNS(null, 'x2', e.target.getAttribute('cx'));
- sightLine.setAttributeNS(null, 'y2', e.target.getAttribute('cy'));
+ // sightLine.classList.add('sight-line');
+ // sightLine.setAttributeNS(null, 'x1', source.getAttribute('cx'));
+ // sightLine.setAttributeNS(null, 'y1', source.getAttribute('cy'));
+ // sightLine.setAttributeNS(null, 'x2', e.target.getAttribute('cx'));
+ // sightLine.setAttributeNS(null, 'y2', e.target.getAttribute('cy'));
- svg.appendChild(sightLine);
- }
- }
- });
+ // svg.appendChild(sightLine);
+ // }
+ // }
+ // });
- counter.addEventListener('mouseleave', e => {
- document.querySelectorAll('.sight-line').forEach(el => el.remove());
- });
+ // counter.addEventListener('mouseleave', e => {
+ // document.querySelectorAll('.sight-line').forEach(el => el.remove());
+ // });
+
+ // svg.insertBefore(counter, ptGrp);
+
+ // let symbCtr = document.createElementNS(svgns, 'use');
+
+ // symbCtr.setAttributeNS(null, 'href', '#troop-counter');
+ // symbCtr.setAttributeNS(null, 'x', cx);
+ // symbCtr.setAttributeNS(null, 'y', cy);
- svg.insertBefore(counter, ptGrp);
- svg.insertBefore(text, ptGrp);
+ // cntrGrp.appendChild(symbCtr);
+
+ cntrGrp.appendChild(counter);
+ cntrGrp.appendChild(text);
}
});
@@ -271,6 +280,13 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
let sl = svg.querySelector('.sight-line');
if (counter && (!sl || sl.classList.contains('active'))) {
+ if (sl) {
+ info.querySelector('#hex-count').textContent = '-';
+ info.style.display = 'none';
+ ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
+ svg.querySelectorAll('.sight-line').forEach(el => el.remove());
+ }
+
let source = ptGrp.querySelector(`use[data-x="${counter.dataset.x}"][data-y="${counter.dataset.y}"]`);
let [x1, y1] = [source.x.baseVal.value, source.y.baseVal.value];
let [x2, y2] = [e.target.x.baseVal.value, e.target.y.baseVal.value];
@@ -288,7 +304,8 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
sightLine.setAttributeNS(null, 'x2', svgX2);
sightLine.setAttributeNS(null, 'y2', svgY2);
- svg.insertBefore(sightLine, ptGrp);
+ // svg.insertBefore(sightLine, ptGrp);
+ document.getElementById('grid').appendChild(sightLine);
let coords = [
counter.dataset.x,
@@ -309,16 +326,16 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
}
});
- point.addEventListener('mouseout', e => {
- let sl = svg.querySelector('.sight-line.active');
+ // point.addEventListener('mouseout', e => {
+ // let sl = svg.querySelector('.sight-line.active');
- if (sl) {
- info.querySelector('#hex-count').textContent = '-';
- info.style.display = 'none';
- ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
- svg.querySelectorAll('.sight-line').forEach(el => el.remove());
- }
- });
+ // if (sl) {
+ // info.querySelector('#hex-count').textContent = '-';
+ // info.style.display = 'none';
+ // ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
+ // svg.querySelectorAll('.sight-line').forEach(el => el.remove());
+ // }
+ // });
point.addEventListener('click', e => {
let sl = svg.querySelector('.sight-line');
@@ -477,7 +494,7 @@ function linedraw(x1, y1, x2, y2) {
for (let i = 0; i <= n; i++) {
let lerp = axial_lerp(axial1.q, axial1.r, axial2.q, axial2.r, 1.0 / n * i),
round = axial_round(lerp.q, lerp.r),
- { x, y } = axial_to_evenr(round.q, round.r)
+ { x, y } = axial_to_evenr(round.q, round.r);
results.push([x, y]);
}
@@ -485,22 +502,22 @@ function linedraw(x1, y1, x2, y2) {
return results;
}
-map.addEventListener('mousemove', e => {
- let boundingRect = e.target.getBoundingClientRect();
- let pointerX = e.clientX - boundingRect.left;
- let pointerY = e.clientY - boundingRect.top;
- let [maxXpx, maxYpx] = [e.target.width, e.target.height].map(v => v.baseVal.value);
-
- let activeFiringArc = document.querySelector('polygon.firing-arc.active');
+function positionFiringArc(e) {
+ activeFiringArc = document.querySelector('polygon.firing-arc.active');
// TODO: handle exactly horizontal and vertical lines
if (activeFiringArc) {
- let {x: x1px, y: y1px} = activeFiringArc.points[0];
+ let board = document.getElementById('image-maps'),
+ { width, height } = board.getBBox(),
+ pt = new DOMPoint(e.clientX, e.clientY),
+ { x: pointerX, y: pointerY } = pt.matrixTransform(board.getScreenCTM().inverse()),
+ [maxXpx, maxYpx] = [width, height],
+ {x: x1px, y: y1px} = activeFiringArc.points[0];
let [x2px, y2px] = [
- pointerX / boundingRect.width * maxXpx,
- pointerY / boundingRect.height * maxYpx
+ pointerX / width * maxXpx,
+ pointerY / height * maxYpx
];
let xDiff = x2px - x1px;
@@ -595,7 +612,7 @@ map.addEventListener('mousemove', e => {
activeFiringArc.setAttributeNS(null, 'points', points);
}
-});
+}
document.querySelectorAll('.soldier-record').forEach(el =>
el.addEventListener('click', e => {
@@ -639,15 +656,13 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener('
if (counter) {
let arcLayer = document.getElementById('firing-arcs');
- let firingArcPlacementListener = e => {
- document.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active'));
- document.querySelector('#point').style.display = '';
- map.removeEventListener('click', firingArcPlacementListener);
- };
-
- map.addEventListener('click', firingArcPlacementListener);
+ let grid = document.getElementById('grid');
+ const transform = getComputedStyle(grid).transform.match(/-?\d+\.?\d*/g);
+ const pt = new DOMPoint(counter.cx.baseVal.value, counter.cy.baseVal.value);
+ const mtx = new DOMMatrix(transform);
+ let tPt = pt.matrixTransform(mtx);
- let pivotPoint = [counter.cx.baseVal.value, counter.cy.baseVal.value];
+ let pivotPoint = [tPt.x, tPt.y];
let firingArc = document.createElementNS(svgns, 'polygon');
firingArc.classList.add('firing-arc', 'active');
@@ -656,8 +671,17 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener('
firingArc.dataset.size = e.target.dataset.size;
firingArc.setAttributeNS(null, 'points', `${pivotPoint} ${pivotPoint} ${pivotPoint}`);
- arcLayer.prepend(firingArc);
+ arcLayer.appendChild(firingArc);
+ let firingArcPlacementListener = e => {
+ document.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active'));
+ document.querySelector('#point').style.display = '';
+ firingArc.removeEventListener('click', firingArcPlacementListener);
+ svg.removeEventListener('mousemove', positionFiringArc);
+ };
+
+ svg.addEventListener('mousemove', positionFiringArc);
+ firingArc.addEventListener('click', firingArcPlacementListener);
document.querySelector('#point').style.display = 'none';
}
}
@@ -674,30 +698,25 @@ document.querySelectorAll('.clear-firing-arcs').forEach(el =>
svg.addEventListener('wheel', e => {
e.preventDefault();
- // const pt = svg.createSVGPoint();
- const pt = new DOMPoint(e.clientX, e.clientY);
-
- // pt.x = e.clientX;
- // pt.y = e.clientY;
-
- const svgP = pt.matrixTransform(svg.getScreenCTM().inverse());
+ const pt = new DOMPoint(e.clientX, e.clientY),
+ svgP = pt.matrixTransform(svg.getScreenCTM().inverse());
- let { x, y, width, height } = svg.viewBox.baseVal;
+ let { x, y, width, height } = svg.viewBox.baseVal,
- let widthDelta = width * 0.25;
- let heightDelta = height * 0.25;
+ widthDelta = width * 0.25,
+ heightDelta = height * 0.25,
- let xChange = (svgP.x - x) / width * widthDelta;
- let yChange = (svgP.y - y) / height * heightDelta;
+ xChange = (svgP.x - x) / width * widthDelta,
+ yChange = (svgP.y - y) / height * heightDelta,
- let widthChange = (1 - ((svgP.x - x) / width)) * widthDelta;
- let heightChange = (1 - ((svgP.y - y) / height)) * heightDelta;
+ widthChange = (1 - ((svgP.x - x) / width)) * widthDelta,
+ heightChange = (1 - ((svgP.y - y) / height)) * heightDelta,
- let newX = parseInt(e.deltaY < 0 ? x + xChange : x - xChange);
- let newWidth = parseInt(e.deltaY < 0 ? width - xChange - widthChange : width + xChange + widthChange);
+ newX = parseInt(e.deltaY < 0 ? x + xChange : x - xChange),
+ newWidth = parseInt(e.deltaY < 0 ? width - xChange - widthChange : width + xChange + widthChange),
- let newY = parseInt(e.deltaY < 0 ? y + yChange : y - yChange);
- let newHeight = parseInt(e.deltaY < 0 ? height - yChange - heightChange : height + yChange + heightChange);
+ newY = parseInt(e.deltaY < 0 ? y + yChange : y - yChange),
+ newHeight = parseInt(e.deltaY < 0 ? height - yChange - heightChange : height + yChange + heightChange);
// console.log('VIEWBOX_X', 'VIEWBOX_Y', VIEWBOX_X, VIEWBOX_Y);
// console.log('VIEWBOX_WIDTH', 'VIEWBOX_HEIGHT', VIEWBOX_WIDTH, VIEWBOX_HEIGHT);
@@ -727,6 +746,17 @@ svg.addEventListener('wheel', e => {
svg.setAttributeNS(null, 'viewBox', vb);
});
+ptGrp.addEventListener('mouseout', e => {
+ let sl = svg.querySelector('.sight-line');
+
+ if (sl && sl.classList.contains('active')) {
+ info.querySelector('#hex-count').textContent = '-';
+ info.style.display = 'none';
+ ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
+ svg.querySelectorAll('.sight-line').forEach(el => el.remove());
+ }
+});
+
svg.addEventListener('pointerdown', e => {
const minPanDistanceThreshold = 5;
@@ -772,6 +802,30 @@ svg.addEventListener('pointerdown', e => {
svg.addEventListener('pointerup', pointerUp);
});
+// svg.addEventListener('pointermove', e => {
+// if (e.target.classList.contains('counter')) {
+// let p = svg.querySelector(`use[data-x="${e.target.dataset.x}"][data-y="${e.target.dataset.y}"]`);
+// p.classList.add('hover');
+// p.dispatchEvent(new MouseEvent('mouseover'));
+
+// let removeHover = e => {
+// p.classList.remove('hover');
+// e.target.removeEventListener('pointerout', removeHover);
+// };
+
+// e.target.addEventListener('pointerout', removeHover);
+// }
+// });
+
recordSheetVisibility.addEventListener('input', e => {
localStorage.setItem('recordsVisibility', recordSheetVisibility.checked);
+});
+
+document.querySelector('.end-move').addEventListener('click', e => {
+ let selectedSoldier = document.querySelector('.soldier-record.selected');
+
+ if (selectedSoldier) {
+ selectedSoldier.classList.toggle('selected');
+ selectedSoldier.classList.toggle('movement-ended');
+ }
});
\ No newline at end of file
diff --git a/style.css b/style.css
index 9954d29..9e481fc 100644
--- a/style.css
+++ b/style.css
@@ -16,18 +16,22 @@ svg {
height: 100%;
}
-svg text {
+svg image#numbers {
+ image-rendering: pixelated;
+}
+
+/* svg text {
user-select: none;
font-size: 4px;
fill: black;
- /* stroke: black; */
+ stroke: black;
stroke-width: 0.2px;
font-weight: bold;
transform: translateY(6px);
font-family: monospace;
text-anchor: middle;
- /* display: none; */
-}
+ display: none;
+} */
div#status {
position: absolute;
@@ -65,6 +69,10 @@ div#content {
border-bottom: 1px solid gray;
}
+#content #buttons {
+ line-height: 1.5em;
+}
+
#content > div {
display: none;
}
@@ -121,25 +129,31 @@ div#content {
}
svg > defs > #point {
- fill: teal;
- fill-opacity: 0.2;
- stroke: black;
- stroke-width: 0.5px;
+ fill: inherit;
+ fill-opacity: inherit;
+ stroke: inherit;
+ stroke-width: inherit;
+ stroke-opacity: inherit;
}
use[href="#point"] {
opacity: 0;
+ fill: teal;
+ fill-opacity: 0.2;
+ stroke: black;
+ stroke-width: 0.5px;
}
-use[href="#point"]:hover {
+use[href="#point"]:hover, use[href="#point"].hover {
opacity: 1;
+ fill: orange;
}
use[href="#point"].active {
opacity: 1;
}
-g#points {
+g#grid {
transform: translate(19px, 31px) scale(4);
}
@@ -174,10 +188,10 @@ image.map-scans {
text-align: right;
}
-circle.counter {
+/* circle.counter {
stroke: transparent;
stroke-width: 0.5in;
-}
+} */
circle.counter[data-troop-allegiance="liao"] {
fill: green;
@@ -187,15 +201,19 @@ circle.counter[data-troop-allegiance="davion"] {
fill: red;
}
-text.counter {
- font-size: 80px;
+text.counter, #troop-counter text {
+ font-size: 12px;
font-weight: bold;
- stroke: black;
+ /* stroke: black; */
fill: white;
- stroke-width: 2px;
+ /* stroke-width: 0.5px; */
font-family: sans-serif;
cursor: default;
+ text-anchor: middle;
+ /* transform: translateY(25%); */
+ transform: translateY(4px);
pointer-events: none;
+ user-select: none;
}
rect#map {
@@ -226,7 +244,8 @@ line.firing-arc {
.sight-line {
stroke: orangered;
- stroke-width: 3px;
+ stroke-width: 0.5px;
+ pointer-events: none;
}
.soldier-record {
@@ -236,6 +255,15 @@ line.firing-arc {
background-color: white;
}
+.soldier-record.selected {
+ background-color: khaki;
+}
+
+.soldier-record.movement-ended {
+ background-color: none;
+ opacity: 0.5;
+}
+
image#img1 {
transform: scale(3.41) rotate(-0.15deg);
/* opacity: 0.33; */
@@ -258,10 +286,6 @@ img.logo {
display: block;
}
-div.soldier-record.selected {
- background-color: khaki;
-}
-
rect#debug-view-box {
/* stroke: red;
stroke-width: 20px; */
@@ -269,6 +293,24 @@ rect#debug-view-box {
fill-opacity: 0.2;
}
+#troop-counter > .outer {
+ fill: inherit;
+}
+
+#troop-counter > .inner {
+ fill: red;
+}
+
+use[href="#troop-counter"] {
+ transform: translate(-7.5px, -7.5px);
+ fill: transparent;
+ /* fill: orange; */
+}
+
+use[href="#troop-counter"]:hover {
+ fill: orange;
+}
+
@media (width >= 1800px) {
#record-sheet {
flex-direction: row;
--
cgit v1.2.3