Fix 'pan event being cancelled by the browser' bug

This commit is contained in:
Catalin Mititiuc 2024-04-04 15:14:16 -07:00
parent 9e653d0681
commit b75a92bfe3
3 changed files with 81 additions and 76 deletions

View File

@ -101,45 +101,6 @@
</p>
</template>
<div id="debug">
<fieldset name="point">
<legend>hex</legend>
<div>
<label>translatex <input name="translateX" type="number" value="0" /></label>
<label>translatey <input name="translateY" type="number" value="0" /></label>
<label>rotate <input name="rotate" type="number" step="0.1" value="0" /></label>
<label>scale <input name="scale" type="number" step="0.1" value="1" /></label>
</div>
</fieldset>
<fieldset name="points">
<legend>grid</legend>
<div>
<label>translatex <input name="translateX" type="number" value="0" /></label>
<label>translatey <input name="translateY" type="number" value="0" /></label>
<label>rotate <input name="rotate" type="number" step="0.1" value="0" /></label>
<label>scale <input name="scale" type="number" step="0.1" value="1" /></label>
</div>
</fieldset>
<fieldset name="map2">
<legend>map2</legend>
<div>
<label>translatex <input name="translateX" type="number" value="0" /></label>
<label>translatey <input name="translateY" type="number" value="0" /></label>
<label>rotate <input name="rotate" type="number" step="0.1" value="0" /></label>
<label>scale <input name="scale" type="number" step="0.1" value="1" /></label>
</div>
</fieldset>
<fieldset name="map3">
<legend>map3</legend>
<div>
<label>translatex <input name="translateX" type="number" value="0" /></label>
<label>translatey <input name="translateY" type="number" value="0" /></label>
<label>rotate <input name="rotate" type="number" step="0.1" value="0" /></label>
<label>scale <input name="scale" type="number" step="0.1" value="1" /></label>
</div>
</fieldset>
</div>
<div id="map-container">
<div id="toggle-firing-arc-vis">
<div>davion</div>
@ -147,6 +108,50 @@
<div>liao</div>
<input type="checkbox" data-allegiance="liao" />
</div>
<div id="panel">
<fieldset name="point">
<legend>hex</legend>
<div>
<label>translateX <input name="translateX" type="number" step="0.1" value="0" /></label>
<label>translateY <input name="translateY" type="number" step="0.1" value="0" /></label>
<label>rotate <input name="rotate" type="number" step="0.1" value="0" /></label>
<label>scaleX <input name="scaleX" type="number" step="0.1" value="1" /></label>
<label>scaleY <input name="scaleY" type="number" step="0.1" value="1" /></label>
</div>
</fieldset>
<fieldset name="points">
<legend>grid</legend>
<div>
<label>translateX <input name="translateX" type="number" step="0.1" value="0" /></label>
<label>translateY <input name="translateY" type="number" step="0.1" value="0" /></label>
<label>rotate <input name="rotate" type="number" step="0.1" value="0" /></label>
<label>scaleX <input name="scaleX" type="number" step="0.1" value="1" /></label>
<label>scaleY <input name="scaleY" type="number" step="0.1" value="1" /></label>
</div>
</fieldset>
<fieldset name="map2">
<legend>map2</legend>
<div>
<label>translateX <input name="translateX" type="number" step="0.1" value="0" /></label>
<label>translateY <input name="translateY" type="number" step="0.1" value="0" /></label>
<label>rotate <input name="rotate" type="number" step="0.1" value="0" /></label>
<label>scaleX <input name="scaleX" type="number" step="0.001" value="1" /></label>
<label>scaleY <input name="scaleY" type="number" step="0.001" value="1" /></label>
</div>
</fieldset>
<fieldset name="map3">
<legend>map3</legend>
<div>
<label>translateX <input name="translateX" type="number" step="0.1" value="0" /></label>
<label>translateY <input name="translateY" type="number" step="0.1" value="0" /></label>
<label>rotate <input name="rotate" type="number" step="0.1" value="0" /></label>
<label>scaleX <input name="scaleX" type="number" step="0.001" value="1" /></label>
<label>scaleY <input name="scaleY" type="number" step="0.001" value="1" /></label>
</div>
</fieldset>
</div>
<svg viewbox="-49 -40 2390 3163" xmlns="http://www.w3.org/2000/svg">
<defs>
<polygon id="point" points="0,10 8.66,5 8.66,-5 0,-10 -8.66,-5 -8.66,5" />
@ -197,8 +202,8 @@
<rect id="background" x="-1" y="-1" width="2287" height="3087" />
<g id="image-maps">
<image id="map2" class="map-scans" href="scans/map2.jpg" width="2284" height="1518" x="2" y="2" />
<image id="map3" class="map-scans" href="scans/map3.jpg" width="2284" height="1518" x="4" y="1564" />
<image id="map2" class="map-scans" href="scans/map2.jpg" width="2284" height="1518" />
<image id="map3" class="map-scans" href="scans/map3.jpg" width="2284" height="1518" />
</g>
<g id="firing-arcs">
@ -217,8 +222,6 @@
<use href="#n2" x="19" y="-40" opacity="0.5" />
<use href="#n3" x="36" y="-40" opacity="0.5" />
<use href="#n4" x="54" y="-40" opacity="0.5" />
<!-- <rect id="debug-view-box" x="-100" y="-100" width="3400" height="4500" /> -->
</svg>
<div id="status">

View File

@ -294,10 +294,11 @@ if (recVis == 'false') {
let info = document.getElementById('status');
// Object.values(settingsPanel.querySelectorAll('fieldset')).forEach(fieldset => {
[].forEach(fieldset => {
Object.values(settingsPanel.querySelectorAll('fieldset')).forEach(fieldset => {
// [].forEach(fieldset => {
const identityMtx = [1, 0, 0, 1, 0, 0];
const target = document.getElementById(fieldset.name);
const transform = getComputedStyle(target).transform.match(/-?\d+\.?\d*/g);
const transform = getComputedStyle(target).transform.match(/-?\d+\.?\d*/g) || identityMtx;
const inputs = fieldset.querySelectorAll('input');
if (transform) {
@ -310,7 +311,8 @@ let info = document.getElementById('status');
const scaleY = Math.sqrt(b**2 + d**2);
let values = {
scale: Math.round(scaleX * 10) / 10,
scaleX: Math.round(scaleX * 1000) / 1000,
scaleY: Math.round(scaleY * 1000) / 1000,
translateX: e,
translateY: f,
rotate: Math.round(radToDeg((Math.acos(a / scaleX) + Math.asin(b / scaleY)) / 2) * 10) / 10
@ -323,12 +325,13 @@ let info = document.getElementById('status');
input.addEventListener('pointerenter', e => e.target.focus());
input.addEventListener('input', e => {
let { scale, translateX, translateY, rotate} = Object.values(inputs).reduce((acc, input) => {
acc[input.name] = input.value;
return acc;
}, {});
let { translateX, translateY, rotate, scaleX, scaleY } =
Object.values(inputs).reduce((acc, input) => {
acc[input.name] = input.value;
return acc;
}, {});
let transform = `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) scale(${scale})`;
let transform = `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) scale(${scaleX}, ${scaleY})`;
target.style.transform = transform;
});
@ -888,11 +891,14 @@ svg.addEventListener('wheel', e => {
let vb = `${newX} ${newY} ${newWidth} ${newHeight}`
// TODO attribute change event?
localStorage.setItem('viewBox', vb);
svg.setAttributeNS(null, 'viewBox', vb);
});
svg.addEventListener('pointerdown', e => {
e.preventDefault();
const minPanDistanceThreshold = 5;
let dist, ctm,
@ -904,16 +910,19 @@ svg.addEventListener('pointerdown', e => {
function pointerMove(e) {
movePt.x = e.clientX;
movePt.y = e.clientY;
dist = Math.sqrt((movePt.x - startPt.x)**2 + (movePt.y - startPt.y)**2);
if (!pan && dist >= minPanDistanceThreshold) {
pan = true;
startPt.x = e.clientX;
startPt.y = e.clientY;
if (!pan) {
dist = Math.sqrt((movePt.x - startPt.x)**2 + (movePt.y - startPt.y)**2);
if (dist >= minPanDistanceThreshold) {
pan = true;
svg.setPointerCapture(e.pointerId);
startPt.x = e.clientX;
startPt.y = e.clientY;
}
}
if (pan) {
svg.setPointerCapture(e.pointerId);
ctm = svg.getScreenCTM().inverse();
const [svgStartPt, svgMovePt] = [startPt, movePt].map(p => p.matrixTransform(ctm)),
@ -928,7 +937,6 @@ svg.addEventListener('pointerdown', e => {
}
function pointerUp(e) {
svg.releasePointerCapture(e.pointerId);
svg.removeEventListener('pointermove', pointerMove);
svg.removeEventListener('pointerup', pointerUp);
}

View File

@ -24,6 +24,10 @@ svg image.map-scans {
image-rendering: auto;
}
svg text {
user-select: none;
}
div#status {
position: absolute;
bottom: 0;
@ -159,19 +163,17 @@ g#grid {
}
#map2 {
transform: rotate(0.1deg);
transform-origin: 0px 0px;
transform: translate(-0.9px, -2.4px) scale(0.999, 1.007);
}
#map3 {
transform: rotate(0.1deg);
transform-origin: 0px 0px;
/* transform: translateY(1518px); */
transform: translate(1.3px, 1564.1px) rotate(0.1deg) scale(0.999, 1.002);
}
image.map-scans {
/* transform: scale(1.39, 1.407) rotate(0.07deg); */
/* opacity: 0.33; */
}
#debug {
#panel {
display: none;
position: absolute;
right: 0;
@ -180,7 +182,7 @@ image.map-scans {
padding: 2px;
}
#debug fieldset label {
#panel fieldset label {
display: block;
text-align: right;
}
@ -259,14 +261,6 @@ text.counter, #troop-counter text {
user-select: none;
}
rect#map {
fill: black;
opacity: 0;
/* fill-opacity: 0;
stroke: red;
stroke-width: 4px; */
}
polygon.firing-arc[data-troop-allegiance="davion"] {
fill: red;
}