index : btroops | |
Virtual board game-aid for BattleTroops, an infantry combat simulator wargame published by FASA in 1989. |
aboutsummaryrefslogtreecommitdiff |
diff options
author | Catalin Mititiuc <webdevcat@proton.me> | 2024-08-09 10:22:44 -0700 |
---|---|---|
committer | Catalin Mititiuc <webdevcat@proton.me> | 2024-08-09 10:22:44 -0700 |
commit | 90fe01caaf5b8e0488aef15eb5c76f1e87145797 (patch) | |
tree | 8d4bdc49898ed8a3842468b93638400496891b6e | |
parent | ca9ad3ac2a8a0b5709ae7f55dcff3a7473bb9203 (diff) |
Extract programmatic pan coord calculations into gameboard module
-rw-r--r-- | node_modules/pan-zoom/index.js | 2 | ||||
-rw-r--r-- | node_modules/pan-zoom/src/modules/pan.js | 82 | ||||
-rw-r--r-- | package-lock.json | 13 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rwxr-xr-x | scripts/docker-run | 2 | ||||
-rw-r--r-- | src/modules/gameboard.js | 33 | ||||
-rw-r--r-- | src/modules/pan-zoom.js | 20 |
7 files changed, 42 insertions, 112 deletions
diff --git a/node_modules/pan-zoom/index.js b/node_modules/pan-zoom/index.js deleted file mode 100644 index ab80f47..0000000 --- a/node_modules/pan-zoom/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default as pan, manualPan } from './src/modules/pan.js'; -export { default as zoom } from './src/modules/zoom.js'; diff --git a/node_modules/pan-zoom/src/modules/pan.js b/node_modules/pan-zoom/src/modules/pan.js deleted file mode 100644 index 98fc74b..0000000 --- a/node_modules/pan-zoom/src/modules/pan.js +++ /dev/null @@ -1,82 +0,0 @@ -import getComputedTransformMatrix from './utils.js'; - -const minDistanceThreshold = 5; - -function distanceBetween({ x: x1, y: y1 }, { x: x2, y: y2 }) { - return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); -} - -function minDistanceThresholdIsMet(startPt, endPt) { - return distanceBetween(startPt, endPt) >= minDistanceThreshold; -} - -function stopEventPropagationToChildren(el, type) { - el.addEventListener(type, e => e.stopPropagation(), { capture: true, once: true }); -} - -function getTranslateMatrix(startPt, movePt) { - const translateMatrix = new DOMMatrix(); - - return translateMatrix.translate(movePt.x - startPt.x, movePt.y - startPt.y); -} - -export function manualPan(gb, counter) { - const mtx = getComputedTransformMatrix(gb), - inverseScreenCTM = gb.getScreenCTM().inverse(); - - const counterRect = counter.getBoundingClientRect(); - const mapRect = document.querySelector('object').getBoundingClientRect(); - - let startPt = new DOMPoint(counterRect.x + counterRect.width / 2, counterRect.y + counterRect.height / 2); - let movePt = new DOMPoint(mapRect.width / 2, mapRect.height / 2); - - startPt = startPt.matrixTransform(inverseScreenCTM); - movePt = movePt.matrixTransform(inverseScreenCTM); - - gb.style.transition = 'transform 0.5s'; - gb.style.transform = mtx.multiply(getTranslateMatrix(startPt, movePt)); - gb.addEventListener('transitionend', () => gb.style.transition = '', { once: true }); -} - -export default function (svg, el, e) { - e.preventDefault(); - - const mtx = getComputedTransformMatrix(el), - inverseScreenCTM = el.getScreenCTM().inverse(); - - let startPt = new DOMPoint(e.clientX, e.clientY), - movePt = new DOMPoint(), - isPanning = false; - - function pointerMove(e) { - movePt.x = e.clientX; - movePt.y = e.clientY; - - if (!isPanning && minDistanceThresholdIsMet(startPt, movePt)) { - isPanning = true; - //e.target.setPointerCapture(e.pointerId); - - startPt.x = e.clientX; - startPt.y = e.clientY; - startPt = startPt.matrixTransform(inverseScreenCTM); - - stopEventPropagationToChildren(el, 'click'); - } - - if (isPanning) { - movePt.x = e.clientX; - movePt.y = e.clientY; - movePt = movePt.matrixTransform(inverseScreenCTM); - - el.style.transform = mtx.multiply(getTranslateMatrix(startPt, movePt)); - } - } - - svg.addEventListener('pointermove', pointerMove); - - svg.addEventListener( - 'pointerup', - () => svg.removeEventListener('pointermove', pointerMove), - { once: true } - ); -} diff --git a/package-lock.json b/package-lock.json index c66ac96..b7e3a65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,7 @@ "packages": { "": { "dependencies": { - "pan-zoom": "github:webdevcat-me/pan-zoom" + "pan-zoom": "file:../pan-zoom" }, "devDependencies": { "esbuild": "^0.20.2", @@ -16,6 +16,13 @@ "selenium-webdriver": "^4.19.0" } }, + "../pan-zoom": { + "version": "0.2.0", + "devDependencies": { + "esbuild": "^0.20.2", + "esbuild-server": "^0.3.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -3819,8 +3826,8 @@ "dev": true }, "node_modules/pan-zoom": { - "version": "0.2.0", - "resolved": "git+ssh://git@github.com/webdevcat-me/pan-zoom.git#9c34e15c47cf3578adeff41693a62061a25fdcde" + "resolved": "../pan-zoom", + "link": true }, "node_modules/parent-module": { "version": "1.0.1", diff --git a/package.json b/package.json index e72df9b..805fd31 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "type": "module", "dependencies": { - "pan-zoom": "github:webdevcat-me/pan-zoom" + "pan-zoom": "file:../pan-zoom" }, "devDependencies": { "esbuild": "^0.20.2", diff --git a/scripts/docker-run b/scripts/docker-run index a11ce87..42af014 100755 --- a/scripts/docker-run +++ b/scripts/docker-run @@ -10,4 +10,4 @@ else port=8080 fi -docker run --rm --init -it -v $PWD:/usr/src/app -u $user_id:$user_id -p $port:$port $image $@ +docker run --rm --init -it -v $PWD:/usr/src/app -v $PWD/../pan-zoom:/usr/src/pan-zoom -u $user_id:$user_id -p $port:$port $image $@ diff --git a/src/modules/gameboard.js b/src/modules/gameboard.js index 4218833..4407577 100644 --- a/src/modules/gameboard.js +++ b/src/modules/gameboard.js @@ -2,15 +2,13 @@ import * as firingArc from './game/firing_arc.js'; import * as sightLine from './game/sight_line.js'; import * as soldier from './game/soldier.js'; import { Observable } from './observable'; +import { programmaticPan } from 'pan-zoom'; - -import { manualPan } from 'pan-zoom'; +const frontmostStore = new Map(); let svg, placing = []; -const frontmostStore = new Map(); - function getCellContents(cell) { return cell.querySelectorAll('*:not(use[href="#hex"])'); } @@ -184,6 +182,27 @@ function selectOffBoard() { Observable.notify('select', this, { revealRecord: true }); } +function panMapToCounter(counter) { + const gb = svg.querySelector('.gameboard'); + + if (gb.contains(counter)) { + const counterRect = counter.getBoundingClientRect(); + const mapRect = svg.parentNode.defaultView.frameElement.getBoundingClientRect(); + + const counterCoords = { + clientX: counterRect.x + counterRect.width / 2, + clientY: counterRect.y + counterRect.height / 2 + }; + + const mapViewportCenterCoords = { + clientX: mapRect.width / 2, + clientY: mapRect.height / 2 + }; + + programmaticPan(gb, counterCoords, mapViewportCenterCoords); + } +} + function select(data, opts) { const counter = data && (soldier.getCounter(svg, data) || soldier.createCounter(data)); const isSelected = data && data.classList && data.classList.contains('selected'); @@ -192,10 +211,8 @@ function select(data, opts) { if (isSelected || !data) return; - if (opts?.revealCounter && document.querySelector('#auto-center-map').checked) { - const gb = svg.querySelector('.gameboard'); - if (gb.contains(counter)) manualPan(gb, counter); - } + if (opts?.revealCounter && document.querySelector('#auto-center-map').checked) + panMapToCounter(counter); counter.classList.add(soldier.getSelectedClass()); firingArc.get(svg, counter).forEach(el => el.removeAttribute('clip-path')); diff --git a/src/modules/pan-zoom.js b/src/modules/pan-zoom.js index 5e224e8..76c77f6 100644 --- a/src/modules/pan-zoom.js +++ b/src/modules/pan-zoom.js @@ -1,27 +1,17 @@ import { pan, zoom } from 'pan-zoom'; -const storageKey = 'pan-zoom', - zoomFactor = 0.25; +const storageKey = 'pan-zoom'; +const zoomFactor = 0.25; function restorePanZoomVal(el) { const storedPanZoomVal = localStorage.getItem(storageKey); - if (storedPanZoomVal) { - el.style.transform = storedPanZoomVal; - } + if (storedPanZoomVal) el.style.transform = storedPanZoomVal; } function addEventListeners(svg, el) { - svg.addEventListener('wheel', e => zoom(el, e, zoomFactor), { passive: false }); - svg.addEventListener('pointerdown', e => { - if (e.button === 0) { - e.target.setPointerCapture(e.pointerId); - pan(svg, el, e), { passive: false }; - } - }); - svg.addEventListener('pointermove', e => { - console.log('clientX,clientY', `${e.clientX},${e.clientY}`); - }); + svg.addEventListener('wheel', zoom(el, zoomFactor), { passive: false }); + svg.addEventListener('pointerdown', pan(el), { passive: false }); } function storePanZoomVal(transformMatrix) { |