Extract programmatic pan coord calculations into gameboard module
This commit is contained in:
parent
ca9ad3ac2a
commit
90fe01caaf
2
node_modules/pan-zoom/index.js
generated
vendored
2
node_modules/pan-zoom/index.js
generated
vendored
@ -1,2 +0,0 @@
|
|||||||
export { default as pan, manualPan } from './src/modules/pan.js';
|
|
||||||
export { default as zoom } from './src/modules/zoom.js';
|
|
82
node_modules/pan-zoom/src/modules/pan.js
generated
vendored
82
node_modules/pan-zoom/src/modules/pan.js
generated
vendored
@ -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 }
|
|
||||||
);
|
|
||||||
}
|
|
13
package-lock.json
generated
13
package-lock.json
generated
@ -5,7 +5,7 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pan-zoom": "github:webdevcat-me/pan-zoom"
|
"pan-zoom": "file:../pan-zoom"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"esbuild": "^0.20.2",
|
"esbuild": "^0.20.2",
|
||||||
@ -16,6 +16,13 @@
|
|||||||
"selenium-webdriver": "^4.19.0"
|
"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": {
|
"node_modules/@ampproject/remapping": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
||||||
@ -3819,8 +3826,8 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/pan-zoom": {
|
"node_modules/pan-zoom": {
|
||||||
"version": "0.2.0",
|
"resolved": "../pan-zoom",
|
||||||
"resolved": "git+ssh://git@github.com/webdevcat-me/pan-zoom.git#9c34e15c47cf3578adeff41693a62061a25fdcde"
|
"link": true
|
||||||
},
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pan-zoom": "github:webdevcat-me/pan-zoom"
|
"pan-zoom": "file:../pan-zoom"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"esbuild": "^0.20.2",
|
"esbuild": "^0.20.2",
|
||||||
|
@ -10,4 +10,4 @@ else
|
|||||||
port=8080
|
port=8080
|
||||||
fi
|
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 $@
|
||||||
|
@ -2,15 +2,13 @@ import * as firingArc from './game/firing_arc.js';
|
|||||||
import * as sightLine from './game/sight_line.js';
|
import * as sightLine from './game/sight_line.js';
|
||||||
import * as soldier from './game/soldier.js';
|
import * as soldier from './game/soldier.js';
|
||||||
import { Observable } from './observable';
|
import { Observable } from './observable';
|
||||||
|
import { programmaticPan } from 'pan-zoom';
|
||||||
|
|
||||||
|
const frontmostStore = new Map();
|
||||||
import { manualPan } from 'pan-zoom';
|
|
||||||
|
|
||||||
let svg,
|
let svg,
|
||||||
placing = [];
|
placing = [];
|
||||||
|
|
||||||
const frontmostStore = new Map();
|
|
||||||
|
|
||||||
function getCellContents(cell) {
|
function getCellContents(cell) {
|
||||||
return cell.querySelectorAll('*:not(use[href="#hex"])');
|
return cell.querySelectorAll('*:not(use[href="#hex"])');
|
||||||
}
|
}
|
||||||
@ -184,6 +182,27 @@ function selectOffBoard() {
|
|||||||
Observable.notify('select', this, { revealRecord: true });
|
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) {
|
function select(data, opts) {
|
||||||
const counter = data && (soldier.getCounter(svg, data) || soldier.createCounter(data));
|
const counter = data && (soldier.getCounter(svg, data) || soldier.createCounter(data));
|
||||||
const isSelected = data && data.classList && data.classList.contains('selected');
|
const isSelected = data && data.classList && data.classList.contains('selected');
|
||||||
@ -192,10 +211,8 @@ function select(data, opts) {
|
|||||||
|
|
||||||
if (isSelected || !data) return;
|
if (isSelected || !data) return;
|
||||||
|
|
||||||
if (opts?.revealCounter && document.querySelector('#auto-center-map').checked) {
|
if (opts?.revealCounter && document.querySelector('#auto-center-map').checked)
|
||||||
const gb = svg.querySelector('.gameboard');
|
panMapToCounter(counter);
|
||||||
if (gb.contains(counter)) manualPan(gb, counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
counter.classList.add(soldier.getSelectedClass());
|
counter.classList.add(soldier.getSelectedClass());
|
||||||
firingArc.get(svg, counter).forEach(el => el.removeAttribute('clip-path'));
|
firingArc.get(svg, counter).forEach(el => el.removeAttribute('clip-path'));
|
||||||
|
@ -1,27 +1,17 @@
|
|||||||
import { pan, zoom } from 'pan-zoom';
|
import { pan, zoom } from 'pan-zoom';
|
||||||
|
|
||||||
const storageKey = 'pan-zoom',
|
const storageKey = 'pan-zoom';
|
||||||
zoomFactor = 0.25;
|
const zoomFactor = 0.25;
|
||||||
|
|
||||||
function restorePanZoomVal(el) {
|
function restorePanZoomVal(el) {
|
||||||
const storedPanZoomVal = localStorage.getItem(storageKey);
|
const storedPanZoomVal = localStorage.getItem(storageKey);
|
||||||
|
|
||||||
if (storedPanZoomVal) {
|
if (storedPanZoomVal) el.style.transform = storedPanZoomVal;
|
||||||
el.style.transform = storedPanZoomVal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addEventListeners(svg, el) {
|
function addEventListeners(svg, el) {
|
||||||
svg.addEventListener('wheel', e => zoom(el, e, zoomFactor), { passive: false });
|
svg.addEventListener('wheel', zoom(el, zoomFactor), { passive: false });
|
||||||
svg.addEventListener('pointerdown', e => {
|
svg.addEventListener('pointerdown', pan(el), { passive: false });
|
||||||
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}`);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function storePanZoomVal(transformMatrix) {
|
function storePanZoomVal(transformMatrix) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user