Web Dev Solutions

Catalin Mititiuc

aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCatalin Mititiuc <webdevcat@proton.me>2024-07-30 21:02:13 -0700
committerCatalin Mititiuc <webdevcat@proton.me>2024-07-30 21:08:00 -0700
commit1687e0e790d869fe58f86046f5ee093981670c63 (patch)
tree212e0c3127483ec29774ac237c07e00b26f05086
parent48e7675eb0583e420dac52be341e505331c05b4b (diff)
Ok, hover and firing arc doesn't get stuck at all
Not sure about counters
-rw-r--r--public/assets/css/map.css7
-rw-r--r--public/assets/images/scenario_template.svg6
-rw-r--r--src/modules/gameboard.js260
-rw-r--r--src/modules/scenario.js3
-rw-r--r--src/radial.js9
5 files changed, 200 insertions, 85 deletions
diff --git a/public/assets/css/map.css b/public/assets/css/map.css
index feda870..9c0c189 100644
--- a/public/assets/css/map.css
+++ b/public/assets/css/map.css
@@ -184,7 +184,6 @@ g.counter.selected {
g.counter use.primary-weapon {
r: inherit;
- pointer-events: none;
}
g.counter use.troop-number, g.counter use.squad-number {
@@ -480,7 +479,7 @@ text.elevation {
fill: black;
}
-.grid-top:hover use[href="#hex"] {
+[data-q][data-r][data-s][data-t].hover use[href="#hex"] {
opacity: 1;
fill: orange;
stroke: black;
@@ -502,12 +501,12 @@ g.counter use[class^="counter-"] {
--translateY: calc(var(--y) / 6 - 5px);
}
-.grid-top .container > g.counter ~ use[class^="counter-"] {
+.frontmost > g.counter ~ use[class^="counter-"] {
--translateX: calc(var(--x) * 2 - 5px);
--translateY: calc(var(--y) * 2 - 5px);
}
-.grid-top .container > use[class^="counter-"] {
+.frontmost > use[class^="counter-"] {
--translateX: calc(var(--x) * 1.5 - 5px);
--translateY: calc(var(--y) * 1.5 - 5px);
}
diff --git a/public/assets/images/scenario_template.svg b/public/assets/images/scenario_template.svg
index bc5b146..6e4ac14 100644
--- a/public/assets/images/scenario_template.svg
+++ b/public/assets/images/scenario_template.svg
@@ -70,10 +70,8 @@
<g id="lines"/>
</g>
- <g class="grid"/>
- <g class="grid-top">
- <use href="#hex"/>
- <g class="container"/>
+ <g class="grid">
+ <g class="frontmost"/>
</g>
</g>
</svg>
diff --git a/src/modules/gameboard.js b/src/modules/gameboard.js
index 02b9c0f..3f02784 100644
--- a/src/modules/gameboard.js
+++ b/src/modules/gameboard.js
@@ -10,6 +10,8 @@ const top = {
collection: new Map()
};
+const frontmostStore = new Map();
+
function getCellContents(cell) {
return cell.querySelectorAll('*:not(use[href="#hex"])');
}
@@ -215,46 +217,142 @@ function workaroundForWebKitBug233432(listener) {
export function start(el) {
svg = el;
- const gridTop = svg.querySelector('.grid-top');
- top.container = svg.querySelector('.grid-top > .container');
- const topHex = svg.querySelector('.grid-top > use[href="#hex"]');
+ //const gridTop = svg.querySelector('.grid-top');
+ //top.container = svg.querySelector('.grid-top > .container');
+ //const topHex = svg.querySelector('.grid-top > use[href="#hex"]');
+
+ const grid = svg.querySelector('.grid');
+ const frontmost = grid.querySelector('.frontmost');
+
+ svg.addEventListener('pointerover', e => {
+ //console.log('pointerover', e.target.closest('[data-q][data-r][data-s][data-t], .frontmost'), e);
+ const targetCell = e.target.closest('[data-q][data-r][data-s][data-t]');
+ console.log('SVG pointerover', targetCell);
+ const counter = targetCell && targetCell.querySelector('.counter');
+ //console.log('pointerover', 'targetCell', targetCell);
+
+ if (counter) {
+ firingArc.toggleCounterVisibility(svg, counter, true);
+ frontmost.setAttributeNS(null, 'transform', targetCell.getAttributeNS(null, 'transform'));
+ frontmostStore.set(counter, targetCell);
+ frontmost.append(counter);
+ }
- const clearHexDialog = document.querySelector('#clear-hex');
- clearHexDialog.addEventListener('close', e => {
- if (clearHexDialog.returnValue === 'confirm') {
- [...top.container.children].forEach(child => {
- top.collection.delete(child);
- child.remove();
+ targetCell && targetCell.classList.add('hover');
+
+ //if (targetCell && !targetCell.classList.contains('frontmost')) {
+ // targetCell.classList.add('hover');
+ // const occupant = targetCell.querySelector('.counter');
+ //
+ // if (occupant) {
+ // firingArc.toggleCounterVisibility(svg, occupant, true);
+ // }
+ // const children = [...targetCell.children].filter(c => c.getAttributeNS(null, 'href') !== '#hex');
+ // if (children.length > 0) {
+ // frontmost.setAttributeNS(null, 'transform', targetCell.getAttributeNS(null, 'transform'));
+ // children.forEach(child => {
+ // frontmostStore.set(child, targetCell);
+ // frontmost.append(child);
+ // });
+ // }
+ //}
+ //console.log('frontmost contents', frontmost.children);
+ });
+
+ svg.addEventListener('pointerout', e => {
+ //const targetCell = e.target.closest('[data-q][data-r][data-s][data-t], .frontmost');
+ console.log('pointer out target', e.target);
+ const targetCell = e.target.closest('[data-q][data-r][data-s][data-t], .frontmost');
+
+ if (targetCell) {
+ console.log('SVG pointerout', targetCell);
+ [...frontmost.children].forEach(child => {
+ //console.log('child', child, 'relatedTarget', e.relatedTarget);
+ //if ([
+ // !e.relatedTarget, // out of the window
+ // targetCell.classList.contains('frontmost') && !e.relatedTarget.closest('.frontmost'), // from one element in frontmost to another element in frontmost
+ // !targetCell.classList.contains('frontmost') && frontmostStore.get(child) === targetCell, // leaving from a hex under frontmost
+ //].some(e => e)) {
+ console.log('child', child, 'belongs to', frontmostStore.get(child));
+ console.log('relatedTarget', e.relatedTarget);
+ if (!e.relatedTarget || frontmostStore.get(child) !== targetCell || (e.relatedTarget !== child && !child.contains(e.relatedTarget))) {
+ //if (!e.relatedTarget || frontmostStore.get(child) !== targetCell || e.relatedTarget !== child) {
+ const parent = frontmostStore.get(child);
+ console.log('returning to', parent);
+ //console.log('RETURNING to', parent);
+ parent.append(child);
+
+ //if (child.classList.contains('.counter')) {
+ // firingArc.toggleCounterVisibility(svg, child, false);
+ //}
+
+ firingArc.toggleCounterVisibility(svg, child, false);
+ parent.classList.remove('hover');
+ frontmostStore.delete(child);
+ }
+ });
+ //targetCell.classList.remove('hover');
+ if (frontmost.children.length < 1) targetCell.classList.remove('hover');
+ } else {
+ [...frontmost.children].forEach(child => {
+ const parent = frontmostStore.get(child);
+ parent.append(child);
+ parent.classList.remove('hover');
+ frontmostStore.delete(child);
});
}
+ //console.log('frontmost contents', frontmost.children);
});
- clearHexDialog.querySelector('button[value="confirm"]').addEventListener('click', function(e) {
- e.preventDefault();
- clearHexDialog.close(this.value);
+ grid.addEventListener('click', e => {
+ console.log('click', e.target);
});
- gridTop.addEventListener('pointerleave', workaroundForWebKitBug233432(e => {
- [...top.container.children].forEach(child => {
- top.collection.get(child).parent.append(child);
- top.collection.delete(child);
- });
-
- top.cell = null;
- }));
-
- topHex.addEventListener('click', clickHandler);
-
- topHex.addEventListener('contextmenu', e => {
- e.preventDefault();
- getSelected() ? sightLine.toggleLock(top.cell) : clearHexDialog.showModal();
- });
+ const clearHexDialog = document.querySelector('#clear-hex');
+ //clearHexDialog.addEventListener('close', e => {
+ // if (clearHexDialog.returnValue === 'confirm') {
+ // [...top.container.children].forEach(child => {
+ // top.collection.delete(child);
+ // child.remove();
+ // });
+ // }
+ //});
+
+ //clearHexDialog.querySelector('button[value="confirm"]').addEventListener('click', function(e) {
+ // e.preventDefault();
+ // clearHexDialog.close(this.value);
+ //});
+
+ //gridTop.addEventListener('pointerleave', workaroundForWebKitBug233432(e => {
+ // console.log('pointerleave top', performance.now(), top.cell);
+ // const occupant = svg.querySelector('.grid-top .container .counter');
+ //
+ // if (occupant) {
+ // firingArc.toggleCounterVisibility(svg, occupant, false);
+ // }
+ //
+ // [...top.container.children].forEach(child => {
+ // top.collection.get(child).parent.append(child);
+ // top.collection.delete(child);
+ // });
+ //
+ // top.cell = null;
+ //
+ // getActiveSightLine(svg) && clearSightLine();
+ //}));
+
+ //topHex.addEventListener('click', clickHandler);
+ //
+ //topHex.addEventListener('contextmenu', e => {
+ // e.preventDefault();
+ // getSelected() ? sightLine.toggleLock(top.cell) : clearHexDialog.showModal();
+ //});
const startingLocations = svg.querySelector('.start-locations');
startingLocations && getUnits(startingLocations).forEach(unit => unit.addEventListener('click', selectOffBoard));
function clickHandler(e) {
- const occupant = svg.querySelector('.grid-top .container .counter')
+ const occupant = svg.querySelector('.grid-top .container .counter');
let toPlace = placing.pop();
if (isCounter(toPlace) || isMechTemplate(toPlace)) {
@@ -280,43 +378,47 @@ export function start(el) {
const selected = getSelected();
}
- getCells(svg).forEach(cell => {
- cell.addEventListener('pointerover', () => {
- //console.log(['pointerenter', cell]);
-
- top.cell = cell;
-
- [...top.container.children].forEach(child => {
- top.collection.get(child).parent.append(child);
- top.collection.delete(child);
- });
-
- top.container.parentElement.setAttributeNS(null, 'transform', cell.getAttributeNS(null, 'transform'));
-
- [...cell.children].filter(c => c.getAttributeNS(null, 'href') !== '#hex').forEach(child => {
- top.collection.set(child, { parent: cell });
- top.container.append(child);
- });
-
- let occupant = svg.querySelector('.grid-top .container .counter');
- const selected = getSelected();
-
- if (placing[0]?.getAttributeNS(null, 'class') == 'mech-template') {
- cell.appendChild(placing[0]);
- }
-
- if (selected && svg.querySelector('.grid').contains(selected) && !getLockedSightLine(svg) && cell !== selected.parentElement) {
- clearSightLine();
- drawSightLine(selected.parentElement, cell);
- }
-
- occupant = getCellOccupant(cell);
-
- if (occupant) {
- firingArc.toggleCounterVisibility(svg, occupant, true);
- }
- });
- });
+ //getCells(svg).forEach(cell => {
+ // cell.addEventListener('pointerleave', () => {
+ // console.log('pointerleave cell', performance.now(), cell);
+ // });
+ //
+ // cell.addEventListener('pointerover', () => {
+ // console.log('pointerenter', performance.now(), cell);
+ //
+ // top.cell = cell;
+ //
+ // [...top.container.children].forEach(child => {
+ // top.collection.get(child).parent.append(child);
+ // top.collection.delete(child);
+ // });
+ //
+ // top.container.parentElement.setAttributeNS(null, 'transform', cell.getAttributeNS(null, 'transform'));
+ //
+ // [...cell.children].filter(c => c.getAttributeNS(null, 'href') !== '#hex').forEach(child => {
+ // top.collection.set(child, { parent: cell });
+ // top.container.append(child);
+ // });
+ //
+ // let occupant = svg.querySelector('.grid-top .container .counter');
+ // const selected = getSelected();
+ //
+ // if (placing[0]?.getAttributeNS(null, 'class') == 'mech-template') {
+ // cell.appendChild(placing[0]);
+ // }
+ //
+ // if (selected && svg.querySelector('.grid').contains(selected) && !getLockedSightLine(svg) && cell !== selected.parentElement) {
+ // clearSightLine();
+ // drawSightLine(selected.parentElement, cell);
+ // }
+ //
+ // occupant = getCellOccupant(cell);
+ //
+ // if (occupant) {
+ // firingArc.toggleCounterVisibility(svg, occupant, true);
+ // }
+ // });
+ //});
//const cell = document.querySelector('[data-q="0"][data-r="0"][data-s="0"][data-t="0"]');
//const povr = new PointerEvent('pointerover');
@@ -326,17 +428,29 @@ export function start(el) {
// debug //
// Add a trooper counter
- //const attacker = { dataset: { allegiance: 'attacker', number: 1, squad: 1 }};
// const defender = { dataset: { allegiance: 'defender', number: 1, squad: 2 }};
- //const cell = getCell(0, 0, 0, 0);
- //const trooper = soldier.createCounter(attacker, 'blazer');
- //const trooperSack = document.createElementNS(svgns, 'g');
- //trooperSack.classList.add('cell-contents');
- //trooperSack.append(trooper);
- //soldier.place(svg, trooper, cell);
+
+ const cell = getCell(0, 0, 0, 0);
+ const attacker = { dataset: { allegiance: 'attacker', number: 1, squad: 1 }};
+ const trooper = soldier.createCounter(attacker, 'blazer');
+ soldier.place(svg, trooper, cell);
// Add some counters in an unoccupied cell
//const countersCell = getCell(-1, 1, 0, 0);
+ const counter = document.createElementNS(svgns, 'use');
+ const name = 'grenade';
+ //counter.addEventListener('click', e => {
+ // e.stopPropagation()
+ // const container = counter.parentElement;
+ // counter.remove()
+ // arrangeCounters(container);
+ //});
+
+ //counter.setAttributeNS(null, 'href', `#counter-${name}`);
+ //counter.classList.add(`counter-${name}`);
+ //cell.append(counter);
+ //arrangeCounters(cell)
+
//setCounter('grenade');
//setCounter('prone');
//setCounter('1st-floor');
@@ -374,7 +488,7 @@ export function setFiringArc() {
isOnBoard = counter => counter && counter.parentElement.hasAttribute('data-q');
if (isOnBoard(counter)) {
- returnToParent(top);
+ //returnToParent(top);
firingArc.set(svg, this.dataset.size, counter, getCellPosition(counter.parentElement));
}
}
diff --git a/src/modules/scenario.js b/src/modules/scenario.js
index 805d0fe..4f72168 100644
--- a/src/modules/scenario.js
+++ b/src/modules/scenario.js
@@ -97,7 +97,8 @@ export async function build(svg, request) {
const scenarioBuildings = scenario.querySelector('.gameboard .buildings');
if (scenarioGrid) {
- grid.replaceWith(svg.ownerDocument.importNode(scenarioGrid, true));
+ const frontmost = grid.querySelector('.frontmost');
+ [...scenarioGrid.children].forEach(child => frontmost.before(svg.ownerDocument.importNode(child, true)));
}
if (scenarioBuildings)
diff --git a/src/radial.js b/src/radial.js
index 09037ab..7c7c0f3 100644
--- a/src/radial.js
+++ b/src/radial.js
@@ -1,5 +1,6 @@
const xmlns = 'http://www.w3.org/2000/svg';
const grid = document.querySelector('svg .grid');
+const frontmost = grid.querySelector('.frontmost');
const hex = {
inradius: 8.66,
@@ -247,10 +248,10 @@ function drawBuildings(buildings, container, { q: pq, r: pr, s: ps }, features)
}, new Map());
}
-function drawMapsheet(gameboard, mapsheet, position) {
+function drawMapsheet(placementMarker, mapsheet, position) {
const container = document.createElementNS(xmlns, 'g');
container.classList.add(mapsheet.id);
- gameboard.appendChild(container);
+ placementMarker.before(container);
const buildingContainer = document.createElementNS(xmlns, 'g');
buildingContainer.classList.add(mapsheet.id);
@@ -440,11 +441,13 @@ findScalar(findMult(sheets), +width + 1, +height).forEach(([vscalar, row]) => {
return vectorAdd(coords, { q: -1, r: 0, s: 1 }, hscalar);
}
- ms = drawMapsheet(grid, ms, horzMapVect(vertMapVect({ q: 0, r: 0, s: 0 })));
+ ms = drawMapsheet(frontmost, ms, horzMapVect(vertMapVect({ q: 0, r: 0, s: 0 })));
finalGrid = new Map([...finalGrid, ...ms]);
})
});
+document.querySelector('.grid .mapsheets').remove();
+
function addGroup(container, className) {
const g = document.createElementNS(xmlns, 'g');
g.classList.add(className);