Web Dev Solutions

Catalin Mititiuc

aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCatalin Mititiuc <webdevcat@proton.me>2024-04-24 19:35:42 -0700
committerCatalin Mititiuc <webdevcat@proton.me>2024-04-24 19:35:42 -0700
commit7f0c19becd5979a16d9298cae9f6ff8a6f96d9c2 (patch)
tree063c3737b276d4117edf4ee17b255b8d84a87a80
parente7f7bf1f31a7e1f937eb3eda4ee735db04e6384e (diff)
More functional refactor
-rw-r--r--src/index.js2
-rw-r--r--src/modules/game.js8
-rw-r--r--src/modules/game/counter.js (renamed from src/modules/counter.js)0
-rw-r--r--src/modules/game/firingArc.js (renamed from src/modules/firingArc.js)140
-rw-r--r--src/modules/game/sightLine.js (renamed from src/modules/sightLine.js)0
-rw-r--r--src/modules/panzoom.js51
6 files changed, 101 insertions, 100 deletions
diff --git a/src/index.js b/src/index.js
index d6204e8..0a75486 100644
--- a/src/index.js
+++ b/src/index.js
@@ -46,7 +46,7 @@ window.addEventListener('load', () => {
const svgns = "http://www.w3.org/2000/svg",
recordSheetVisibility = document.querySelector('#content input[type="checkbox"].visible');
- new PanZoom(svg);
+ PanZoom(svg);
const distanceOutput = document.getElementById('status');
diff --git a/src/modules/game.js b/src/modules/game.js
index f9ce991..c22dc9d 100644
--- a/src/modules/game.js
+++ b/src/modules/game.js
@@ -1,6 +1,6 @@
-import FiringArc from './firingArc.js';
-import SightLine from './sightLine.js';
-import Counter from './counter.js';
+import firingArc from './game/firingArc.js';
+import SightLine from './game/sightLine.js';
+import Counter from './game/counter.js';
const svgns = "http://www.w3.org/2000/svg";
@@ -10,7 +10,7 @@ export default class Game {
constructor(svg) {
this.svg = svg;
- this.firingArc = new FiringArc(svg);
+ this.firingArc = new firingArc(svg);
this.sightLine = new SightLine(svg);
this.counter = new Counter(svg);
diff --git a/src/modules/counter.js b/src/modules/game/counter.js
index 69552d8..69552d8 100644
--- a/src/modules/counter.js
+++ b/src/modules/game/counter.js
diff --git a/src/modules/firingArc.js b/src/modules/game/firingArc.js
index 5e5d84a..d2f18a5 100644
--- a/src/modules/firingArc.js
+++ b/src/modules/game/firingArc.js
@@ -1,11 +1,25 @@
-const HORZ_POINT_DISTANCE = 1.005,
- VERT_POINT_DISTANCE = Math.sqrt(3) * HORZ_POINT_DISTANCE / 2,
+// https://www.redblobgames.com/grids/hexagons/
- FIRING_ARC_SIZE = {
- 'small': Math.atan(HORZ_POINT_DISTANCE / (6 * VERT_POINT_DISTANCE)),
- 'medium': Math.atan((HORZ_POINT_DISTANCE / 2) / VERT_POINT_DISTANCE),
- 'large': Math.atan((21 * HORZ_POINT_DISTANCE) / (6 * VERT_POINT_DISTANCE))
-};
+// Horizontal distance between hex centers is sqrt(3) * size. The vertical
+// distance is 3 / 2 * size. When we calculate horzDist / vertDist, the size
+// cancels out, leaving us with a unitless ratio of sqrt(3) / (3 / 2), or
+// 2 * sqrt(3) / 3.
+
+const svgns = "http://www.w3.org/2000/svg",
+ horzToVertDistRatio = 2 * Math.sqrt(3) / 3,
+
+ arcSize = {
+ 'small': Math.atan(horzToVertDistRatio / 6),
+ 'medium': Math.atan(horzToVertDistRatio / 2),
+ 'large': Math.atan(7 * horzToVertDistRatio / 2)
+ },
+
+ firingArcVisibility = {
+ davion: false,
+ liao: false
+ };
+
+let svg;
function calculateAngle(xDiff, yDiff) {
yDiff = -yDiff;
@@ -73,7 +87,7 @@ function position(e) {
let yDiff = y2px - y1px;
let angle = calculateAngle(xDiff, yDiff);
- let arcAngle = FIRING_ARC_SIZE[activeFiringArc.dataset.size];
+ let arcAngle = arcSize[activeFiringArc.dataset.size];
let distance = Math.sqrt((x2px - x1px) ** 2 + (y2px - y1px) ** 2);
let yDelta = distance * Math.cos(angle) * Math.tan(arcAngle);
let xDelta = distance * Math.sin(angle) * Math.tan(arcAngle);
@@ -164,30 +178,30 @@ function position(e) {
}
}
-export default class FiringArc {
- #firingArcVisibility = {
- davion: false,
- liao: false
- };
+function setDataAttrs({ dataset: { allegiance, number }}, el) {
+ el.dataset.allegiance = allegiance;
+ el.dataset.number = number;
+}
- constructor(svg) {
- this.svg = svg;
- }
+function getClipPathId({ dataset: { allegiance, number }}) {
+ return `clip-path-${allegiance}-${number}`;
+}
- set(size, { dataset: { allegiance, number }}, { x, y }) {
- const svgns = "http://www.w3.org/2000/svg";
+function getUnclipped() {
+ return svg.querySelectorAll('#firing-arcs polygon:not([clip-path])');
+};
- let existingArcs = this.svg.querySelectorAll(
- `#firing-arcs [data-number="${number}"][data-allegiance="${allegiance}"]`
- );
+export default function (el) {
+ svg = el;
- existingArcs.forEach(el => el.remove());
+ this.set = function (size, counter, { x, y }) {
+ this.get(counter).forEach(fa => fa.remove());
- let arcLayer = this.svg.querySelector('#shapes');
- let outlineLayer = this.svg.querySelector('#lines');
- let arcContainer = this.svg.querySelector('#firing-arcs');
+ let arcLayer = svg.querySelector('#shapes');
+ let outlineLayer = svg.querySelector('#lines');
+ let arcContainer = svg.querySelector('#firing-arcs');
- let grid = this.svg.querySelector('.board');
+ let grid = svg.querySelector('.board');
const transform = getComputedStyle(grid).transform.match(/-?\d+\.?\d*/g);
const pt = new DOMPoint(x, y);
const mtx = new DOMMatrix(transform);
@@ -197,14 +211,12 @@ export default class FiringArc {
let firingArc = document.createElementNS(svgns, 'polygon');
let firingArcOutline = document.createElementNS(svgns, 'polygon');
- firingArc.classList.add('firing-arc', 'active');
- firingArc.dataset.number = number;
- firingArc.dataset.allegiance = allegiance;
+ setDataAttrs(counter, firingArc);
firingArc.dataset.size = size;
+ firingArc.classList.add('firing-arc', 'active');
firingArc.setAttributeNS(null, 'points', `${pivotPoint} ${pivotPoint} ${pivotPoint}`);
- firingArcOutline.dataset.number = number;
- firingArcOutline.dataset.allegiance = allegiance;
+ setDataAttrs(counter, firingArcOutline);
firingArcOutline.setAttributeNS(null, 'points', `${pivotPoint} ${pivotPoint} ${pivotPoint}`);
let clipShape = document.createElementNS(svgns, 'circle');
@@ -213,9 +225,8 @@ export default class FiringArc {
clipShape.setAttributeNS(null, 'r', 100);
let clipPath = document.createElementNS(svgns, 'clipPath');
- clipPath.setAttributeNS(null, 'id', `clip-path-${allegiance}-${number}`);
- clipPath.dataset.number = number;
- clipPath.dataset.allegiance = allegiance;
+ setDataAttrs(counter, clipPath);
+ clipPath.setAttributeNS(null, 'id', getClipPathId(counter));
clipPath.appendChild(clipShape);
arcContainer.appendChild(clipPath);
@@ -223,9 +234,9 @@ export default class FiringArc {
outlineLayer.appendChild(firingArcOutline);
let firingArcPlacementListener = e => {
- this.svg.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active'));
+ svg.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active'));
grid.removeAttribute('style');
- this.svg.removeEventListener('mousemove', position);
+ svg.removeEventListener('mousemove', position);
firingArc.removeEventListener('click', firingArcPlacementListener);
firingArc.removeEventListener('contextmenu', cancelFiringArcPlacement);
};
@@ -236,65 +247,58 @@ export default class FiringArc {
firingArc.removeEventListener('click', firingArcPlacementListener);
firingArc.removeEventListener('contextmenu', cancelFiringArcPlacement);
- let existingArcs = this.svg.querySelectorAll(
- `#firing-arcs [data-number="${number}"][data-allegiance="${allegiance}"]`
- );
-
- existingArcs.forEach(el => el.remove());
+ this.get(counter).forEach(fa => fa.remove());
grid.removeAttribute('style');
- this.svg.removeEventListener('mousemove', position);
+ svg.removeEventListener('mousemove', position);
};
grid.style.pointerEvents = 'none';
- this.svg.addEventListener('mousemove', position);
+ svg.addEventListener('mousemove', position);
firingArc.addEventListener('click', firingArcPlacementListener);
firingArc.addEventListener('contextmenu', cancelFiringArcPlacement);
- }
+ };
- clear(allegiance) {
+ this.clear = function (allegiance) {
const selector = `#firing-arcs [data-allegiance="${allegiance}"]`;
- this.svg.querySelectorAll(selector).forEach(el => el.remove());
- }
-
- get({ dataset: { allegiance, number }}) {
- return this.svg.querySelectorAll(`#firing-arcs polygon[data-number="${number}"][data-allegiance="${allegiance}"]`);
- }
+ svg.querySelectorAll(selector).forEach(el => el.remove());
+ };
- getUnclipped() {
- return this.svg.querySelectorAll('#firing-arcs polygon:not([clip-path])');
- }
+ this.get = function ({ dataset: { allegiance, number }}) {
+ return svg.querySelectorAll(`#firing-arcs polygon[data-number="${number}"][data-allegiance="${allegiance}"]`);
+ };
- toggleVisibility(allegiance) {
- const vis = this.#firingArcVisibility[allegiance],
- clipPaths = this.svg.querySelectorAll(`clipPath[data-allegiance="${allegiance}"]`);
+ this.toggleVisibility = function (allegiance) {
+ const vis = firingArcVisibility[allegiance],
+ clipPaths = svg.querySelectorAll(`clipPath[data-allegiance="${allegiance}"]`);
clipPaths.forEach(cp => cp.style.display = !vis ? 'none' : '');
- this.#firingArcVisibility[allegiance] = !vis;
- }
+ firingArcVisibility[allegiance] = !vis;
+ };
- toggleCounterVisibility({ dataset: { number, allegiance }}, vis) {
- const cp = this.svg.querySelector(`#clip-path-${allegiance}-${number}`),
+ this.toggleCounterVisibility = function ({ dataset: { number, allegiance }}, vis) {
+ const cp = svg.querySelector(`#clip-path-${allegiance}-${number}`),
display = vis ? 'none' : '';
if (cp) {
- cp.style.display = this.#firingArcVisibility[allegiance] ? 'none' : display;
+ cp.style.display = firingArcVisibility[allegiance] ? 'none' : display;
}
- }
+ };
- clipAll() {
- let unclipped = this.getUnclipped();
+ this.clipAll = function () {
+ console.log('clipall')
+ let unclipped = getUnclipped();
unclipped.forEach(el => {
const { number, allegiance } = el.dataset,
clipPathId = `clip-path-${allegiance}-${number}`,
- isVisible = this.#firingArcVisibility[allegiance];
+ isVisible = firingArcVisibility[allegiance];
if (isVisible) {
- this.svg.querySelector(`#${clipPathId}`).style.display = 'none';
+ svg.querySelector(`#${clipPathId}`).style.display = 'none';
}
el.setAttributeNS(null, 'clip-path', `url(#${clipPathId})`);
});
- }
+ };
}
diff --git a/src/modules/sightLine.js b/src/modules/game/sightLine.js
index 4790bd8..4790bd8 100644
--- a/src/modules/sightLine.js
+++ b/src/modules/game/sightLine.js
diff --git a/src/modules/panzoom.js b/src/modules/panzoom.js
index ae95171..dcc6b34 100644
--- a/src/modules/panzoom.js
+++ b/src/modules/panzoom.js
@@ -1,36 +1,33 @@
import { pan, zoom } from 'pan-zoom';
-export default class PanZoom {
- #storageKey = 'pan-zoom';
- #zoomFactor = 0.25;
-
- constructor(svg) {
- this.#restorePanZoomVal(svg);
- this.#addEventListeners(svg);
- this.#observePanZoomChanges(svg);
- }
+const storageKey = 'pan-zoom',
+ zoomFactor = 0.25;
+
+function restorePanZoomVal(svg) {
+ const storedPanZoomVal = localStorage.getItem(storageKey);
- #storePanZoomVal(transformMatrix) {
- localStorage.setItem(this.#storageKey, transformMatrix);
+ if (storedPanZoomVal) {
+ svg.style.transform = storedPanZoomVal;
}
+}
- #observePanZoomChanges(svg) {
- const observer =
- new MutationObserver(() => this.#storePanZoomVal(svg.style.transform));
+function addEventListeners(svg) {
+ svg.addEventListener('wheel', e => zoom(svg, e, zoomFactor), { passive: false });
+ svg.addEventListener('pointerdown', e => pan(svg, e), { passive: false });
+}
- observer.observe(svg, { attributeFilter: ['style'] });
- }
+function storePanZoomVal(transformMatrix) {
+ localStorage.setItem(storageKey, transformMatrix);
+}
- #restorePanZoomVal(svg) {
- const storedPanZoomVal = localStorage.getItem(this.#storageKey);
+function observePanZoomChanges(svg) {
+ const observer = new MutationObserver(() => storePanZoomVal(svg.style.transform));
- if (storedPanZoomVal) {
- svg.style.transform = storedPanZoomVal;
- }
- }
+ observer.observe(svg, { attributeFilter: ['style'] });
+}
- #addEventListeners(svg) {
- svg.addEventListener('wheel', e => zoom(svg, e, this.#zoomFactor), { passive: false });
- svg.addEventListener('pointerdown', e => pan(svg, e), { passive: false });
- }
-};
+export default function (svg) {
+ restorePanZoomVal(svg);
+ addEventListeners(svg);
+ observePanZoomChanges(svg);
+}