From d2409c3f603e7fc459acac8f3210ffddbcf375ba Mon Sep 17 00:00:00 2001 From: Jan Bicker Date: Thu, 20 Dec 2018 13:48:55 +0000 Subject: [PATCH] improvements --- example/src/index.ts | 122 +++++++++--------- example/src/test-data-provider.ts | 1 - .../src/components/time-graph-grid.ts | 22 ++-- .../src/layer/time-graph-chart-cursors.ts | 16 ++- timeline-chart/src/layer/time-graph-chart.ts | 61 +++++---- timeline-chart/src/layer/time-graph-layer.ts | 17 ++- 6 files changed, 122 insertions(+), 117 deletions(-) diff --git a/example/src/index.ts b/example/src/index.ts index 59c8aab..43b26f4 100644 --- a/example/src/index.ts +++ b/example/src/index.ts @@ -1,5 +1,5 @@ import { TimeGraphAxis } from "timeline-chart/lib/layer/time-graph-axis"; -import { TimeGraphChart, TimeGraphRowStyleHook } from "timeline-chart/lib/layer/time-graph-chart"; +import { TimeGraphChart } from "timeline-chart/lib/layer/time-graph-chart"; import { TimeGraphUnitController } from "timeline-chart/lib/time-graph-unit-controller"; import { TimeGraphNavigator } from "timeline-chart/lib/layer/time-graph-navigator"; import { TimeGraphContainer } from "timeline-chart/lib/time-graph-container"; @@ -11,7 +11,7 @@ import { TimeGraphRowElement, TimeGraphRowElementStyle } from "timeline-chart/li import { TestDataProvider } from "./test-data-provider"; import { TimeGraphChartGrid } from "timeline-chart/lib/layer/time-graph-chart-grid"; import { TimeGraphVerticalScrollbar } from "timeline-chart/lib/layer/time-graph-vertical-scrollbar"; -import { TimeGraphChartArrows } from "timeline-chart/lib/layer/time-graph-chart-arrows"; +// import { TimeGraphChartArrows } from "timeline-chart/lib/layer/time-graph-chart-arrows"; const styleConfig = { mainWidth: 1000, @@ -22,43 +22,6 @@ const styleConfig = { } const styleMap = new Map(); -const stateStyleHook = (model: TimeGraphRowElementModel) => { - const styles: TimeGraphRowElementStyle[] = [ - { - color: 0x11ad1b, - height: rowHeight * 0.8 - }, { - color: 0xbc2f00, - height: rowHeight * 0.7 - }, { - color: 0xccbf5d, - height: rowHeight * 0.6 - } - ]; - let style: TimeGraphRowElementStyle | undefined = styles[0]; - if (model.data && model.data.value) { - const val = model.data.value; - style = styleMap.get(val); - if (!style) { - style = styles[(styleMap.size % styles.length)]; - styleMap.set(val, style); - } - } - return { - color: style.color, - height: style.height, - borderWidth: model.selected ? 1 : 0 - }; -} - -const rowStyleHook: TimeGraphRowStyleHook = (row: TimeGraphRowModel) => { - return { - backgroundColor: 0xe0ddcf, - backgroundOpacity: row.selected ? 0.6 : 0, - lineColor: row.data && row.data.hasStates ? 0xdddddd : 0xaa4444, - lineThickness: row.data && row.data.hasStates ? 1 : 3 - } -} const container = document.getElementById('main'); if (!container) { @@ -110,11 +73,62 @@ const rowHeight = 16; const timeGraphChartGridLayer = new TimeGraphChartGrid('timeGraphGrid', rowHeight); timeGraphChartContainer.addLayer(timeGraphChartGridLayer); -const timeGraphChartLayer = new TimeGraphChart('timeGraphChart', rowHeight); +const timeGraphChartLayer = new TimeGraphChart('timeGraphChart', { + dataProvider: (range: TimeGraphRange, resolution: number) => { + timeGraph = testDataProvider.getData(range); + if (selectedElement) { + for (const row of timeGraph.rows) { + const selEl = row.states.find(el => el.id === selectedElement.id); + if (selEl) { + selEl.selected = true; + break; + } + } + } + return { + rows: timeGraph.rows, + range + }; + }, + rowElementStyleProvider: (model: TimeGraphRowElementModel) => { + const styles: TimeGraphRowElementStyle[] = [ + { + color: 0x11ad1b, + height: rowHeight * 0.8 + }, { + color: 0xbc2f00, + height: rowHeight * 0.7 + }, { + color: 0xccbf5d, + height: rowHeight * 0.6 + } + ]; + let style: TimeGraphRowElementStyle | undefined = styles[0]; + if (model.data && model.data.value) { + const val = model.data.value; + style = styleMap.get(val); + if (!style) { + style = styles[(styleMap.size % styles.length)]; + styleMap.set(val, style); + } + } + return { + color: style.color, + height: style.height, + borderWidth: model.selected ? 1 : 0 + }; + }, + rowStyleProvider: (row: TimeGraphRowModel) => { + return { + backgroundColor: 0xe0ddcf, + backgroundOpacity: row.selected ? 0.6 : 0, + lineColor: row.data && row.data.hasStates ? 0xdddddd : 0xaa4444, + lineThickness: row.data && row.data.hasStates ? 1 : 3 + } + } +}, rowHeight); timeGraphChartContainer.addLayer(timeGraphChartLayer); -timeGraphChartLayer.registerRowElementStyleHook(stateStyleHook); -timeGraphChartLayer.registerRowStyleHook(rowStyleHook); timeGraphChartLayer.registerRowElementMouseInteractions({ click: el => { console.log(el.model.label); @@ -131,27 +145,9 @@ timeGraphChartLayer.onSelectedRowElementChanged((model) => { } }) -timeGraphChartLayer.setRowModel(timeGraph.rows); -timeGraphChartLayer.registerPullHook((range: TimeGraphRange, resolution: number) => { - timeGraph = testDataProvider.getData(range); - if (selectedElement) { - for (const row of timeGraph.rows) { - const selEl = row.states.find(el => el.id === selectedElement.id); - if (selEl) { - selEl.selected = true; - break; - } - } - } - return { - rows: timeGraph.rows, - range - }; -}); - -const timeGraphChartArrows = new TimeGraphChartArrows('timeGraphChartArrows'); -timeGraphChartContainer.addLayer(timeGraphChartArrows); -timeGraphChartArrows.addArrows(timeGraph.arrows, rowHeight); +// const timeGraphChartArrows = new TimeGraphChartArrows('timeGraphChartArrows'); +// timeGraphChartContainer.addLayer(timeGraphChartArrows); +// timeGraphChartArrows.addArrows(timeGraph.arrows, rowHeight); const timeAxisCursors = new TimeGraphAxisCursors('timeGraphAxisCursors', { color: styleConfig.cursorColor }); timeGraphAxisContainer.addLayer(timeAxisCursors); diff --git a/example/src/test-data-provider.ts b/example/src/test-data-provider.ts index e30531a..e507538 100644 --- a/example/src/test-data-provider.ts +++ b/example/src/test-data-provider.ts @@ -200,7 +200,6 @@ export class TestDataProvider { }) let arrows: TimeGraphArrow[] = []; timeGraphArrows.forEach(arrow => { - console.log("in provider arrow", arrow, this.absoluteStart); arrows.push({ sourceId: arrow.sourceId, destinationId: arrow.destinationId, diff --git a/timeline-chart/src/components/time-graph-grid.ts b/timeline-chart/src/components/time-graph-grid.ts index 072ade1..7303c5e 100644 --- a/timeline-chart/src/components/time-graph-grid.ts +++ b/timeline-chart/src/components/time-graph-grid.ts @@ -18,16 +18,16 @@ export class TimeGraphGrid extends TimeGraphAxisScale { render(): void { this.renderVerticalLines(this.stateController.canvasDisplayHeight, 0xdddddd); - const rowNumber = Math.trunc(this.stateController.canvasDisplayHeight / this.rowHeight) + 2; - for (let i = 0; i < rowNumber; i++) { - this.hline({ - color: 0xdddddd, - position: { - x: this._options.position.x, - y: (i * this.rowHeight) - (this.rowHeight / 2) - }, - width: this._options.width - }); - } + // const rowNumber = Math.trunc(this.stateController.canvasDisplayHeight / this.rowHeight) + 2; + // for (let i = 0; i < rowNumber; i++) { + // this.hline({ + // color: 0xdddddd, + // position: { + // x: this._options.position.x, + // y: (i * this.rowHeight) - (this.rowHeight / 2) + // }, + // width: this._options.width + // }); + // } } } \ No newline at end of file diff --git a/timeline-chart/src/layer/time-graph-chart-cursors.ts b/timeline-chart/src/layer/time-graph-chart-cursors.ts index 2ac276f..346241c 100644 --- a/timeline-chart/src/layer/time-graph-chart-cursors.ts +++ b/timeline-chart/src/layer/time-graph-chart-cursors.ts @@ -19,6 +19,11 @@ export class TimeGraphChartCursors extends TimeGraphLayer { } } + protected updateScaleAndPosition() { + this.layer.position.x = -(this.unitController.viewRange.start * this.stateController.zoomFactor); + this.layer.scale.x = this.stateController.zoomFactor; + } + protected afterAddToContainer() { this.addBackground(); this.mouseIsDown = false; @@ -39,6 +44,7 @@ export class TimeGraphChartCursors extends TimeGraphLayer { this.mouseIsDown = true; const mouseX = event.data.global.x; const xpos = this.unitController.viewRange.start + (mouseX / this.stateController.zoomFactor); + console.log("SET CURSOR AT", xpos); if (this.shiftKeyDown) { const start = this.unitController.selectionRange ? this.unitController.selectionRange.start : 0; this.unitController.selectionRange = { @@ -69,8 +75,12 @@ export class TimeGraphChartCursors extends TimeGraphLayer { this.stage.on('mouseupoutside', (event: PIXI.interaction.InteractionEvent) => { this.mouseIsDown = false; }); + this.unitController.onViewRangeChanged(() => { + this.updateScaleAndPosition(); + }); + this.updateScaleAndPosition(); this.unitController.onSelectionRangeChange(() => this.update()); - this.unitController.onViewRangeChanged(() => this.update()); + // this.unitController.onViewRangeChanged(() => this.update()); } protected maybeCenterCursor() { @@ -154,8 +164,8 @@ export class TimeGraphChartCursors extends TimeGraphLayer { this.removeChildren(); this.addBackground(); if (this.unitController.selectionRange) { - const firstCursorPosition = (this.unitController.selectionRange.start - this.unitController.viewRange.start) * this.stateController.zoomFactor; - const secondCursorPosition = (this.unitController.selectionRange.end - this.unitController.viewRange.start) * this.stateController.zoomFactor; + const firstCursorPosition = this.unitController.selectionRange.start;//(this.unitController.selectionRange.start - this.unitController.viewRange.start) * this.stateController.zoomFactor; + const secondCursorPosition = this.unitController.selectionRange.end;//(this.unitController.selectionRange.end - this.unitController.viewRange.start) * this.stateController.zoomFactor; const firstCursorOptions = { color: this.color, height: this.stateController.canvasDisplayHeight, diff --git a/timeline-chart/src/layer/time-graph-chart.ts b/timeline-chart/src/layer/time-graph-chart.ts index b2b30ba..426e0e4 100644 --- a/timeline-chart/src/layer/time-graph-chart.ts +++ b/timeline-chart/src/layer/time-graph-chart.ts @@ -13,13 +13,17 @@ export interface TimeGraphRowElementMouseInteractions { mouseup?: (el: TimeGraphRowElement, ev: PIXI.interaction.InteractionEvent) => void } +export interface TimeGraphChartProviders { + dataProvider: (range: TimeGraphRange, resolution: number) => { rows: TimeGraphRowModel[], range: TimeGraphRange } + rowElementStyleProvider?: (el: TimeGraphRowElementModel) => TimeGraphRowElementStyle | undefined + rowStyleProvider?: (row: TimeGraphRowModel) => TimeGraphRowStyle | undefined +} + export type TimeGraphRowStyleHook = (row: TimeGraphRowModel) => TimeGraphRowStyle | undefined; export class TimeGraphChart extends TimeGraphLayer { protected rows: TimeGraphRowModel[]; - protected rowElementStyleHook: (el: TimeGraphRowElementModel) => TimeGraphRowElementStyle | undefined; - protected rowStyleHook: (row: TimeGraphRowModel) => TimeGraphRowStyle | undefined; protected rowElementMouseInteractions: TimeGraphRowElementMouseInteractions; protected selectedElementModel: TimeGraphRowElementModel; protected selectedElementChangedHandler: ((el: TimeGraphRowElementModel) => void)[] = []; @@ -27,19 +31,13 @@ export class TimeGraphChart extends TimeGraphLayer { protected selectedRowChangedHandler: ((el: TimeGraphRowModel) => void)[] = []; protected verticalPositionChangedHandler: ((verticalChartPosition: number) => void)[] = []; protected totalHeight: number; - protected throttledUpdate: () => void; - protected pullHook: (range: TimeGraphRange, resolution: number) => {rows: TimeGraphRowModel[], range: TimeGraphRange}; - constructor(id: string, protected rowHeight: number) { + constructor(id: string, protected providers: TimeGraphChartProviders, protected rowHeight: number) { super(id); } protected afterAddToContainer() { - this.unitController.onViewRangeChanged(() => { - this.stage.position.x = -(this.unitController.viewRange.start * this.stateController.zoomFactor); - this.stage.scale.x = this.stateController.zoomFactor; - this.update(); - }); + this.onCanvasEvent('mousewheel', (ev: WheelEvent) => { const shiftStep = ev.deltaY; let verticalOffset = this.stateController.positionOffset.y + shiftStep; @@ -50,13 +48,28 @@ export class TimeGraphChart extends TimeGraphLayer { verticalOffset = this.totalHeight - this.stateController.canvasDisplayHeight; } this.stateController.positionOffset.y = verticalOffset; - this.stage.position.y = -verticalOffset; + this.layer.position.y = -verticalOffset; this.handleVerticalPositionChange(); return false; }); + + this.unitController.onViewRangeChanged(() => { + this.updateScaleAndPosition(); + }); + this.updateScaleAndPosition(); + + // lets fetch everything + const rowData = this.providers.dataProvider({ start: 0, end: this.unitController.absoluteRange }, 1); + this.setRowModel(rowData.rows); + this.addRows(this.rows, this.rowHeight); } - update() {} + update() { } + + protected updateScaleAndPosition() { + this.layer.position.x = -(this.unitController.viewRange.start * this.stateController.zoomFactor); + this.layer.scale.x = this.stateController.zoomFactor; + } protected handleVerticalPositionChange() { this.verticalPositionChangedHandler.forEach(handler => handler(this.stateController.positionOffset.y)); @@ -73,7 +86,7 @@ export class TimeGraphChart extends TimeGraphLayer { protected addRow(row: TimeGraphRowModel, height: number, rowIndex: number) { const rowId = 'row_' + rowIndex; const length = row.range.end - row.range.start; - const rowStyle = this.rowStyleHook ? this.rowStyleHook(row) : undefined; + const rowStyle = this.providers.rowStyleProvider ? this.providers.rowStyleProvider(row) : undefined; const rowComponent = new TimeGraphRow(rowId, { position: { x: row.range.start, @@ -94,7 +107,7 @@ export class TimeGraphChart extends TimeGraphLayer { start, end }; - const elementStyle = this.rowElementStyleHook ? this.rowElementStyleHook(rowElementModel) : undefined; + const elementStyle = this.providers.rowElementStyleProvider ? this.providers.rowElementStyleProvider(rowElementModel) : undefined; const el = new TimeGraphRowElement(rowElementModel.id, rowElementModel, range, rowComponent, elementStyle); this.addElementInteractions(el); this.addChild(el); @@ -142,20 +155,8 @@ export class TimeGraphChart extends TimeGraphLayer { }); } - registerPullHook(pullHook: (range: TimeGraphRange, resolution: number) => {rows: TimeGraphRowModel[], range: TimeGraphRange}){ - this.pullHook = pullHook; - // lets fetch everything - const rowData = this.pullHook({ start:0, end: this.unitController.absoluteRange}, 1); - this.setRowModel(rowData.rows); - this.addRows(rowData.rows, this.rowHeight); - } - - registerRowStyleHook(styleHook: TimeGraphRowStyleHook) { - this.rowStyleHook = styleHook; - } - - registerRowElementStyleHook(styleHook: (el: TimeGraphRowElementModel) => TimeGraphRowElementStyle | undefined) { - this.rowElementStyleHook = styleHook; + protected setRowModel(rows: TimeGraphRowModel[]) { + this.rows = rows; } registerRowElementMouseInteractions(interactions: TimeGraphRowElementMouseInteractions) { @@ -215,10 +216,6 @@ export class TimeGraphChart extends TimeGraphLayer { this.handleSelectedRowElementChange(); } - setRowModel(rows: TimeGraphRowModel[]) { - this.rows = rows; - } - setVerticalPositionOffset(ypos: number) { this.stateController.positionOffset.y = ypos; } diff --git a/timeline-chart/src/layer/time-graph-layer.ts b/timeline-chart/src/layer/time-graph-layer.ts index 0b7864f..150ddf3 100644 --- a/timeline-chart/src/layer/time-graph-layer.ts +++ b/timeline-chart/src/layer/time-graph-layer.ts @@ -8,37 +8,40 @@ export abstract class TimeGraphLayer { protected unitController: TimeGraphUnitController; protected children: TimeGraphComponent[]; protected stage: PIXI.Container; + protected layer: PIXI.Container; constructor(protected id: string) { this.children = []; + this.layer = new PIXI.Container; } protected addChild(child: TimeGraphComponent) { - if(!this.stage){ - throw("Layers must be added to a container before components can be added."); + if (!this.canvas) { + throw ("Layers must be added to a container before components can be added."); } child.render(); - this.stage.addChild(child.displayObject); + this.layer.addChild(child.displayObject); this.children.push(child); } /** This method is called by the container this layer is added to. */ - initializeLayer(canvas:HTMLCanvasElement, stage: PIXI.Container, stateController: TimeGraphStateController, unitController: TimeGraphUnitController) { + initializeLayer(canvas: HTMLCanvasElement, stage: PIXI.Container, stateController: TimeGraphStateController, unitController: TimeGraphUnitController) { this.canvas = canvas; - this.stage = stage; this.stateController = stateController; this.unitController = unitController; + this.stage = stage; + stage.addChild(this.layer); this.afterAddToContainer(); } - protected onCanvasEvent(type: string, handler: (event:Event)=>void){ + protected onCanvasEvent(type: string, handler: (event: Event) => void) { this.canvas.addEventListener(type, handler); } protected removeChildren() { - this.children.forEach(child => this.stage.removeChild(child.displayObject)); + this.children.forEach(child => this.layer.removeChild(child.displayObject)); this.children = []; }