WIP: end movement, turn buttons
This commit is contained in:
parent
b095228f37
commit
5276532e70
59
index.html
59
index.html
@ -143,19 +143,50 @@
|
|||||||
<div id="map-container">
|
<div id="map-container">
|
||||||
<svg viewbox="-49 -40 2390 3163" xmlns="http://www.w3.org/2000/svg">
|
<svg viewbox="-49 -40 2390 3163" xmlns="http://www.w3.org/2000/svg">
|
||||||
<defs>
|
<defs>
|
||||||
<!-- <circle id="point" cx="0" cy="0" r="0.07in" /> -->
|
|
||||||
<!-- <circle id="point" cx="0" cy="0" r="50" /> -->
|
|
||||||
<!-- <polygon id="point" points="0,100 86.6,50 86.6,-50 0,-100 -86.6,-50 -86.6,50" /> -->
|
|
||||||
<polygon id="point" points="0,10 8.66,5 8.66,-5 0,-10 -8.66,-5 -8.66,5" />
|
<polygon id="point" points="0,10 8.66,5 8.66,-5 0,-10 -8.66,-5 -8.66,5" />
|
||||||
<!-- <text id="asterisk" x="-0.06in" y="0.22in">*</text> -->
|
|
||||||
|
<symbol id="troop-counter" viewBox="-8 -8 16 16" width="15" height="15">
|
||||||
|
<circle class="outer" cx="0" cy="0" r="8" />
|
||||||
|
<circle class="inner" cx="0" cy="0" r="6" />
|
||||||
|
<text>1</text>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<image id="numbers" href="rendered_numbers.png" width="182" height="22" />
|
||||||
|
|
||||||
|
<symbol id="n1" viewBox="1 0 17 22" width="17" height="22"><use href="#numbers" /></symbol>
|
||||||
|
<symbol id="n2" viewBox="19 0 16 22" width="16" height="22"><use href="#numbers" /></symbol>
|
||||||
|
<symbol id="n3" viewBox="36 0 18 22" width="18" height="22"><use href="#numbers" /></symbol>
|
||||||
|
<symbol id="n4" viewBox="54 0 18 22" width="18" height="22"><use href="#numbers" /></symbol>
|
||||||
|
<symbol id="n5" viewBox="0 0 18 22" width="18" height="22"><use href="#numbers" /></symbol>
|
||||||
|
<symbol id="n6" viewBox="0 0 18 22" width="18" height="22"><use href="#numbers" /></symbol>
|
||||||
|
<symbol id="n7" viewBox="0 0 18 22" width="18" height="22"><use href="#numbers" /></symbol>
|
||||||
|
<symbol id="n8" viewBox="0 0 18 22" width="18" height="22"><use href="#numbers" /></symbol>
|
||||||
|
<symbol id="n9" viewBox="0 0 18 22" width="18" height="22"><use href="#numbers" /></symbol>
|
||||||
|
<symbol id="n0" viewBox="0 0 18 22" width="18" height="22"><use href="#numbers" /></symbol>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
<rect id="background" x="-1" y="-1" width="2287" height="3087" />
|
<rect id="background" x="-1" y="-1" width="2287" height="3087" />
|
||||||
|
|
||||||
|
<g id="image-maps">
|
||||||
<image id="map2" class="map-scans" href="scans/map2.jpg" width="2284" height="1518" x="2" y="2" />
|
<image id="map2" class="map-scans" href="scans/map2.jpg" width="2284" height="1518" x="2" y="2" />
|
||||||
<image id="map3" class="map-scans" href="scans/map3.jpg" width="2284" height="1518" x="4" y="1564" />
|
<image id="map3" class="map-scans" href="scans/map3.jpg" width="2284" height="1518" x="4" y="1564" />
|
||||||
|
</g>
|
||||||
|
|
||||||
<g id="firing-arcs"></g>
|
<g id="firing-arcs"></g>
|
||||||
<rect id="map" x="-1" y="-1" width="2287" height="3087" />
|
|
||||||
|
<g id="grid">
|
||||||
<g id="points"></g>
|
<g id="points"></g>
|
||||||
|
<!-- <g id="firing-arcs"></g> -->
|
||||||
|
<g id="counters"></g>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<image style="image-rendering: pixelated" href="rendered_numbers.png" x="0" y="-46" width="182" height="22" opacity="0.5" />
|
||||||
|
|
||||||
|
<use href="#n1" x="1" y="-40" opacity="0.5" />
|
||||||
|
<use href="#n2" x="19" y="-40" opacity="0.5" />
|
||||||
|
<use href="#n3" x="36" y="-40" opacity="0.5" />
|
||||||
|
<use href="#n4" x="54" y="-40" opacity="0.5" />
|
||||||
|
|
||||||
<!-- <rect id="debug-view-box" x="-100" y="-100" width="3400" height="4500" /> -->
|
<!-- <rect id="debug-view-box" x="-100" y="-100" width="3400" height="4500" /> -->
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
@ -183,10 +214,13 @@
|
|||||||
<div>
|
<div>
|
||||||
<!-- <img class="logo" src="logo-davion.png" /> -->
|
<!-- <img class="logo" src="logo-davion.png" /> -->
|
||||||
<p>
|
<p>
|
||||||
<button type="button" class="clear-firing-arcs" data-allegiance="davion">
|
|
||||||
Clear Firing Arcs
|
|
||||||
</button>
|
|
||||||
<strong>Davion</strong>
|
<strong>Davion</strong>
|
||||||
|
<button type="button" class="end-move" data-allegiance="davion">
|
||||||
|
End Movement
|
||||||
|
</button>
|
||||||
|
<button type="button" class="clear-firing-arcs" data-allegiance="davion">
|
||||||
|
End Turn
|
||||||
|
</button>
|
||||||
<br>
|
<br>
|
||||||
<!-- 1st Squad, 3rd Platoon, Bravo Company, 2nd Battalion<br>
|
<!-- 1st Squad, 3rd Platoon, Bravo Company, 2nd Battalion<br>
|
||||||
17th Kestral Mechanized Infantry -->
|
17th Kestral Mechanized Infantry -->
|
||||||
@ -244,10 +278,13 @@
|
|||||||
<div>
|
<div>
|
||||||
<!-- <img class="logo" src="logo-liao.png" /> -->
|
<!-- <img class="logo" src="logo-liao.png" /> -->
|
||||||
<p>
|
<p>
|
||||||
<button type="button" class="clear-firing-arcs" data-allegiance="liao">
|
|
||||||
Clear Firing Arcs
|
|
||||||
</button>
|
|
||||||
<strong>Liao</strong>
|
<strong>Liao</strong>
|
||||||
|
<button type="button" class="end-move" data-allegiance="liao">
|
||||||
|
End Movement
|
||||||
|
</button>
|
||||||
|
<button type="button" class="clear-firing-arcs" data-allegiance="liao">
|
||||||
|
End Turn
|
||||||
|
</button>
|
||||||
<br>
|
<br>
|
||||||
<!-- 2nd Squad, 1st Platoon, 3rd Company, 2nd Battalion<br>
|
<!-- 2nd Squad, 1st Platoon, 3rd Company, 2nd Battalion<br>
|
||||||
Aldebaran Home Guard -->
|
Aldebaran Home Guard -->
|
||||||
|
230
index.js
230
index.js
@ -64,9 +64,13 @@ const svgns = "http://www.w3.org/2000/svg",
|
|||||||
map = document.querySelector('rect#map'),
|
map = document.querySelector('rect#map'),
|
||||||
hex = document.getElementById('point'),
|
hex = document.getElementById('point'),
|
||||||
ptGrp = document.getElementById('points'),
|
ptGrp = document.getElementById('points'),
|
||||||
|
cntrGrp = document.getElementById('counters'),
|
||||||
settingsPanel = document.getElementById('panel'),
|
settingsPanel = document.getElementById('panel'),
|
||||||
recordSheetVisibility = document.querySelector('#content input[type="checkbox"].visible');
|
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 } =
|
const { x: VIEWBOX_X, y: VIEWBOX_Y, width: VIEWBOX_WIDTH, height: VIEWBOX_HEIGHT } =
|
||||||
svg.viewBox.baseVal;
|
svg.viewBox.baseVal;
|
||||||
|
|
||||||
@ -135,7 +139,7 @@ let info = document.getElementById('status');
|
|||||||
return acc;
|
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;
|
target.style.transform = transform;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -177,27 +181,22 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
|
|||||||
{troopNumber, troopAllegiance} = selectedSoldier.dataset,
|
{troopNumber, troopAllegiance} = selectedSoldier.dataset,
|
||||||
selector = troopSelector(troopNumber, troopAllegiance);
|
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.querySelector('#hex-count').textContent = '-';
|
||||||
info.style.display = 'none';
|
info.style.display = 'none';
|
||||||
ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
|
ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
|
||||||
svg.querySelectorAll('.sight-line').forEach(el => el.remove());
|
svg.querySelectorAll('.sight-line').forEach(el => el.remove());
|
||||||
|
|
||||||
counter.setAttributeNS(null, 'cx', svgP.x);
|
counter.setAttributeNS(null, 'cx', cx);
|
||||||
counter.setAttributeNS(null, 'cy', svgP.y);
|
counter.setAttributeNS(null, 'cy', cy);
|
||||||
counter.setAttributeNS(null, 'r', '0.25in');
|
counter.setAttributeNS(null, 'r', '5');
|
||||||
counter.dataset.troopNumber = troopNumber;
|
counter.dataset.troopNumber = troopNumber;
|
||||||
counter.dataset.troopAllegiance = troopAllegiance;
|
counter.dataset.troopAllegiance = troopAllegiance;
|
||||||
counter.dataset.x = point.dataset.x;
|
counter.dataset.x = point.dataset.x;
|
||||||
counter.dataset.y = point.dataset.y;
|
counter.dataset.y = point.dataset.y;
|
||||||
counter.classList.add('counter');
|
counter.classList.add('counter');
|
||||||
|
|
||||||
text.setAttributeNS(null, 'x', svgP.x);
|
text.setAttributeNS(null, 'x', cx);
|
||||||
text.setAttributeNS(null, 'y', svgP.y);
|
text.setAttributeNS(null, 'y', cy);
|
||||||
text.dataset.troopNumber = troopNumber;
|
text.dataset.troopNumber = troopNumber;
|
||||||
text.dataset.troopAllegiance = troopAllegiance;
|
text.dataset.troopAllegiance = troopAllegiance;
|
||||||
text.textContent = troopNumber;
|
text.textContent = troopNumber;
|
||||||
@ -205,7 +204,7 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
|
|||||||
|
|
||||||
document.querySelectorAll(`.counter${selector}`).forEach(el => el.remove());
|
document.querySelectorAll(`.counter${selector}`).forEach(el => el.remove());
|
||||||
|
|
||||||
counter.addEventListener('click', e => {
|
counter.addEventListener('dblclick', e => {
|
||||||
let selectedSoldier = document.querySelector('.soldier-record.selected');
|
let selectedSoldier = document.querySelector('.soldier-record.selected');
|
||||||
|
|
||||||
if (selectedSoldier) {
|
if (selectedSoldier) {
|
||||||
@ -223,40 +222,50 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
counter.addEventListener('mouseenter', e => {
|
// counter.addEventListener('mouseenter', e => {
|
||||||
let selectedSoldier = document.querySelector('.soldier-record.selected');
|
// let selectedSoldier = document.querySelector('.soldier-record.selected');
|
||||||
|
|
||||||
if (selectedSoldier) {
|
// if (selectedSoldier) {
|
||||||
let {troopNumber, troopAllegiance} = selectedSoldier.dataset,
|
// let {troopNumber, troopAllegiance} = selectedSoldier.dataset,
|
||||||
selector = troopSelector(troopNumber, troopAllegiance),
|
// selector = troopSelector(troopNumber, troopAllegiance),
|
||||||
source = document.querySelector(`circle.counter${selector}`),
|
// source = document.querySelector(`circle.counter${selector}`),
|
||||||
|
|
||||||
// TODO: use isEqualNode() method instead
|
// // TODO: use isEqualNode() method instead
|
||||||
sourceAndTargetAreNotTheSame = [
|
// sourceAndTargetAreNotTheSame = [
|
||||||
troopNumber != e.target.dataset.troopNumber,
|
// troopNumber != e.target.dataset.troopNumber,
|
||||||
troopAllegiance != e.target.dataset.troopAllegiance
|
// troopAllegiance != e.target.dataset.troopAllegiance
|
||||||
].some(el => el);
|
// ].some(el => el);
|
||||||
|
|
||||||
if (source && sourceAndTargetAreNotTheSame) {
|
// if (source && sourceAndTargetAreNotTheSame) {
|
||||||
let sightLine = document.createElementNS(svgns, 'line');
|
// let sightLine = document.createElementNS(svgns, 'line');
|
||||||
|
|
||||||
sightLine.classList.add('sight-line');
|
// sightLine.classList.add('sight-line');
|
||||||
sightLine.setAttributeNS(null, 'x1', source.getAttribute('cx'));
|
// sightLine.setAttributeNS(null, 'x1', source.getAttribute('cx'));
|
||||||
sightLine.setAttributeNS(null, 'y1', source.getAttribute('cy'));
|
// sightLine.setAttributeNS(null, 'y1', source.getAttribute('cy'));
|
||||||
sightLine.setAttributeNS(null, 'x2', e.target.getAttribute('cx'));
|
// sightLine.setAttributeNS(null, 'x2', e.target.getAttribute('cx'));
|
||||||
sightLine.setAttributeNS(null, 'y2', e.target.getAttribute('cy'));
|
// sightLine.setAttributeNS(null, 'y2', e.target.getAttribute('cy'));
|
||||||
|
|
||||||
svg.appendChild(sightLine);
|
// svg.appendChild(sightLine);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
counter.addEventListener('mouseleave', e => {
|
// counter.addEventListener('mouseleave', e => {
|
||||||
document.querySelectorAll('.sight-line').forEach(el => el.remove());
|
// document.querySelectorAll('.sight-line').forEach(el => el.remove());
|
||||||
});
|
// });
|
||||||
|
|
||||||
svg.insertBefore(counter, ptGrp);
|
// svg.insertBefore(counter, ptGrp);
|
||||||
svg.insertBefore(text, ptGrp);
|
|
||||||
|
// let symbCtr = document.createElementNS(svgns, 'use');
|
||||||
|
|
||||||
|
// symbCtr.setAttributeNS(null, 'href', '#troop-counter');
|
||||||
|
// symbCtr.setAttributeNS(null, 'x', cx);
|
||||||
|
// symbCtr.setAttributeNS(null, 'y', cy);
|
||||||
|
|
||||||
|
// 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');
|
let sl = svg.querySelector('.sight-line');
|
||||||
|
|
||||||
if (counter && (!sl || sl.classList.contains('active'))) {
|
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 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 [x1, y1] = [source.x.baseVal.value, source.y.baseVal.value];
|
||||||
let [x2, y2] = [e.target.x.baseVal.value, e.target.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, 'x2', svgX2);
|
||||||
sightLine.setAttributeNS(null, 'y2', svgY2);
|
sightLine.setAttributeNS(null, 'y2', svgY2);
|
||||||
|
|
||||||
svg.insertBefore(sightLine, ptGrp);
|
// svg.insertBefore(sightLine, ptGrp);
|
||||||
|
document.getElementById('grid').appendChild(sightLine);
|
||||||
|
|
||||||
let coords = [
|
let coords = [
|
||||||
counter.dataset.x,
|
counter.dataset.x,
|
||||||
@ -309,16 +326,16 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
point.addEventListener('mouseout', e => {
|
// point.addEventListener('mouseout', e => {
|
||||||
let sl = svg.querySelector('.sight-line.active');
|
// let sl = svg.querySelector('.sight-line.active');
|
||||||
|
|
||||||
if (sl) {
|
// if (sl) {
|
||||||
info.querySelector('#hex-count').textContent = '-';
|
// info.querySelector('#hex-count').textContent = '-';
|
||||||
info.style.display = 'none';
|
// info.style.display = 'none';
|
||||||
ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
|
// ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
|
||||||
svg.querySelectorAll('.sight-line').forEach(el => el.remove());
|
// svg.querySelectorAll('.sight-line').forEach(el => el.remove());
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
point.addEventListener('click', e => {
|
point.addEventListener('click', e => {
|
||||||
let sl = svg.querySelector('.sight-line');
|
let sl = svg.querySelector('.sight-line');
|
||||||
@ -477,7 +494,7 @@ function linedraw(x1, y1, x2, y2) {
|
|||||||
for (let i = 0; i <= n; i++) {
|
for (let i = 0; i <= n; i++) {
|
||||||
let lerp = axial_lerp(axial1.q, axial1.r, axial2.q, axial2.r, 1.0 / 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),
|
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]);
|
results.push([x, y]);
|
||||||
}
|
}
|
||||||
@ -485,22 +502,22 @@ function linedraw(x1, y1, x2, y2) {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
map.addEventListener('mousemove', e => {
|
function positionFiringArc(e) {
|
||||||
let boundingRect = e.target.getBoundingClientRect();
|
activeFiringArc = document.querySelector('polygon.firing-arc.active');
|
||||||
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');
|
|
||||||
|
|
||||||
// TODO: handle exactly horizontal and vertical lines
|
// TODO: handle exactly horizontal and vertical lines
|
||||||
|
|
||||||
if (activeFiringArc) {
|
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] = [
|
let [x2px, y2px] = [
|
||||||
pointerX / boundingRect.width * maxXpx,
|
pointerX / width * maxXpx,
|
||||||
pointerY / boundingRect.height * maxYpx
|
pointerY / height * maxYpx
|
||||||
];
|
];
|
||||||
|
|
||||||
let xDiff = x2px - x1px;
|
let xDiff = x2px - x1px;
|
||||||
@ -595,7 +612,7 @@ map.addEventListener('mousemove', e => {
|
|||||||
|
|
||||||
activeFiringArc.setAttributeNS(null, 'points', points);
|
activeFiringArc.setAttributeNS(null, 'points', points);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
document.querySelectorAll('.soldier-record').forEach(el =>
|
document.querySelectorAll('.soldier-record').forEach(el =>
|
||||||
el.addEventListener('click', e => {
|
el.addEventListener('click', e => {
|
||||||
@ -639,15 +656,13 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener('
|
|||||||
if (counter) {
|
if (counter) {
|
||||||
let arcLayer = document.getElementById('firing-arcs');
|
let arcLayer = document.getElementById('firing-arcs');
|
||||||
|
|
||||||
let firingArcPlacementListener = e => {
|
let grid = document.getElementById('grid');
|
||||||
document.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active'));
|
const transform = getComputedStyle(grid).transform.match(/-?\d+\.?\d*/g);
|
||||||
document.querySelector('#point').style.display = '';
|
const pt = new DOMPoint(counter.cx.baseVal.value, counter.cy.baseVal.value);
|
||||||
map.removeEventListener('click', firingArcPlacementListener);
|
const mtx = new DOMMatrix(transform);
|
||||||
};
|
let tPt = pt.matrixTransform(mtx);
|
||||||
|
|
||||||
map.addEventListener('click', firingArcPlacementListener);
|
let pivotPoint = [tPt.x, tPt.y];
|
||||||
|
|
||||||
let pivotPoint = [counter.cx.baseVal.value, counter.cy.baseVal.value];
|
|
||||||
let firingArc = document.createElementNS(svgns, 'polygon');
|
let firingArc = document.createElementNS(svgns, 'polygon');
|
||||||
|
|
||||||
firingArc.classList.add('firing-arc', 'active');
|
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.dataset.size = e.target.dataset.size;
|
||||||
firingArc.setAttributeNS(null, 'points', `${pivotPoint} ${pivotPoint} ${pivotPoint}`);
|
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';
|
document.querySelector('#point').style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -674,30 +698,25 @@ document.querySelectorAll('.clear-firing-arcs').forEach(el =>
|
|||||||
svg.addEventListener('wheel', e => {
|
svg.addEventListener('wheel', e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// const pt = svg.createSVGPoint();
|
const pt = new DOMPoint(e.clientX, e.clientY),
|
||||||
const pt = new DOMPoint(e.clientX, e.clientY);
|
svgP = pt.matrixTransform(svg.getScreenCTM().inverse());
|
||||||
|
|
||||||
// pt.x = e.clientX;
|
let { x, y, width, height } = svg.viewBox.baseVal,
|
||||||
// pt.y = e.clientY;
|
|
||||||
|
|
||||||
const svgP = pt.matrixTransform(svg.getScreenCTM().inverse());
|
widthDelta = width * 0.25,
|
||||||
|
heightDelta = height * 0.25,
|
||||||
|
|
||||||
let { x, y, width, height } = svg.viewBox.baseVal;
|
xChange = (svgP.x - x) / width * widthDelta,
|
||||||
|
yChange = (svgP.y - y) / height * heightDelta,
|
||||||
|
|
||||||
let widthDelta = width * 0.25;
|
widthChange = (1 - ((svgP.x - x) / width)) * widthDelta,
|
||||||
let heightDelta = height * 0.25;
|
heightChange = (1 - ((svgP.y - y) / height)) * heightDelta,
|
||||||
|
|
||||||
let xChange = (svgP.x - x) / width * widthDelta;
|
newX = parseInt(e.deltaY < 0 ? x + xChange : x - xChange),
|
||||||
let yChange = (svgP.y - y) / height * heightDelta;
|
newWidth = parseInt(e.deltaY < 0 ? width - xChange - widthChange : width + xChange + widthChange),
|
||||||
|
|
||||||
let widthChange = (1 - ((svgP.x - x) / width)) * widthDelta;
|
newY = parseInt(e.deltaY < 0 ? y + yChange : y - yChange),
|
||||||
let heightChange = (1 - ((svgP.y - y) / height)) * heightDelta;
|
newHeight = parseInt(e.deltaY < 0 ? height - yChange - heightChange : height + yChange + heightChange);
|
||||||
|
|
||||||
let newX = parseInt(e.deltaY < 0 ? x + xChange : x - xChange);
|
|
||||||
let 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);
|
|
||||||
|
|
||||||
// console.log('VIEWBOX_X', 'VIEWBOX_Y', VIEWBOX_X, VIEWBOX_Y);
|
// console.log('VIEWBOX_X', 'VIEWBOX_Y', VIEWBOX_X, VIEWBOX_Y);
|
||||||
// console.log('VIEWBOX_WIDTH', 'VIEWBOX_HEIGHT', VIEWBOX_WIDTH, VIEWBOX_HEIGHT);
|
// console.log('VIEWBOX_WIDTH', 'VIEWBOX_HEIGHT', VIEWBOX_WIDTH, VIEWBOX_HEIGHT);
|
||||||
@ -727,6 +746,17 @@ svg.addEventListener('wheel', e => {
|
|||||||
svg.setAttributeNS(null, 'viewBox', vb);
|
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 => {
|
svg.addEventListener('pointerdown', e => {
|
||||||
const minPanDistanceThreshold = 5;
|
const minPanDistanceThreshold = 5;
|
||||||
|
|
||||||
@ -772,6 +802,30 @@ svg.addEventListener('pointerdown', e => {
|
|||||||
svg.addEventListener('pointerup', pointerUp);
|
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 => {
|
recordSheetVisibility.addEventListener('input', e => {
|
||||||
localStorage.setItem('recordsVisibility', recordSheetVisibility.checked);
|
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');
|
||||||
|
}
|
||||||
|
});
|
84
style.css
84
style.css
@ -16,18 +16,22 @@ svg {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg text {
|
svg image#numbers {
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* svg text {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
font-size: 4px;
|
font-size: 4px;
|
||||||
fill: black;
|
fill: black;
|
||||||
/* stroke: black; */
|
stroke: black;
|
||||||
stroke-width: 0.2px;
|
stroke-width: 0.2px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
transform: translateY(6px);
|
transform: translateY(6px);
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
text-anchor: middle;
|
text-anchor: middle;
|
||||||
/* display: none; */
|
display: none;
|
||||||
}
|
} */
|
||||||
|
|
||||||
div#status {
|
div#status {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -65,6 +69,10 @@ div#content {
|
|||||||
border-bottom: 1px solid gray;
|
border-bottom: 1px solid gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#content #buttons {
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
#content > div {
|
#content > div {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -121,25 +129,31 @@ div#content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
svg > defs > #point {
|
svg > defs > #point {
|
||||||
|
fill: inherit;
|
||||||
|
fill-opacity: inherit;
|
||||||
|
stroke: inherit;
|
||||||
|
stroke-width: inherit;
|
||||||
|
stroke-opacity: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
use[href="#point"] {
|
||||||
|
opacity: 0;
|
||||||
fill: teal;
|
fill: teal;
|
||||||
fill-opacity: 0.2;
|
fill-opacity: 0.2;
|
||||||
stroke: black;
|
stroke: black;
|
||||||
stroke-width: 0.5px;
|
stroke-width: 0.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
use[href="#point"] {
|
use[href="#point"]:hover, use[href="#point"].hover {
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
use[href="#point"]:hover {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
fill: orange;
|
||||||
}
|
}
|
||||||
|
|
||||||
use[href="#point"].active {
|
use[href="#point"].active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
g#points {
|
g#grid {
|
||||||
transform: translate(19px, 31px) scale(4);
|
transform: translate(19px, 31px) scale(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,10 +188,10 @@ image.map-scans {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
circle.counter {
|
/* circle.counter {
|
||||||
stroke: transparent;
|
stroke: transparent;
|
||||||
stroke-width: 0.5in;
|
stroke-width: 0.5in;
|
||||||
}
|
} */
|
||||||
|
|
||||||
circle.counter[data-troop-allegiance="liao"] {
|
circle.counter[data-troop-allegiance="liao"] {
|
||||||
fill: green;
|
fill: green;
|
||||||
@ -187,15 +201,19 @@ circle.counter[data-troop-allegiance="davion"] {
|
|||||||
fill: red;
|
fill: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
text.counter {
|
text.counter, #troop-counter text {
|
||||||
font-size: 80px;
|
font-size: 12px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
stroke: black;
|
/* stroke: black; */
|
||||||
fill: white;
|
fill: white;
|
||||||
stroke-width: 2px;
|
/* stroke-width: 0.5px; */
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
text-anchor: middle;
|
||||||
|
/* transform: translateY(25%); */
|
||||||
|
transform: translateY(4px);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
rect#map {
|
rect#map {
|
||||||
@ -226,7 +244,8 @@ line.firing-arc {
|
|||||||
|
|
||||||
.sight-line {
|
.sight-line {
|
||||||
stroke: orangered;
|
stroke: orangered;
|
||||||
stroke-width: 3px;
|
stroke-width: 0.5px;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.soldier-record {
|
.soldier-record {
|
||||||
@ -236,6 +255,15 @@ line.firing-arc {
|
|||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.soldier-record.selected {
|
||||||
|
background-color: khaki;
|
||||||
|
}
|
||||||
|
|
||||||
|
.soldier-record.movement-ended {
|
||||||
|
background-color: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
image#img1 {
|
image#img1 {
|
||||||
transform: scale(3.41) rotate(-0.15deg);
|
transform: scale(3.41) rotate(-0.15deg);
|
||||||
/* opacity: 0.33; */
|
/* opacity: 0.33; */
|
||||||
@ -258,10 +286,6 @@ img.logo {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.soldier-record.selected {
|
|
||||||
background-color: khaki;
|
|
||||||
}
|
|
||||||
|
|
||||||
rect#debug-view-box {
|
rect#debug-view-box {
|
||||||
/* stroke: red;
|
/* stroke: red;
|
||||||
stroke-width: 20px; */
|
stroke-width: 20px; */
|
||||||
@ -269,6 +293,24 @@ rect#debug-view-box {
|
|||||||
fill-opacity: 0.2;
|
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) {
|
@media (width >= 1800px) {
|
||||||
#record-sheet {
|
#record-sheet {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user