|
|
@ -1,5 +1,5 @@ |
|
|
|
import VueChartwerkPodMixin from './VueChartwerkPodMixin'; |
|
|
|
import VueChartwerkPodMixin from './VueChartwerkPodMixin'; |
|
|
|
import { PodState } from './state'; |
|
|
|
import { PodState } from './models/state'; |
|
|
|
import { Grid } from './components/grid'; |
|
|
|
import { Grid } from './components/grid'; |
|
|
|
|
|
|
|
|
|
|
|
import { CoreSeries } from './models/series'; |
|
|
|
import { CoreSeries } from './models/series'; |
|
|
@ -165,8 +165,7 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
height: this.height, |
|
|
|
height: this.height, |
|
|
|
width: this.width, |
|
|
|
width: this.width, |
|
|
|
} |
|
|
|
} |
|
|
|
// TODO: use instanses instead of oblects
|
|
|
|
this.state = new PodState(boxPararms, this.coreSeries, this.coreOptions); |
|
|
|
this.state = new PodState(boxPararms, this.coreSeries.visibleSeries, this.coreOptions.allOptions); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected initComponents(): void { |
|
|
|
protected initComponents(): void { |
|
|
@ -232,7 +231,7 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
.attr('id', 'x-axis-container') |
|
|
|
.attr('id', 'x-axis-container') |
|
|
|
.style('pointer-events', 'none') |
|
|
|
.style('pointer-events', 'none') |
|
|
|
.call( |
|
|
|
.call( |
|
|
|
d3.axisBottom(this.xScale) |
|
|
|
d3.axisBottom(this.state.xScale) |
|
|
|
.ticks(this.coreOptions.axis.x.ticksCount) |
|
|
|
.ticks(this.coreOptions.axis.x.ticksCount) |
|
|
|
.tickSize(DEFAULT_TICK_SIZE) |
|
|
|
.tickSize(DEFAULT_TICK_SIZE) |
|
|
|
.tickFormat(this.getAxisTicksFormatter(this.coreOptions.axis.x)) |
|
|
|
.tickFormat(this.getAxisTicksFormatter(this.coreOptions.axis.x)) |
|
|
@ -251,7 +250,7 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
.style('pointer-events', 'none') |
|
|
|
.style('pointer-events', 'none') |
|
|
|
// TODO: number of ticks shouldn't be hardcoded
|
|
|
|
// TODO: number of ticks shouldn't be hardcoded
|
|
|
|
.call( |
|
|
|
.call( |
|
|
|
d3.axisLeft(this.yScale) |
|
|
|
d3.axisLeft(this.state.yScale) |
|
|
|
.ticks(this.coreOptions.axis.y.ticksCount) |
|
|
|
.ticks(this.coreOptions.axis.y.ticksCount) |
|
|
|
.tickSize(DEFAULT_TICK_SIZE) |
|
|
|
.tickSize(DEFAULT_TICK_SIZE) |
|
|
|
.tickFormat(this.getAxisTicksFormatter(this.coreOptions.axis.y)) |
|
|
|
.tickFormat(this.getAxisTicksFormatter(this.coreOptions.axis.y)) |
|
|
@ -277,7 +276,7 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
.style('pointer-events', 'none') |
|
|
|
.style('pointer-events', 'none') |
|
|
|
// TODO: number of ticks shouldn't be hardcoded
|
|
|
|
// TODO: number of ticks shouldn't be hardcoded
|
|
|
|
.call( |
|
|
|
.call( |
|
|
|
d3.axisRight(this.y1Scale) |
|
|
|
d3.axisRight(this.state.y1Scale) |
|
|
|
.ticks(DEFAULT_TICK_COUNT) |
|
|
|
.ticks(DEFAULT_TICK_COUNT) |
|
|
|
.tickSize(DEFAULT_TICK_SIZE) |
|
|
|
.tickSize(DEFAULT_TICK_SIZE) |
|
|
|
.tickFormat(this.getAxisTicksFormatter(this.coreOptions.axis.y1)) |
|
|
|
.tickFormat(this.getAxisTicksFormatter(this.coreOptions.axis.y1)) |
|
|
@ -416,10 +415,10 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
.attr('fill', 'none'); |
|
|
|
.attr('fill', 'none'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.initScaleX = this.xScale.copy(); |
|
|
|
this.initScaleX = this.state.xScale.copy(); |
|
|
|
this.initScaleY = this.yScale.copy(); |
|
|
|
this.initScaleY = this.state.yScale.copy(); |
|
|
|
if(this.coreOptions.axis.y1.isActive) { |
|
|
|
if(this.coreOptions.axis.y1.isActive) { |
|
|
|
this.initScaleY1 = this.y1Scale.copy(); |
|
|
|
this.initScaleY1 = this.state.y1Scale.copy(); |
|
|
|
} |
|
|
|
} |
|
|
|
this.pan = d3.zoom() |
|
|
|
this.pan = d3.zoom() |
|
|
|
.on('zoom', this.onPanning.bind(this)) |
|
|
|
.on('zoom', this.onPanning.bind(this)) |
|
|
@ -611,18 +610,18 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
rescaleAxisX(transformX: number): void { |
|
|
|
rescaleAxisX(transformX: number): void { |
|
|
|
this.state.transform = { x: transformX }; |
|
|
|
this.state.transform = { x: transformX }; |
|
|
|
const rescaleX = d3.event.transform.rescaleX(this.initScaleX); |
|
|
|
const rescaleX = d3.event.transform.rescaleX(this.initScaleX); |
|
|
|
this.xAxisElement.call(d3.axisBottom(this.xScale).scale(rescaleX)); |
|
|
|
this.xAxisElement.call(d3.axisBottom(this.state.xScale).scale(rescaleX)); |
|
|
|
this.state.xValueRange = [rescaleX.invert(0), rescaleX.invert(this.width)]; |
|
|
|
this.state.xValueRange = [rescaleX.invert(0), rescaleX.invert(this.width)]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
rescaleAxisY(transformY: number): void { |
|
|
|
rescaleAxisY(transformY: number): void { |
|
|
|
this.state.transform = { y: transformY }; |
|
|
|
this.state.transform = { y: transformY }; |
|
|
|
const rescaleY = d3.event.transform.rescaleY(this.initScaleY); |
|
|
|
const rescaleY = d3.event.transform.rescaleY(this.initScaleY); |
|
|
|
this.yAxisElement.call(d3.axisLeft(this.yScale).scale(rescaleY)); |
|
|
|
this.yAxisElement.call(d3.axisLeft(this.state.yScale).scale(rescaleY)); |
|
|
|
this.state.yValueRange = [rescaleY.invert(0), rescaleY.invert(this.height)]; |
|
|
|
this.state.yValueRange = [rescaleY.invert(0), rescaleY.invert(this.height)]; |
|
|
|
if(this.y1AxisElement) { |
|
|
|
if(this.y1AxisElement) { |
|
|
|
const rescaleY1 = d3.event.transform.rescaleY(this.initScaleY1); |
|
|
|
const rescaleY1 = d3.event.transform.rescaleY(this.initScaleY1); |
|
|
|
this.y1AxisElement.call(d3.axisLeft(this.y1Scale).scale(rescaleY1)); |
|
|
|
this.y1AxisElement.call(d3.axisLeft(this.state.y1Scale).scale(rescaleY1)); |
|
|
|
this.state.y1ValueRange = [rescaleY1.invert(0), rescaleY1.invert(this.height)]; |
|
|
|
this.state.y1ValueRange = [rescaleY1.invert(0), rescaleY1.invert(this.height)]; |
|
|
|
// TODO: y1 axis jumps on panning
|
|
|
|
// TODO: y1 axis jumps on panning
|
|
|
|
this.y1AxisElement.selectAll('line').attr('x2', 2); |
|
|
|
this.y1AxisElement.selectAll('line').attr('x2', 2); |
|
|
@ -639,7 +638,7 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
case ScrollPanOrientation.HORIZONTAL: |
|
|
|
case ScrollPanOrientation.HORIZONTAL: |
|
|
|
// @ts-ignore
|
|
|
|
// @ts-ignore
|
|
|
|
const signX = Math.sign(event.transform.x); |
|
|
|
const signX = Math.sign(event.transform.x); |
|
|
|
const transformX = this.absXScale.invert(Math.abs(transformStep)); |
|
|
|
const transformX = this.state.absXScale.invert(Math.abs(transformStep)); |
|
|
|
let rangeX = this.state.xValueRange; |
|
|
|
let rangeX = this.state.xValueRange; |
|
|
|
this.state.xValueRange = [rangeX[0] + signX * transformX, rangeX[1] + signX * transformX]; |
|
|
|
this.state.xValueRange = [rangeX[0] + signX * transformX, rangeX[1] + signX * transformX]; |
|
|
|
const translateX = this.state.transform.x + signX * transformStep; |
|
|
|
const translateX = this.state.transform.x + signX * transformStep; |
|
|
@ -652,7 +651,7 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
signY = -signY; |
|
|
|
signY = -signY; |
|
|
|
} |
|
|
|
} |
|
|
|
let rangeY = this.state.yValueRange; |
|
|
|
let rangeY = this.state.yValueRange; |
|
|
|
const transformY = this.absYScale.invert(transformStep); |
|
|
|
const transformY = this.state.absYScale.invert(transformStep); |
|
|
|
this.deltaYTransform = this.deltaYTransform + transformStep; |
|
|
|
this.deltaYTransform = this.deltaYTransform + transformStep; |
|
|
|
// TODO: not hardcoded bounds
|
|
|
|
// TODO: not hardcoded bounds
|
|
|
|
if(this.deltaYTransform > this.height * 0.9) { |
|
|
|
if(this.deltaYTransform > this.height * 0.9) { |
|
|
@ -735,23 +734,23 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
let yRange: [number, number]; |
|
|
|
let yRange: [number, number]; |
|
|
|
switch(this.coreOptions.mouseZoomEvent.orientation) { |
|
|
|
switch(this.coreOptions.mouseZoomEvent.orientation) { |
|
|
|
case BrushOrientation.HORIZONTAL: |
|
|
|
case BrushOrientation.HORIZONTAL: |
|
|
|
const startTimestamp = this.xScale.invert(extent[0]); |
|
|
|
const startTimestamp = this.state.xScale.invert(extent[0]); |
|
|
|
const endTimestamp = this.xScale.invert(extent[1]); |
|
|
|
const endTimestamp = this.state.xScale.invert(extent[1]); |
|
|
|
xRange = [startTimestamp, endTimestamp]; |
|
|
|
xRange = [startTimestamp, endTimestamp]; |
|
|
|
this.state.xValueRange = xRange; |
|
|
|
this.state.xValueRange = xRange; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case BrushOrientation.VERTICAL: |
|
|
|
case BrushOrientation.VERTICAL: |
|
|
|
const upperY = this.yScale.invert(extent[0]); |
|
|
|
const upperY = this.state.yScale.invert(extent[0]); |
|
|
|
const bottomY = this.yScale.invert(extent[1]); |
|
|
|
const bottomY = this.state.yScale.invert(extent[1]); |
|
|
|
// TODO: add min zoom y
|
|
|
|
// TODO: add min zoom y
|
|
|
|
yRange = [upperY, bottomY]; |
|
|
|
yRange = [upperY, bottomY]; |
|
|
|
this.state.yValueRange = yRange; |
|
|
|
this.state.yValueRange = yRange; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case BrushOrientation.RECTANGLE: |
|
|
|
case BrushOrientation.RECTANGLE: |
|
|
|
const bothStartTimestamp = this.xScale.invert(extent[0][0]); |
|
|
|
const bothStartTimestamp = this.state.xScale.invert(extent[0][0]); |
|
|
|
const bothEndTimestamp = this.xScale.invert(extent[1][0]); |
|
|
|
const bothEndTimestamp = this.state.xScale.invert(extent[1][0]); |
|
|
|
const bothUpperY = this.yScale.invert(extent[0][1]); |
|
|
|
const bothUpperY = this.state.yScale.invert(extent[0][1]); |
|
|
|
const bothBottomY = this.yScale.invert(extent[1][1]); |
|
|
|
const bothBottomY = this.state.yScale.invert(extent[1][1]); |
|
|
|
xRange = [bothStartTimestamp, bothEndTimestamp]; |
|
|
|
xRange = [bothStartTimestamp, bothEndTimestamp]; |
|
|
|
yRange = [bothUpperY, bothBottomY]; |
|
|
|
yRange = [bothUpperY, bothBottomY]; |
|
|
|
this.state.xValueRange = xRange; |
|
|
|
this.state.xValueRange = xRange; |
|
|
@ -762,10 +761,10 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
if(selectionAtts === undefined) { |
|
|
|
if(selectionAtts === undefined) { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
const scaledX0 = this.xScale.invert(selectionAtts.x); |
|
|
|
const scaledX0 = this.state.xScale.invert(selectionAtts.x); |
|
|
|
const scaledX1 = this.xScale.invert(selectionAtts.x + selectionAtts.width); |
|
|
|
const scaledX1 = this.state.xScale.invert(selectionAtts.x + selectionAtts.width); |
|
|
|
const scaledY0 = this.yScale.invert(selectionAtts.y); |
|
|
|
const scaledY0 = this.state.yScale.invert(selectionAtts.y); |
|
|
|
const scaledY1 = this.yScale.invert(selectionAtts.y + selectionAtts.height); |
|
|
|
const scaledY1 = this.state.yScale.invert(selectionAtts.y + selectionAtts.height); |
|
|
|
xRange = [scaledX0, scaledX1]; |
|
|
|
xRange = [scaledX0, scaledX1]; |
|
|
|
yRange = [scaledY0, scaledY1]; |
|
|
|
yRange = [scaledY0, scaledY1]; |
|
|
|
this.state.xValueRange = xRange; |
|
|
|
this.state.xValueRange = xRange; |
|
|
@ -777,8 +776,8 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected zoomOut(): void { |
|
|
|
protected zoomOut(): void { |
|
|
|
let xAxisMiddleValue: number = this.xScale.invert(this.width / 2); |
|
|
|
let xAxisMiddleValue: number = this.state.xScale.invert(this.width / 2); |
|
|
|
let yAxisMiddleValue: number = this.yScale.invert(this.height / 2); |
|
|
|
let yAxisMiddleValue: number = this.state.yScale.invert(this.height / 2); |
|
|
|
const centers = { |
|
|
|
const centers = { |
|
|
|
x: xAxisMiddleValue, |
|
|
|
x: xAxisMiddleValue, |
|
|
|
y: yAxisMiddleValue |
|
|
|
y: yAxisMiddleValue |
|
|
@ -786,33 +785,6 @@ abstract class ChartwerkPod<T extends CoreSerie, O extends Options> { |
|
|
|
this.coreOptions.callbackZoomOut(centers); |
|
|
|
this.coreOptions.callbackZoomOut(centers); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO: move to State
|
|
|
|
|
|
|
|
get absXScale(): d3.ScaleLinear<number, number> { |
|
|
|
|
|
|
|
const domain = [0, Math.abs(this.state.getMaxValueX() - this.state.getMinValueX())]; |
|
|
|
|
|
|
|
return d3.scaleLinear() |
|
|
|
|
|
|
|
.domain(domain) |
|
|
|
|
|
|
|
.range([0, this.width]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get absYScale(): d3.ScaleLinear<number, number> { |
|
|
|
|
|
|
|
const domain = [0, Math.abs(this.state.getMaxValueY() - this.state.getMinValueY())]; |
|
|
|
|
|
|
|
return d3.scaleLinear() |
|
|
|
|
|
|
|
.domain(domain) |
|
|
|
|
|
|
|
.range([0, this.height]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get xScale(): d3.ScaleLinear<number, number> { |
|
|
|
|
|
|
|
return this.state.xScale; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get yScale(): d3.ScaleLinear<number, number> { |
|
|
|
|
|
|
|
return this.state.yScale; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected get y1Scale(): d3.ScaleLinear<number, number> { |
|
|
|
|
|
|
|
return this.state.y1Scale; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getd3TimeRangeEvery(count: number): d3.TimeInterval { |
|
|
|
getd3TimeRangeEvery(count: number): d3.TimeInterval { |
|
|
|
if(this.coreOptions.allOptions.timeInterval.timeFormat === undefined) { |
|
|
|
if(this.coreOptions.allOptions.timeInterval.timeFormat === undefined) { |
|
|
|
return d3.timeMinute.every(count); |
|
|
|
return d3.timeMinute.every(count); |
|
|
|