Compare commits
No commits in common. "4bb91d664d71a10c6df626d3383ba5d7160b77fe" and "b76adc69414f9eb7e0a881d6b033dd2f6fd8bac6" have entirely different histories.
4bb91d664d
...
b76adc6941
@ -2,12 +2,11 @@ export const DISPLAY_OBJECTS_INFO = false;
|
|||||||
export const DISPLAY_CURSOR_INFO = false;
|
export const DISPLAY_CURSOR_INFO = false;
|
||||||
export const DISPLAY_CANVAS_SIZE = false;
|
export const DISPLAY_CANVAS_SIZE = false;
|
||||||
export const DISPLAY_CURRENT_SCALE = true;
|
export const DISPLAY_CURRENT_SCALE = true;
|
||||||
export const DISPLAY_CURRENT_MODE = false;
|
|
||||||
export const DISPLAY_VELOCITY_VECTORS = true;
|
export const DISPLAY_VELOCITY_VECTORS = true;
|
||||||
|
|
||||||
export const MASS_CREATION_RATE = 0.001;
|
export const MASS_CREATION_RATE = 0.001;
|
||||||
export const POINTER_HISTORY_SIZE = 15;
|
export const POINTER_HISTORY_SIZE = 10;
|
||||||
export const VELOCITY_VECTOR_SCALE = 0.1;
|
export const VELOCITY_VECTOR_SCALE = 0.2;
|
||||||
export const VELOCITY_VECTOR_COLOR = 'rgb(150, 150, 150)'; // optionally set to 'object color'
|
export const VELOCITY_VECTOR_COLOR = 'rgb(150, 150, 150)'; // optionally set to 'object color'
|
||||||
export const VELOCITY_VECTOR_WIDTH = 1.5;
|
export const VELOCITY_VECTOR_WIDTH = 1.5;
|
||||||
export const VELOCITY_VECTOR_ARROWHEAD = true;
|
export const VELOCITY_VECTOR_ARROWHEAD = true;
|
||||||
@ -21,8 +20,6 @@ export const ZOOM_IN_FACTOR = 1;
|
|||||||
export const ZOOM_OUT_FACTOR = -1;
|
export const ZOOM_OUT_FACTOR = -1;
|
||||||
export const SCALE_POWER_MAX = 8;
|
export const SCALE_POWER_MAX = 8;
|
||||||
export const SCALE_POWER_MIN = -8;
|
export const SCALE_POWER_MIN = -8;
|
||||||
export const PAN_VELOCITY_SCALE_FACTOR = 1E-3;
|
|
||||||
export const PAN_DRAG = 1;
|
|
||||||
|
|
||||||
export const DRAGGABLE_ELEMENT_CLASSNAME = 'lhg-draggable-element';
|
export const DRAGGABLE_ELEMENT_CLASSNAME = 'lhg-draggable-element';
|
||||||
|
|
||||||
|
|||||||
@ -60,6 +60,7 @@ export class Objects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
handlePointerDown({x, y}) {
|
handlePointerDown({x, y}) {
|
||||||
// If pointer is touching an object, select the object
|
// If pointer is touching an object, select the object
|
||||||
const touchingObject = this.objectAtLocation(x, y);
|
const touchingObject = this.objectAtLocation(x, y);
|
||||||
|
|||||||
76
pointer.js
76
pointer.js
@ -6,7 +6,6 @@ import {
|
|||||||
DRAGGABLE_ELEMENT_CLASSNAME,
|
DRAGGABLE_ELEMENT_CLASSNAME,
|
||||||
MODE_MASS_GENERATION,
|
MODE_MASS_GENERATION,
|
||||||
MODE_PAN_VIEW,
|
MODE_PAN_VIEW,
|
||||||
PAN_VELOCITY_SCALE_FACTOR,
|
|
||||||
} from './config.js';
|
} from './config.js';
|
||||||
|
|
||||||
function dispatchEvent(target, eventType, data) {
|
function dispatchEvent(target, eventType, data) {
|
||||||
@ -20,7 +19,6 @@ export class Pointer {
|
|||||||
pointerHistory = [];
|
pointerHistory = [];
|
||||||
draggingElement = undefined;
|
draggingElement = undefined;
|
||||||
panning = undefined;
|
panning = undefined;
|
||||||
suppressClick = false;
|
|
||||||
|
|
||||||
constructor(sim) {
|
constructor(sim) {
|
||||||
this.sim = sim;
|
this.sim = sim;
|
||||||
@ -32,26 +30,26 @@ export class Pointer {
|
|||||||
if (DISPLAY_CURSOR_INFO) {
|
if (DISPLAY_CURSOR_INFO) {
|
||||||
this.sim.info['pointermove'] = [`${e.clientX}, `, `${e.clientY}`];
|
this.sim.info['pointermove'] = [`${e.clientX}, `, `${e.clientY}`];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.draggingElement) {
|
if (this.draggingElement) {
|
||||||
|
// e.preventDefault();
|
||||||
this.draggingElement.dragging.pointerEnd = {
|
this.draggingElement.dragging.pointerEnd = {
|
||||||
x: e.clientX,
|
x: e.clientX,
|
||||||
y: e.clientY,
|
y: e.clientY,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// const {x, y} = this.sim.screenToSim(e.clientX, e.clientY);
|
const {x, y} = this.sim.screenToSim(e.clientX, e.clientY);
|
||||||
this.handlePointerMove({x: e.clientX, y: e.clientY});
|
this.handlePointerMove({x, y});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
el.addEventListener('pointerdown', e => {
|
el.addEventListener('pointerdown', e => {
|
||||||
// If this is a child of a draggable element, handle dragging
|
// e.preventDefault();
|
||||||
let target = e.target;
|
let target = e.target;
|
||||||
while (target && !target.classList.contains(DRAGGABLE_ELEMENT_CLASSNAME)) {
|
while (target && !target.classList.contains(DRAGGABLE_ELEMENT_CLASSNAME)) {
|
||||||
target = target.parentElement;
|
target = target.parentElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target?.classList.contains(DRAGGABLE_ELEMENT_CLASSNAME)) {
|
if (target?.classList.contains(DRAGGABLE_ELEMENT_CLASSNAME)) {
|
||||||
|
// e.preventDefault();
|
||||||
this.draggingElement = target;
|
this.draggingElement = target;
|
||||||
this.draggingElement.dragging = {
|
this.draggingElement.dragging = {
|
||||||
elementStart: {
|
elementStart: {
|
||||||
@ -73,7 +71,7 @@ export class Pointer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
el.addEventListener('pointerup', e => {
|
el.addEventListener('pointerup', e => {
|
||||||
this.clearPointerHistory();
|
// e.preventDefault();
|
||||||
if (this.draggingElement) {
|
if (this.draggingElement) {
|
||||||
this.draggingElement.dragging = undefined;
|
this.draggingElement.dragging = undefined;
|
||||||
this.draggingElement = undefined;
|
this.draggingElement = undefined;
|
||||||
@ -83,9 +81,16 @@ export class Pointer {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
el.addEventListener('click', e => {
|
||||||
|
// e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
// Monitor wheel events
|
// Monitor wheel events
|
||||||
el.addEventListener('wheel', e => {
|
el.addEventListener('wheel', e => {
|
||||||
|
// e.preventDefault();
|
||||||
|
// Wheel scroll down => positive deltaY => ZOOM IN
|
||||||
const factor = e.deltaY > 0 ? ZOOM_IN_FACTOR : ZOOM_OUT_FACTOR;
|
const factor = e.deltaY > 0 ? ZOOM_IN_FACTOR : ZOOM_OUT_FACTOR;
|
||||||
|
|
||||||
this.sim.scheduleZoom({x: e.clientX, y: e.clientY}, factor);
|
this.sim.scheduleZoom({x: e.clientX, y: e.clientY}, factor);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -119,73 +124,34 @@ export class Pointer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handlePointerDown({x, y}) {
|
handlePointerDown({x, y}) {
|
||||||
|
this.clearPointerHistory();
|
||||||
|
this.updatePointer({x, y});
|
||||||
|
|
||||||
if (this.sim.isCurrentMode(MODE_MASS_GENERATION)) {
|
if (this.sim.isCurrentMode(MODE_MASS_GENERATION)) {
|
||||||
this.sim.objects.handlePointerDown({x, y});
|
this.sim.objects.handlePointerDown({x, y});
|
||||||
} else if (this.sim.isCurrentMode(MODE_PAN_VIEW)) {
|
} else if (this.sim.isCurrentMode(MODE_PAN_VIEW)) {
|
||||||
this.panning = {
|
this.panning = {
|
||||||
gathering: true,
|
|
||||||
viewOriginStart: this.sim.display.viewOrigin,
|
|
||||||
pointerStart: {x, y},
|
pointerStart: {x, y},
|
||||||
pointerCurrent: {x, y},
|
pointerCurrent: {x, y},
|
||||||
velocity: this.getPointerVelocity(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePointerUp({x, y}) {
|
handlePointerUp({x, y}) {
|
||||||
this.clearPointerHistory();
|
this.panning = undefined;
|
||||||
if (this.sim.isCurrentMode(MODE_MASS_GENERATION)) {
|
if (this.sim.isCurrentMode(MODE_MASS_GENERATION)) {
|
||||||
this.sim.objects.handlePointerUp({x, y});
|
this.sim.objects.handlePointerUp({x, y});
|
||||||
} else if (this.sim.isCurrentMode(MODE_PAN_VIEW)) {
|
|
||||||
if (this.panning?.gathering) {
|
|
||||||
this.panning.gathering = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle cursor (mouse or touch) movement
|
// Handle cursor (mouse or touch) movement
|
||||||
// TODO: If e.touches.length > 1, user may be engaging pinch to zoom
|
// TODO: If e.touches.length > 1, user may be engaging pinch to zoom
|
||||||
handlePointerMove({x: clientX, y: clientY}) {
|
handlePointerMove({x, y}) {
|
||||||
|
this.updatePointer({x, y});
|
||||||
|
const {x: vx, y: vy} = this.getPointerVelocity();
|
||||||
|
|
||||||
if (this.sim.isCurrentMode(MODE_MASS_GENERATION)) {
|
if (this.sim.isCurrentMode(MODE_MASS_GENERATION)) {
|
||||||
this.updatePointer({ x: clientX, y: clientY });
|
|
||||||
const {x, y} = this.sim.screenToSim(clientX, clientY);
|
|
||||||
const velocity = this.getPointerVelocity();
|
|
||||||
// Convert pointer velocity to sim internal scale
|
|
||||||
const vx = velocity.x / this.sim.display.scale;
|
|
||||||
const vy = velocity.y / this.sim.display.scale;
|
|
||||||
this.sim.objects.handlePointerMove({x, y, vx, vy});
|
this.sim.objects.handlePointerMove({x, y, vx, vy});
|
||||||
|
|
||||||
} else if (this.sim.isCurrentMode(MODE_PAN_VIEW)) {
|
|
||||||
if (this.panning?.gathering) {
|
|
||||||
this.updatePointer({ x: clientX, y: clientY });
|
|
||||||
this.panning.pointerCurrent = {x: clientX, y: clientY};
|
|
||||||
this.panning.velocity = this.getPointerVelocity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
computeFrame(elapsedTime) {
|
|
||||||
// Add another entry for the current pointer position
|
|
||||||
if (this.pointerHistory?.length) {
|
|
||||||
const currentPointer = this.pointerHistory[this.pointerHistory.length - 1];
|
|
||||||
this.updatePointer(currentPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply update to viewOrigin based on panning
|
|
||||||
if (!this.sim.isCurrentMode(MODE_PAN_VIEW)) {
|
|
||||||
this.panning = undefined;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.panning) {
|
|
||||||
const {pointerStart, pointerCurrent, viewOriginStart, velocity} = this.sim.pointer.panning;
|
|
||||||
// Convert pointer velocity to sim internal scale
|
|
||||||
const vx = velocity.x / this.sim.display.scale;
|
|
||||||
const vy = velocity.y / this.sim.display.scale;
|
|
||||||
this.panning.viewOriginStart = this.sim.display.viewOrigin;
|
|
||||||
this.panning.pointerStart = pointerCurrent;
|
|
||||||
// const speed = Math.sqrt(velocity.x ** 2 + velocity.y ** 2);
|
|
||||||
this.sim.display.viewOrigin.x -= vx * elapsedTime * PAN_VELOCITY_SCALE_FACTOR;
|
|
||||||
this.sim.display.viewOrigin.y -= vy * elapsedTime * PAN_VELOCITY_SCALE_FACTOR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
simulator.js
10
simulator.js
@ -10,7 +10,6 @@ import {
|
|||||||
SCALE_POWER_MAX,
|
SCALE_POWER_MAX,
|
||||||
SCALE_POWER_MIN,
|
SCALE_POWER_MIN,
|
||||||
DISPLAY_CURRENT_SCALE,
|
DISPLAY_CURRENT_SCALE,
|
||||||
DISPLAY_CURRENT_MODE,
|
|
||||||
} from './config.js';
|
} from './config.js';
|
||||||
|
|
||||||
export class Sim {
|
export class Sim {
|
||||||
@ -64,12 +63,6 @@ export class Sim {
|
|||||||
// compute coordinates of new view frame
|
// compute coordinates of new view frame
|
||||||
this.display.viewOrigin.x = x - this.display.width / 2;
|
this.display.viewOrigin.x = x - this.display.width / 2;
|
||||||
this.display.viewOrigin.y = y - this.display.height / 2;
|
this.display.viewOrigin.y = y - this.display.height / 2;
|
||||||
|
|
||||||
this.pointer.clearPointerHistory();
|
|
||||||
if (this.pointer.panning) {
|
|
||||||
this.pointer.panning = undefined;
|
|
||||||
// TODO: Maybe rescale velocity
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform display coordinates to simulator coordinates using scale and viewOrigin
|
// Transform display coordinates to simulator coordinates using scale and viewOrigin
|
||||||
@ -90,9 +83,7 @@ export class Sim {
|
|||||||
const elapsedTime = currentTime - this.time;
|
const elapsedTime = currentTime - this.time;
|
||||||
this.time = currentTime;
|
this.time = currentTime;
|
||||||
|
|
||||||
if (DISPLAY_CURRENT_MODE) {
|
|
||||||
this.info['Mode'] = this.getCurrentMode();
|
this.info['Mode'] = this.getCurrentMode();
|
||||||
}
|
|
||||||
|
|
||||||
if (this.nextZoom) {
|
if (this.nextZoom) {
|
||||||
this.zoom(this.nextZoom);
|
this.zoom(this.nextZoom);
|
||||||
@ -104,7 +95,6 @@ export class Sim {
|
|||||||
this.info['Scale'] = this.display.scalePower >= 0 ? `${scale}` : `1/${scale}`;
|
this.info['Scale'] = this.display.scalePower >= 0 ? `${scale}` : `1/${scale}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pointer.computeFrame(elapsedTime);
|
|
||||||
this.objects.computeFrame(elapsedTime);
|
this.objects.computeFrame(elapsedTime);
|
||||||
|
|
||||||
this.overlay.updateDraggable();
|
this.overlay.updateDraggable();
|
||||||
|
|||||||
@ -59,8 +59,7 @@ export class ModeSwitch extends Tool {
|
|||||||
for (let button of this.buttons) {
|
for (let button of this.buttons) {
|
||||||
button.style.opacity = button.modeID === this.currentMode ? '50%' : '100%';
|
button.style.opacity = button.modeID === this.currentMode ? '50%' : '100%';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
// TODO: on enter / on leave mode / some sort of callbacks on mode transitions
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@ export class Zoom extends Tool {
|
|||||||
// Aim at center of view
|
// Aim at center of view
|
||||||
const x = this.sim.display.width * this.sim.display.scale / 2;
|
const x = this.sim.display.width * this.sim.display.scale / 2;
|
||||||
const y = this.sim.display.height * this.sim.display.scale / 2;
|
const y = this.sim.display.height * this.sim.display.scale / 2;
|
||||||
|
console.log(`zoom out, x`, x, 'y', y);
|
||||||
this.sim.scheduleZoom({x, y}, ZOOM_OUT_FACTOR);
|
this.sim.scheduleZoom({x, y}, ZOOM_OUT_FACTOR);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -35,6 +36,7 @@ export class Zoom extends Tool {
|
|||||||
// Aim at center of view
|
// Aim at center of view
|
||||||
const x = this.sim.display.width * this.sim.display.scale / 2;
|
const x = this.sim.display.width * this.sim.display.scale / 2;
|
||||||
const y = this.sim.display.height * this.sim.display.scale / 2;
|
const y = this.sim.display.height * this.sim.display.scale / 2;
|
||||||
|
console.log(`zoom in, x`, x, 'y', y);
|
||||||
this.sim.scheduleZoom({x, y}, ZOOM_IN_FACTOR);
|
this.sim.scheduleZoom({x, y}, ZOOM_IN_FACTOR);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user