veritatisquam
Version:
Carbon charting components, lerna monorepo
163 lines (136 loc) • 4.35 kB
text/typescript
// Internal Imports
import { Component } from '../component';
import { AxisPositions, ScaleTypes, AxesOptions } from '../../interfaces';
import { Axis } from './axis';
import { Tools } from '../../tools';
import { DOMUtils } from '../../services';
import { Threshold } from '../essentials/threshold';
import { Events } from './../../interfaces';
export class TwoDimensionalAxes extends Component {
type = '2D-axes';
children: any = {};
thresholds: Threshold[] = [];
margins = {
top: 0,
right: 0,
bottom: 0,
left: 0,
};
render(animate = false) {
const axes = {};
const axisPositions = Object.keys(AxisPositions);
const axesOptions = Tools.getProperty(this.getOptions(), 'axes');
axisPositions.forEach((axisPosition) => {
const axisOptions = axesOptions[AxisPositions[axisPosition]];
if (axisOptions) {
axes[AxisPositions[axisPosition]] = true;
}
});
this.configs.axes = axes;
// Check the configs to know which axes need to be rendered
axisPositions.forEach((axisPositionKey) => {
const axisPosition = AxisPositions[axisPositionKey];
if (
this.configs.axes[axisPosition] &&
!this.children[axisPosition]
) {
const axisComponent = new Axis(this.model, this.services, {
position: axisPosition,
axes: this.configs.axes,
margins: this.margins,
});
// Set model, services & parent for the new axis component
axisComponent.setModel(this.model);
axisComponent.setServices(this.services);
axisComponent.setParent(this.parent);
this.children[axisPosition] = axisComponent;
}
});
Object.keys(this.children).forEach((childKey) => {
const child = this.children[childKey];
child.render(animate);
});
const margins = {} as any;
Object.keys(this.children).forEach((childKey) => {
const child = this.children[childKey];
const axisPosition = child.configs.position;
// Grab the invisibly rendered axis' width & height, and set margins
// Based off of that
// We draw the invisible axis because of the async nature of d3 transitions
// To be able to tell the final width & height of the axis when initiaing the transition
// The invisible axis is updated instantly and without a transition
const invisibleAxisRef = child.getInvisibleAxisRef();
const {
width,
height,
} = DOMUtils.getSVGElementSize(invisibleAxisRef, { useBBox: true });
let offset;
if (child.getTitleRef().empty()) {
offset = 0;
} else {
offset = DOMUtils.getSVGElementSize(child.getTitleRef(), {
useBBox: true,
}).height;
if (
axisPosition === AxisPositions.LEFT ||
axisPosition === AxisPositions.RIGHT
) {
offset += 5;
}
}
switch (axisPosition) {
case AxisPositions.TOP:
margins.top = height + offset;
break;
case AxisPositions.BOTTOM:
margins.bottom = height + offset;
break;
case AxisPositions.LEFT:
margins.left = width + offset;
break;
case AxisPositions.RIGHT:
margins.right = width + offset;
break;
}
// Add thresholds
this.addAxisThresholds(animate, axisPosition);
});
// If the new margins are different than the existing ones
const isNotEqual = Object.keys(margins).some((marginKey) => {
return this.margins[marginKey] !== margins[marginKey];
});
if (isNotEqual) {
this.margins = Object.assign(this.margins, margins);
// also set new margins to model to allow external components to access
this.model.set({ axesMargins: this.margins }, { skipUpdate: true });
this.services.events.dispatchEvent(Events.ZoomBar.UPDATE);
Object.keys(this.children).forEach((childKey) => {
const child = this.children[childKey];
child.margins = this.margins;
});
this.render(true);
}
}
addAxisThresholds(animate, axisPosition) {
const axesOptions = Tools.getProperty(
this.getOptions(),
'axes',
axisPosition
);
const { thresholds } = axesOptions;
if (thresholds) {
thresholds.forEach((thresholdConfig, i) => {
const thresholdComponent = new Threshold(
this.model,
this.services,
{ ...thresholdConfig, axisPosition, index: i }
);
this.thresholds.push(thresholdComponent);
});
this.thresholds.forEach((threshold) => {
threshold.setParent(this.parent);
threshold.render(animate);
});
}
}
}