Skip to content

Commit

Permalink
Implement zoom in/out and horizontal scrolling using WASD (for right …
Browse files Browse the repository at this point in the history
…handed user)

and IKJL (for left handed user).

-- Added the mousemove event handler to capture x,y position on the canvas.
-- The x,y position will determine the start from where the zoom should trigger.
-- Recalculated the start and end position.
-- Call the viewRange method with the new coordinates on the canvas.
Note: I have tested this on chrome version (75.0.3770.100) and firefox (79.0 64 bit)

Signed-off-by: Ankush Tyagi <ankush.tyagi@ericsson.com>
  • Loading branch information
ankusht-work authored and MatthewKhouzam committed Sep 3, 2020
1 parent 35a4f32 commit d0e6597
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 33 deletions.
1 change: 1 addition & 0 deletions timeline-chart/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
},
"dependencies": {
"@types/lodash.throttle": "^4.1.4",
"keyboard-key": "1.1.0",
"lodash.throttle": "^4.1.1",
"pixi.js": "^5.0.0",
"rimraf": "latest"
Expand Down
27 changes: 14 additions & 13 deletions timeline-chart/src/layer/time-graph-chart-cursors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as PIXI from "pixi.js"
import * as keyboardKey from "keyboard-key"

import { TimeGraphCursor } from "../components/time-graph-cursor";
import { TimelineChart } from "../time-graph-model";
Expand Down Expand Up @@ -26,13 +27,13 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
this.stage.interactive = true;
document.addEventListener('keydown', (event: KeyboardEvent) => {
this.shiftKeyDown = event.shiftKey;
if (event.keyCode === 37) {
if (event.keyCode === keyboardKey.ArrowLeft) {
this.navigateOrSelectLeft();
} else if (event.keyCode === 39) {
} else if (event.keyCode === keyboardKey.ArrowRight) {
this.navigateOrSelectRight();
} else if(event.keyCode === 38){
} else if (event.keyCode === keyboardKey.ArrowUp) {
this.navigateUp();
} else if(event.keyCode === 40){
} else if (event.keyCode === keyboardKey.ArrowDown) {
this.navigateDown();
}
});
Expand Down Expand Up @@ -136,33 +137,33 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
}
}

protected navigateDown(){
protected navigateDown() {
const rows = this.chartLayer.getRowModels();
let selectedRow = this.rowController.selectedRow;
const idx = rows.findIndex(row => row === selectedRow);
if(idx < rows.length){
if (idx < rows.length) {
this.chartLayer.selectRow(rows[idx + 1]);
}
selectedRow = this.rowController.selectedRow;
const state = selectedRow.states.find(state => {
if(this.unitController.selectionRange){
if (this.unitController.selectionRange) {
return state.range.start <= this.unitController.selectionRange.start && state.range.end > this.unitController.selectionRange.start;
}
return false;
});
state && this.chartLayer.selectRowElement(state);
}

protected navigateUp(){
protected navigateUp() {
const rows = this.chartLayer.getRowModels();
let selectedRow = this.rowController.selectedRow;
const idx = rows.findIndex(row => row === selectedRow);
if(idx > 0){
if (idx > 0) {
this.chartLayer.selectRow(rows[idx - 1]);
}
selectedRow = this.rowController.selectedRow;
const state = selectedRow.states.find(state => {
if(this.unitController.selectionRange){
if (this.unitController.selectionRange) {
return state.range.start <= this.unitController.selectionRange.start && state.range.end > this.unitController.selectionRange.start;
}
return false;
Expand Down Expand Up @@ -200,7 +201,7 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
if (!this.firstCursor) {
this.firstCursor = new TimeGraphCursor(firstCursorOptions);
this.addChild(this.firstCursor);
}else{
} else {
this.firstCursor.update(firstCursorOptions);
}
if (secondCursorPosition !== firstCursorPosition) {
Expand All @@ -215,10 +216,10 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
if (!this.secondCursor) {
this.secondCursor = new TimeGraphCursor(secondCursorOptions);
this.addChild(this.secondCursor);
}else{
} else {
this.secondCursor.update(secondCursorOptions);
}
} else if(!!this.secondCursor){
} else if (!!this.secondCursor) {
this.removeChild(this.secondCursor);
delete this.secondCursor;
}
Expand Down
112 changes: 92 additions & 20 deletions timeline-chart/src/layer/time-graph-chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ export interface TimeGraphChartProviders {
rowStyleProvider?: (row: TimelineChart.TimeGraphRowModel) => TimeGraphRowStyle | undefined
}

export const keyBoardNavs: Record<string, Array<string>> = {
"zoomin": ['w', 'i'],
"zoomout": ['s', 'k'],
"panleft": ['a', 'j'],
"panright": ['d', 'l']
}

export type TimeGraphRowStyleHook = (row: TimelineChart.TimeGraphRowModel) => TimeGraphRowStyle | undefined;

export class TimeGraphChart extends TimeGraphChartLayer {
Expand Down Expand Up @@ -50,38 +57,103 @@ export class TimeGraphChart extends TimeGraphChartLayer {
protected afterAddToContainer() {
this.shiftKeyDown = false;
this.ctrlKeyDown = false;

let mousePositionX = 1;
let mousePositionY = 1;
const moveLeft = -1;
const moveRight = 1;
const horizontalDelta = 3;
let triggerKeyEvent = false;

const moveTimeGraph = (direction: number) => {
const moveFactor = horizontalDelta / this.stateController.zoomFactor;
let start = this.unitController.viewRange.start + (moveFactor * direction);
let end = this.unitController.viewRange.end + (moveFactor * direction);
if (start < 0) {
end = end - start;
start = 0;
}
if (end > this.unitController.absoluteRange) {
start = start - end + this.unitController.absoluteRange;
end = this.unitController.absoluteRange;
}
this.unitController.viewRange = {
start,
end
}
}
const adjustZoom = (zoomPosition: number, deltaLength: number) => {
let newViewRangeLength = this.unitController.viewRangeLength;
let xOffset = 0;

newViewRangeLength += deltaLength;
xOffset = ((zoomPosition / this.unitController.viewRangeLength) * deltaLength);
let start = this.unitController.viewRange.start - xOffset;
if (start < 0) {
start = 0;
}
let end = start + newViewRangeLength;
if (end > this.unitController.absoluteRange) {
end = this.unitController.absoluteRange;
}
this.unitController.viewRange = {
start,
end
}
};

document.addEventListener('mousemove', (event: MouseEvent) => {
mousePositionX = event.offsetX;
mousePositionY = event.offsetY;
})

document.addEventListener('keydown', (event: KeyboardEvent) => {
this.shiftKeyDown = event.shiftKey;
this.ctrlKeyDown = event.ctrlKey;
let keyPressed = event.key;

if (triggerKeyEvent) {
if (keyBoardNavs['zoomin'].indexOf(keyPressed) >= 0) {
const zoomPosition = (mousePositionX / this.stateController.zoomFactor);
const deltaLength = -(mousePositionY / this.stateController.zoomFactor);
adjustZoom(zoomPosition, deltaLength);

} else if (keyBoardNavs['zoomout'].indexOf(keyPressed) >= 0) {
const zoomPosition = (mousePositionX / this.stateController.zoomFactor);
const deltaLength = (mousePositionY / this.stateController.zoomFactor);
adjustZoom(zoomPosition, deltaLength);

} else if (keyBoardNavs['panleft'].indexOf(keyPressed) >= 0) {
moveTimeGraph(moveLeft);

} else if (keyBoardNavs['panright'].indexOf(keyPressed) >= 0) {
moveTimeGraph(moveRight);
}

event.preventDefault();
}

});

document.addEventListener('keyup', (event: KeyboardEvent) => {
this.shiftKeyDown = event.shiftKey;
this.ctrlKeyDown = event.ctrlKey;
});

this.stage.addListener('mouseover', (event: MouseEvent) => {
triggerKeyEvent = true;
});

this.stage.addListener('mouseout', (event: MouseEvent) => {
triggerKeyEvent = false;
});

const mw = (ev: WheelEvent) => {
if (this.ctrlKeyDown) {
let newViewRangeLength = this.unitController.viewRangeLength;
let xOffset = 0;
let moveX = false;
const zoomPosition = (ev.offsetX / this.stateController.zoomFactor);
const deltaLength = (ev.deltaY / this.stateController.zoomFactor);
newViewRangeLength += deltaLength;
xOffset = ((zoomPosition / this.unitController.viewRangeLength) * deltaLength);
let start = this.unitController.viewRange.start - xOffset;
if (start < 0) {
start = 0;
}
let end = start + newViewRangeLength;
if (end > this.unitController.absoluteRange) {
end = this.unitController.absoluteRange;
if (moveX) {
start = end - newViewRangeLength;
}
}
this.unitController.viewRange = {
start,
end
}
adjustZoom(zoomPosition, deltaLength);

} else if (this.shiftKeyDown) {
let newViewRangeLength = this.unitController.viewRangeLength;
let xOffset = 0;
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2955,6 +2955,11 @@ jsonparse@^1.2.0:
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=

keyboard-key@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/keyboard-key/-/keyboard-key-1.1.0.tgz#6f2e8e37fa11475bb1f1d65d5174f1b35653f5b7"
integrity sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ==

killable@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
Expand Down

0 comments on commit d0e6597

Please sign in to comment.