WIP: auto-pan map to selected counter
This commit is contained in:
parent
33caa636d7
commit
a85a2d6575
2
node_modules/pan-zoom/index.js
generated
vendored
Normal file
2
node_modules/pan-zoom/index.js
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { default as pan, manualPan } from './src/modules/pan.js';
|
||||||
|
export { default as zoom } from './src/modules/zoom.js';
|
86
node_modules/pan-zoom/src/modules/pan.js
generated
vendored
Normal file
86
node_modules/pan-zoom/src/modules/pan.js
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
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.y);
|
||||||
|
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 = '');
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
const t1Rect = t1.getBoundingClientRect();
|
||||||
|
console.log('trooper1 DOM x,y', t1Rect.x, t1Rect.y);
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
}
|
@ -1,15 +1,14 @@
|
|||||||
import * as firingArc from './game/firing_arc.js';
|
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 { manualPan } from 'pan-zoom';
|
||||||
|
|
||||||
let svg,
|
let svg,
|
||||||
placing = [];
|
placing = [];
|
||||||
|
|
||||||
const top = {
|
|
||||||
collection: new Map()
|
|
||||||
};
|
|
||||||
|
|
||||||
const frontmostStore = new Map();
|
const frontmostStore = new Map();
|
||||||
|
|
||||||
function getCellContents(cell) {
|
function getCellContents(cell) {
|
||||||
@ -194,6 +193,11 @@ function select(data) {
|
|||||||
if (isSelected || !data) return;
|
if (isSelected || !data) return;
|
||||||
|
|
||||||
counter.classList.add(soldier.getSelectedClass());
|
counter.classList.add(soldier.getSelectedClass());
|
||||||
|
const gb = svg.querySelector('.gameboard');
|
||||||
|
|
||||||
|
// TODO check if counter is on board before calling
|
||||||
|
manualPan(gb, counter);
|
||||||
|
|
||||||
firingArc.get(svg, counter).forEach(el => el.removeAttribute('clip-path'));
|
firingArc.get(svg, counter).forEach(el => el.removeAttribute('clip-path'));
|
||||||
placing.push(counter);
|
placing.push(counter);
|
||||||
}
|
}
|
||||||
@ -215,8 +219,8 @@ export function start(el) {
|
|||||||
// For when the pointer leaves the window
|
// For when the pointer leaves the window
|
||||||
document.querySelector('object').addEventListener('pointerout', e => {
|
document.querySelector('object').addEventListener('pointerout', e => {
|
||||||
if (clearHexDialog.open) return;
|
if (clearHexDialog.open) return;
|
||||||
console.log('object pointerout');
|
//console.log('object pointerout');
|
||||||
console.log('Left map... CLEARING HOVERS');
|
//console.log('Left map... CLEARING HOVERS');
|
||||||
svg.querySelectorAll('.hover').forEach(el => el.classList.remove('hover'));
|
svg.querySelectorAll('.hover').forEach(el => el.classList.remove('hover'));
|
||||||
|
|
||||||
[...frontmost.children].forEach(child => {
|
[...frontmost.children].forEach(child => {
|
||||||
@ -236,7 +240,7 @@ export function start(el) {
|
|||||||
|
|
||||||
// Pointer moves outside the edge of the grid
|
// Pointer moves outside the edge of the grid
|
||||||
if (!targetCell) {
|
if (!targetCell) {
|
||||||
console.log('No target cell... CLEARING HOVERS');
|
//console.log('No target cell... CLEARING HOVERS');
|
||||||
svg.querySelectorAll('.hover').forEach(el => el.classList.remove('hover'));
|
svg.querySelectorAll('.hover').forEach(el => el.classList.remove('hover'));
|
||||||
|
|
||||||
[...frontmost.children].forEach(child => {
|
[...frontmost.children].forEach(child => {
|
||||||
@ -257,7 +261,7 @@ export function start(el) {
|
|||||||
// 's contents that is in frontmost, whose parent cell is not already highlighted
|
// 's contents that is in frontmost, whose parent cell is not already highlighted
|
||||||
!(targetCell.classList.contains('frontmost') && frontmostStore.get(e.target.closest('.frontmost > *')).classList.contains('hover'))
|
!(targetCell.classList.contains('frontmost') && frontmostStore.get(e.target.closest('.frontmost > *')).classList.contains('hover'))
|
||||||
].every(e => e)) {
|
].every(e => e)) {
|
||||||
console.log('Target cell missing hover... CLEARING HOVERS AND ADDING TO TARGET CELL');
|
//console.log('Target cell missing hover... CLEARING HOVERS AND ADDING TO TARGET CELL');
|
||||||
svg.querySelectorAll('.hover').forEach(el => el.classList.remove('hover'));
|
svg.querySelectorAll('.hover').forEach(el => el.classList.remove('hover'));
|
||||||
|
|
||||||
if (placing[0]?.getAttributeNS(null, 'class') === 'mech-template') {
|
if (placing[0]?.getAttributeNS(null, 'class') === 'mech-template') {
|
||||||
@ -299,7 +303,7 @@ export function start(el) {
|
|||||||
getActiveSightLine(svg) && clearSightLine();
|
getActiveSightLine(svg) && clearSightLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('frontmost contents', frontmost.children);
|
//console.log('frontmost contents', frontmost.children);
|
||||||
});
|
});
|
||||||
|
|
||||||
grid.addEventListener('click', clickHandler);
|
grid.addEventListener('click', clickHandler);
|
||||||
@ -378,17 +382,24 @@ export function start(el) {
|
|||||||
//cell2.classList.add('hover');
|
//cell2.classList.add('hover');
|
||||||
//
|
//
|
||||||
|
|
||||||
//soldier.place(
|
const trooper1 = soldier.createCounter({ dataset: { allegiance: 'attacker', number: 1, squad: 1 }}, 'blazer');
|
||||||
// svg,
|
|
||||||
// soldier.createCounter({ dataset: { allegiance: 'attacker', number: 2, squad: 1 }}, 'hsplaser'),
|
|
||||||
// getCell(-2, 3, -1, 0)
|
soldier.place(svg, trooper1, getCell(-3, 9, -6, 0));
|
||||||
//);
|
|
||||||
//
|
soldier.place(
|
||||||
//soldier.place(
|
svg,
|
||||||
// svg,
|
soldier.createCounter({ dataset: { allegiance: 'defender', number: 1, squad: 1 }}, 'blazer'),
|
||||||
// soldier.createCounter({ dataset: { allegiance: 'attacker', number: 2, squad: 5 }}, 'rifle'),
|
getCell(1, -8, 7, 0)
|
||||||
// getCell(-3, 3, 0, 0)
|
);
|
||||||
//);
|
|
||||||
|
const t1Rect = trooper1.getBoundingClientRect();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const t1Rect = trooper1.getBoundingClientRect();
|
||||||
|
console.log('trooper', trooper1, trooper1.getBoundingClientRect());
|
||||||
|
|
||||||
|
}, 10);
|
||||||
|
|
||||||
// Add some counters in an unoccupied cell
|
// Add some counters in an unoccupied cell
|
||||||
//const countersCell = getCell(-1, 1, 0, 0);
|
//const countersCell = getCell(-1, 1, 0, 0);
|
||||||
|
@ -19,6 +19,9 @@ function addEventListeners(svg, el) {
|
|||||||
pan(svg, el, e), { passive: false };
|
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