Add touch controls

This commit is contained in:
Blue (Lukas Rieger) 2020-01-18 23:33:38 +01:00
parent 7cca8e428f
commit c5485e6657
5 changed files with 138 additions and 15 deletions

View File

@ -17,7 +17,8 @@
"homepage": "https://github.com/BlueMap-Minecraft/BlueMap#readme",
"dependencies": {
"jquery": "^3.4.1",
"three": "^0.94.0"
"three": "^0.94.0",
"hammerjs": "^2.0.8"
},
"devDependencies": {
"css-loader": "^3.4.2",

View File

@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<title>BlueMap</title>
</head>
<body>

View File

@ -69,6 +69,7 @@ export default class BlueMap {
this.dataRoot = dataRoot;
this.loadingNoticeElement = $('<div id="bluemap-loading" class="box">loading...</div>').appendTo($(this.element));
window.onerror = this.onLoadError;
this.fileLoader = new FileLoader();
this.blobLoader = new FileLoader();
@ -105,7 +106,7 @@ export default class BlueMap {
this.initModules();
this.start();
});
}).catch(error => this.onLoadError(error.toString()));
}
initModules() {
@ -363,7 +364,6 @@ export default class BlueMap {
return new Promise(resolve => {
this.fileLoader.load(this.dataRoot + 'textures.json', textures => {
textures = JSON.parse(textures);
let materials = [];
for (let i = 0; i < textures['textures'].length; i++) {
let t = textures['textures'][i];
@ -399,7 +399,6 @@ export default class BlueMap {
}
this.hiresMaterial = materials;
resolve();
});
});
@ -458,6 +457,17 @@ export default class BlueMap {
})
}
onLoadError = (message, url, line, col) => {
this.loadingNoticeElement.remove();
this.toggleAlert(undefined, `
<div style="max-width: 500px">
<h1>Error</h1>
<p style="color: red; font-family: monospace">${message}</p>
</div>
`);
};
// ###### UI ######
toggleAlert(id, content) {
@ -474,13 +484,15 @@ export default class BlueMap {
alert.fadeIn(200);
};
let sameAlert = alertBox.find(`.alert[data-alert-id=${id}]`);
if (sameAlert.length > 0){
alertBox.fadeOut(200, () => {
alertBox.html('');
alertBox.show();
});
return;
if (id !== undefined) {
let sameAlert = alertBox.find(`.alert[data-alert-id=${id}]`);
if (sameAlert.length > 0) {
alertBox.fadeOut(200, () => {
alertBox.html('');
alertBox.show();
});
return;
}
}
let oldAlerts = alertBox.find('.alert');

View File

@ -30,6 +30,7 @@ import {
Vector3,
MOUSE
} from 'three';
import Hammer from 'hammerjs';
import { Vector2_ZERO } from './utils.js';
@ -94,10 +95,15 @@ export default class Controls {
this.cameraPosDelta = new Vector3(0, 0, 0);
this.moveDelta = new Vector2(0, 0);
this.keyStates = {}
this.touchStart = new Vector2(0, 0);
this.touchDelta = new Vector2(0, 0);
this.keyStates = {};
this.state = Controls.STATES.NONE;
let canvas = $(this.element).find('canvas').get(0);
// mouse events
window.addEventListener('contextmenu', event => {
event.preventDefault();
}, false);
@ -108,6 +114,37 @@ export default class Controls {
window.addEventListener('keydown', this.onKeyDown, false);
window.addEventListener('keyup', this.onKeyUp, false);
// touch events
this.hammer = new Hammer.Manager(canvas);
let touchMove = new Hammer.Pan({ event: 'move', direction: Hammer.DIRECTION_ALL, threshold: 0 });
let touchTilt = new Hammer.Pan({ event: 'tilt', direction: Hammer.DIRECTION_VERTICAL, pointers: 2, threshold: 0 });
let touchRotate = new Hammer.Rotate({ event: 'rotate', pointers: 2, threshold: 10 });
let touchZoom = new Hammer.Pinch({ event: 'zoom', pointers: 2, threshold: 0 });
touchTilt.recognizeWith(touchRotate);
touchTilt.recognizeWith(touchZoom);
touchRotate.recognizeWith(touchZoom);
this.hammer.add( touchMove );
this.hammer.add( touchTilt );
this.hammer.add( touchRotate );
this.hammer.add( touchZoom );
this.hammer.on('movestart', this.onTouchDown);
this.hammer.on('movemove', this.onTouchMove);
this.hammer.on('moveend', this.onTouchUp);
this.hammer.on('movecancel', this.onTouchUp);
this.hammer.on('tiltstart', this.onTouchTiltDown);
this.hammer.on('tiltmove', this.onTouchTiltMove);
this.hammer.on('tiltend', this.onTouchTiltUp);
this.hammer.on('tiltcancel', this.onTouchTiltUp);
this.hammer.on('rotatestart', this.onTouchRotateDown);
this.hammer.on('rotatemove', this.onTouchRotateMove);
this.hammer.on('rotateend', this.onTouchRotateUp);
this.hammer.on('rotatecancel', this.onTouchRotateUp);
this.hammer.on('zoomstart', this.onTouchZoomDown);
this.hammer.on('zoommove', this.onTouchZoomMove);
this.camera.position.set(0, 1000, 0);
this.camera.lookAt(this.position);
this.camera.updateProjectionMatrix();
@ -218,9 +255,6 @@ export default class Controls {
updateMouseMoves = () => {
this.deltaMouse.set(this.lastMouse.x - this.mouse.x, this.lastMouse.y - this.mouse.y);
this.moveDelta.x = 0;
this.moveDelta.y = 0;
if (this.keyStates[Controls.KEYS.UP]){
this.moveDelta.y -= 20;
}
@ -254,6 +288,9 @@ export default class Controls {
}
this.lastMouse.copy(this.mouse);
this.moveDelta.x = 0;
this.moveDelta.y = 0;
};
onMouseWheel = event => {
@ -305,6 +342,77 @@ export default class Controls {
}
};
onTouchDown = event => {
this.touchStart.x = this.targetPosition.x;
this.touchStart.y = this.targetPosition.z;
this.state = Controls.STATES.MOVE;
};
onTouchMove = event => {
if (this.state !== Controls.STATES.MOVE) return;
this.touchDelta.x = event.deltaX;
this.touchDelta.y = event.deltaY;
if (this.touchDelta.x !== 0 || this.touchDelta.y !== 0) {
this.touchDelta.rotateAround(Vector2_ZERO, -this.direction);
this.targetPosition.x = this.touchStart.x - (this.touchDelta.x * this.distance / this.element.clientHeight * this.settings.move.speed);
this.targetPosition.z = this.touchStart.y - (this.touchDelta.y * this.distance / this.element.clientHeight * this.settings.move.speed);
}
};
onTouchUp = event => {
this.state = Controls.STATES.NONE;
};
onTouchTiltDown = event => {
this.touchTiltStart = this.targetAngle;
this.state = Controls.STATES.ORBIT;
};
onTouchTiltMove = event => {
if (this.state !== Controls.STATES.ORBIT) return;
this.targetAngle = this.touchTiltStart - (event.deltaY / this.element.clientHeight * Math.PI);
};
onTouchTiltUp = event => {
this.state = Controls.STATES.NONE;
};
onTouchRotateDown = event => {
this.lastTouchRotation = event.rotation;
this.state = Controls.STATES.ORBIT;
};
onTouchRotateMove = event => {
if (this.state !== Controls.STATES.ORBIT) return;
let delta = event.rotation - this.lastTouchRotation;
this.lastTouchRotation = event.rotation;
if (delta > 180) delta -= 360;
if (delta < -180) delta += 360;
this.targetDirection += (delta * (Math.PI / 180)) * 1.4;
};
onTouchRotateUp = event => {
this.state = Controls.STATES.NONE;
};
onTouchZoomDown = event => {
this.touchZoomStart = this.targetDistance;
};
onTouchZoomMove = event => {
this.targetDistance = this.touchZoomStart / event.scale;
if (this.targetDistance < this.settings.zoom.min) this.targetDistance = this.settings.zoom.min;
if (this.targetDistance > this.settings.zoom.max) this.targetDistance = this.settings.zoom.max;
};
onKeyDown = event => {
this.keyStates[event.keyCode] = true;
};

View File

@ -23,6 +23,7 @@ module.exports = {
compress: true,
port: 8080,
hot: true,
host: "192.168.178.22"
},
plugins: [
new MiniCssExtractPlugin({