stricter thresholds for clicks and taps to avoid accidental pixel
placing
This commit is contained in:
parent
ce09198374
commit
641c996c0c
|
@ -16,6 +16,7 @@ import {
|
|||
screenToWorld,
|
||||
getChunkOfPixel,
|
||||
getOffsetOfPixel,
|
||||
getTapOrClickCenter,
|
||||
} from '../core/utils';
|
||||
import {
|
||||
HOLD_PAINT,
|
||||
|
@ -28,8 +29,9 @@ class PixelPainterControls {
|
|||
//
|
||||
clickTapStartView = [0, 0];
|
||||
clickTapStartTime = 0;
|
||||
clickTapStartCoords = [0, 0];
|
||||
tapStartDist = 50;
|
||||
// screen coords of where a tap/click started
|
||||
clickTapStartCoords = [0, 0];
|
||||
// stored speed for acceleration
|
||||
speedScalar = 0;
|
||||
// on mouse: true as long as left mouse button is pressed
|
||||
|
@ -118,7 +120,7 @@ class PixelPainterControls {
|
|||
].map(Math.abs);
|
||||
// thresholds for single click / holding
|
||||
if (clickTapStartTime > Date.now() - 250
|
||||
&& coordsDiff[0] < 3 && coordsDiff[1] < 3
|
||||
&& coordsDiff[0] < 6 && coordsDiff[1] < 6
|
||||
) {
|
||||
PixelPainterControls.placePixel(
|
||||
store,
|
||||
|
@ -231,7 +233,7 @@ class PixelPainterControls {
|
|||
this.clearTabTimeout();
|
||||
this.isTapPainting = false;
|
||||
this.clickTapStartTime = Date.now();
|
||||
this.clickTapStartCoords = PixelPainterControls.getTouchCenter(event);
|
||||
this.clickTapStartCoords = getTapOrClickCenter(event);
|
||||
this.clickTapStartView = this.renderer.view;
|
||||
|
||||
if (event.touches.length > 1) {
|
||||
|
@ -263,26 +265,25 @@ class PixelPainterControls {
|
|||
onTouchEnd(event) {
|
||||
event.preventDefault();
|
||||
if (event.touches.length) {
|
||||
// still other touches left
|
||||
return;
|
||||
}
|
||||
|
||||
const { store, renderer } = this;
|
||||
if (!this.wasEverMultiTap) {
|
||||
const { pageX, pageY } = event.changedTouches[0];
|
||||
const [clientX, clientY] = getTapOrClickCenter(event);
|
||||
const { clickTapStartCoords, clickTapStartTime } = this;
|
||||
const coordsDiff = [
|
||||
clickTapStartCoords[0] - pageX,
|
||||
clickTapStartCoords[1] - pageY,
|
||||
clickTapStartCoords[0] - clientX,
|
||||
clickTapStartCoords[1] - clientY,
|
||||
].map(Math.abs);
|
||||
// thresholds for single click / holding
|
||||
if (clickTapStartTime > Date.now() - 580
|
||||
&& coordsDiff[0] < 3 && coordsDiff[1] < 3
|
||||
&& coordsDiff[0] < 6 && coordsDiff[1] < 6
|
||||
) {
|
||||
PixelPainterControls.placePixel(
|
||||
store,
|
||||
this.renderer,
|
||||
this.screenToWorld([pageX, pageY]),
|
||||
this.screenToWorld([clientX, clientY]),
|
||||
);
|
||||
setTimeout(() => {
|
||||
store.dispatch(unsetHover());
|
||||
|
@ -300,7 +301,7 @@ class PixelPainterControls {
|
|||
const multiTouch = (event.touches.length > 1);
|
||||
const state = this.store.getState();
|
||||
|
||||
const [clientX, clientY] = PixelPainterControls.getTouchCenter(event);
|
||||
const [clientX, clientY] = getTapOrClickCenter(event);
|
||||
if (this.isMultiTap !== multiTouch) {
|
||||
this.wasEverMultiTap = true;
|
||||
// if one finger got lifted or added, reset clickTabStart
|
||||
|
@ -328,7 +329,7 @@ class PixelPainterControls {
|
|||
const [lastPosX, lastPosY] = clickTapStartView;
|
||||
const deltaX = clientX - clickTapStartCoords[0];
|
||||
const deltaY = clientY - clickTapStartCoords[1];
|
||||
if (deltaX > 2 || deltaY > 2) {
|
||||
if (deltaX > 5 || deltaY > 5) {
|
||||
this.clearTabTimeout();
|
||||
}
|
||||
const { viewscale: scale } = this.renderer;
|
||||
|
|
|
@ -636,6 +636,30 @@ export function getDateKeyOfTs(ts) {
|
|||
return `${year}${month}${day}`;
|
||||
}
|
||||
|
||||
/*
|
||||
* get screen coords of touch / mouse event
|
||||
* @param event MouseEvent or TouchEvent
|
||||
* @return [x, y] in screen coordinates
|
||||
*/
|
||||
export function getTapOrClickCenter(event) {
|
||||
if (event instanceof TouchEvent) {
|
||||
const touches = (event.touches.length)
|
||||
? event.touches : event.changedTouches;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
for (const { pageX, pageY } of touches) {
|
||||
x += pageX;
|
||||
y += pageY;
|
||||
}
|
||||
const { length } = touches;
|
||||
return [x / length, y / length];
|
||||
}
|
||||
return [
|
||||
event.clientX,
|
||||
event.clientY,
|
||||
];
|
||||
}
|
||||
|
||||
/*
|
||||
* check if parent window exists and
|
||||
* is accessible
|
||||
|
|
|
@ -28,6 +28,7 @@ import ChunkLoader from './ChunkLoader3D';
|
|||
import {
|
||||
getChunkOfPixel,
|
||||
getOffsetOfPixel,
|
||||
getTapOrClickCenter,
|
||||
} from '../core/utils';
|
||||
import {
|
||||
THREE_TILE_SIZE,
|
||||
|
@ -62,12 +63,15 @@ class Renderer3D extends Renderer {
|
|||
threeRenderer;
|
||||
// temp variables for mouse events
|
||||
mouse = new Vector2();
|
||||
mouseMoveStart;
|
||||
raycaster = new Raycaster();
|
||||
pressTime;
|
||||
pressCdTime;
|
||||
multitap = 0;
|
||||
lastIntersect = 0;
|
||||
// on touch: true if current tab was ever more than one figher at any time
|
||||
wasEverMultiTap = false;
|
||||
// screen coords of where a tap/click started
|
||||
clickTapStartCoords = [0, 0];
|
||||
|
||||
constructor(store) {
|
||||
super(store);
|
||||
|
@ -188,7 +192,6 @@ class Renderer3D extends Renderer {
|
|||
);
|
||||
this.controls = controls;
|
||||
|
||||
|
||||
this.onDocumentMouseMove = this.onDocumentMouseMove.bind(this);
|
||||
this.onDocumentTouchMove = this.onDocumentTouchMove.bind(this);
|
||||
// eslint-disable-next-line max-len
|
||||
|
@ -516,13 +519,16 @@ class Renderer3D extends Renderer {
|
|||
);
|
||||
}
|
||||
|
||||
onDocumentMouseDownOrTouchStart() {
|
||||
onDocumentMouseDownOrTouchStart(event) {
|
||||
this.pressTime = Date.now();
|
||||
const state = this.store.getState();
|
||||
this.mouseMoveStart = state.canvas.hover;
|
||||
this.clickTapStartCoords = getTapOrClickCenter(event);
|
||||
this.wasEverMultiTap = (event.touches?.length > 1);
|
||||
}
|
||||
|
||||
onDocumentTouchMove() {
|
||||
onDocumentTouchMove(event) {
|
||||
if (event.touches?.length > 1) {
|
||||
this.wasEverMultiTap = true;
|
||||
}
|
||||
this.updateRollOverMesh(0, 0);
|
||||
}
|
||||
|
||||
|
@ -581,7 +587,7 @@ class Renderer3D extends Renderer {
|
|||
);
|
||||
}
|
||||
|
||||
multiTapEnd() {
|
||||
multiTapEnd(event) {
|
||||
const {
|
||||
store,
|
||||
multitap,
|
||||
|
@ -589,12 +595,16 @@ class Renderer3D extends Renderer {
|
|||
this.multitap = 0;
|
||||
const state = store.getState();
|
||||
|
||||
if (!this.mouseMoveStart || !state.canvas.hover) {
|
||||
if (!state.canvas.hover || this.wasEverMultiTap) {
|
||||
return;
|
||||
}
|
||||
const [px, py, pz] = this.mouseMoveStart;
|
||||
const [qx, qy, qz] = state.canvas.hover;
|
||||
if (px !== qx || py !== qy || pz !== qz) {
|
||||
const [clientX, clientY] = getTapOrClickCenter(event);
|
||||
const { clickTapStartCoords } = this;
|
||||
const coordsDiff = [
|
||||
clickTapStartCoords[0] - clientX,
|
||||
clickTapStartCoords[1] - clientY,
|
||||
].map(Math.abs);
|
||||
if (coordsDiff[0] > 5 || coordsDiff[1] > 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -605,7 +615,7 @@ class Renderer3D extends Renderer {
|
|||
if (this.rollOverMesh.position.y < 0) {
|
||||
return;
|
||||
}
|
||||
this.placeVoxel(px, py, pz);
|
||||
this.placeVoxel(...state.canvas.hover);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
|
@ -644,6 +654,9 @@ class Renderer3D extends Renderer {
|
|||
|
||||
onDocumentTouchEnd(event) {
|
||||
event.preventDefault();
|
||||
if (event.touches.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const curTime = Date.now();
|
||||
if (curTime - this.pressTime > 600) {
|
||||
|
@ -654,7 +667,7 @@ class Renderer3D extends Renderer {
|
|||
// we should reset on every tap
|
||||
// but we don't need that right now...
|
||||
if (this.multitap === 0) {
|
||||
setTimeout(this.multiTapEnd, 500);
|
||||
setTimeout(() => this.multiTapEnd(event), 500);
|
||||
}
|
||||
this.multitap += 1;
|
||||
}
|
||||
|
@ -680,21 +693,21 @@ class Renderer3D extends Renderer {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!this.mouseMoveStart || !state.canvas.hover) {
|
||||
if (!state.canvas.hover) {
|
||||
return;
|
||||
}
|
||||
const [px, py, pz] = this.mouseMoveStart;
|
||||
const [qx, qy, qz] = state.canvas.hover;
|
||||
if (px !== qx || py !== qy || pz !== qz) {
|
||||
const [clientX, clientY] = getTapOrClickCenter(event);
|
||||
const { clickTapStartCoords } = this;
|
||||
const coordsDiff = [
|
||||
clickTapStartCoords[0] - clientX,
|
||||
clickTapStartCoords[1] - clientY,
|
||||
].map(Math.abs);
|
||||
if (coordsDiff[0] > 5 || coordsDiff[1] > 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
const {
|
||||
clientX,
|
||||
clientY,
|
||||
button,
|
||||
} = event;
|
||||
const { button } = event;
|
||||
const {
|
||||
innerWidth,
|
||||
innerHeight,
|
||||
|
|
Loading…
Reference in New Issue
Block a user