UNPKG

veritatisquam

Version:
162 lines (144 loc) 4.25 kB
// Internal Imports import { Scatter } from './scatter'; import { Roles } from '../../interfaces'; import { Tools } from '../../tools'; export class StackedScatter extends Scatter { type = 'scatter-stacked'; render(animate: boolean) { const isScatterEnabled = Tools.getProperty( this.getOptions(), 'points', 'enabled' ); if (!isScatterEnabled) { return; } // Grab container SVG const svg = this.getContainerSVG({ withinChartClip: true }); const options = this.getOptions(); const { groupMapsTo } = options.data; const percentage = Object.keys(options.axes).some( (axis) => options.axes[axis].percentage ); const stackedData = this.model.getStackedData({ groups: this.configs.groups, percentage, }); // Update data on dot groups const circleGroups = svg .selectAll('g.dots') .data(stackedData, (d) => d[0][groupMapsTo]); // Remove dot groups that need to be removed circleGroups.exit().attr('opacity', 0).remove(); // Add the dot groups that need to be introduced const circleGroupsEnter = circleGroups .enter() .append('g') .classed('dots', true) .attr('role', Roles.GROUP); // Update data on all circles const circles = circleGroupsEnter .merge(circleGroups) .selectAll('circle.dot') .data((d) => d); // Remove circles that need to be removed circles.exit().attr('opacity', 0).remove(); // Add the dot groups that need to be introduced const enteringCircles = circles .enter() .append('circle') .classed('dot', true) .attr('opacity', 0); // Apply styling & position const circlesToStyle = enteringCircles.merge(circles).datum((d) => { const group = d[groupMapsTo]; const domainIdentifier = this.services.cartesianScales.getDomainIdentifier( d ); const rangeIdentifier = this.services.cartesianScales.getRangeIdentifier( d ); return { [groupMapsTo]: group, [domainIdentifier]: d['data']['sharedStackKey'], [rangeIdentifier]: d[1], }; }); this.styleCircles(circlesToStyle, animate); // Add event listeners to elements drawn this.addEventListeners(); } getTooltipData(hoveredX, hoveredY) { const options = this.getOptions(); const { groupMapsTo } = options.data; const percentage = Object.keys(options.axes).some( (axis) => options.axes[axis].percentage ); const stackedData = this.model.getStackedData({ groups: this.configs.groups, percentage, }); const tooltipData = []; stackedData.forEach((groupData, groupDataIndex) => { groupData.forEach((datum, dataIndex) => { const group = datum[groupMapsTo]; const domainValue = datum['data']['sharedStackKey']; let rangeValue = datum['data'][group]; const stackedRangeValue = datum[1]; const domainIdentifier = this.services.cartesianScales.getDomainIdentifier( datum ); const rangeIdentifier = this.services.cartesianScales.getRangeIdentifier( datum ); if ( rangeValue !== null && rangeValue !== undefined && hoveredX === this.services.cartesianScales.getDomainValue( domainValue ) && hoveredY === this.services.cartesianScales.getRangeValue( stackedRangeValue ) ) { if (percentage) { rangeValue = this.model.getStackedData({ groups: this.configs.groups, })[groupDataIndex][dataIndex]['data'][group]; } if (rangeValue !== null) { tooltipData.push({ [groupMapsTo]: group, [domainIdentifier]: domainValue, [rangeIdentifier]: rangeValue, }); } } }); }); return this.model .getDisplayData(this.configs.groups) .filter((datapoint) => { const domainIdentifier = this.services.cartesianScales.getDomainIdentifier( datapoint ); const rangeIdentifier = this.services.cartesianScales.getRangeIdentifier( datapoint ); return ( tooltipData.find((tooltipDatapoint) => { return ( tooltipDatapoint[groupMapsTo] == datapoint[groupMapsTo] && tooltipDatapoint[domainIdentifier] == datapoint[domainIdentifier] && tooltipDatapoint[rangeIdentifier] == datapoint[rangeIdentifier] ); }) !== undefined ); }); } }