veritatisquam
Version:
Carbon charting components, lerna monorepo
101 lines (92 loc) • 2.72 kB
text/typescript
// Internal Imports
import { Scatter } from './scatter';
import { DOMUtils } from '../../services';
import { Roles, ColorClassNameTypes } from '../../interfaces';
// D3 Imports
import { Selection } from 'd3-selection';
import { extent } from 'd3-array';
import { scaleLinear } from 'd3-scale';
export class Bubble extends Scatter {
type = 'bubble';
getRadiusScale(selection: Selection<any, any, any, any>) {
const options = this.getOptions();
const { radiusMapsTo } = options.bubble;
const data = selection.data();
// Filter out any null/undefined values
const allRadii = data
.map((d) => d[radiusMapsTo])
.filter((radius) => radius);
const chartSize = DOMUtils.getSVGElementSize(
this.services.domUtils.getMainSVG(),
{ useAttr: true }
);
// We need the ternary operator here in case the user
// doesn't provide radius values in data
const radiusDataIsValid = allRadii.length > 0;
const domain = radiusDataIsValid ? extent(allRadii) : [1, 1];
return scaleLinear()
.domain(domain)
.range(
radiusDataIsValid
? options.bubble.radiusRange(chartSize, data)
: [4, 4]
);
}
styleCircles(selection: Selection<any, any, any, any>, animate: boolean) {
// Chart options mixed with the internal configurations
const options = this.getOptions();
const { radiusMapsTo } = options.bubble;
const radiusScale = this.getRadiusScale(selection);
const { groupMapsTo } = options.data;
selection
.raise()
.classed('dot', true)
.attr('role', Roles.GRAPHICS_SYMBOL)
.transition(
this.services.transitions.getTransition(
'bubble-update-enter',
animate
)
)
.attr('cx', (d, i) =>
this.services.cartesianScales.getDomainValue(d, i)
)
.attr('cy', (d, i) =>
this.services.cartesianScales.getRangeValue(d, i)
)
// We need `|| 1` here in case the user doesn't provide radius values in data
.attr('r', (d) => radiusScale(d[radiusMapsTo] || 1))
.attr('class', (d) =>
this.model.getColorClassName({
classNameTypes: [
ColorClassNameTypes.FILL,
ColorClassNameTypes.STROKE,
],
dataGroupName: d[groupMapsTo],
originalClassName: 'dot',
})
)
.style('fill', (d) => {
const domainIdentifier = this.services.cartesianScales.getDomainIdentifier(
d
);
return this.model.getFillColor(
d[groupMapsTo],
d[domainIdentifier],
d
);
})
.style('stroke', (d) => {
const domainIdentifier = this.services.cartesianScales.getDomainIdentifier(
d
);
return this.model.getStrokeColor(
d[groupMapsTo],
d[domainIdentifier],
d
);
})
.attr('fill-opacity', options.bubble.fillOpacity)
.attr('opacity', 1);
}
}