in src/visual.ts [962:1131]
private drawDots(lineTipSelection) {
const point_time: number = this.settings.misc.isAnimated && !this.settings.misc.isStopped
? LineDotChart.pointTime
: 0;
const hasHighlights: boolean = this.data.hasHighlights;
const hasSelection: boolean = this.interactivityService && this.interactivityService.hasSelection();
// Draw the individual data points that will be shown on hover with a tooltip
const lineTipSelectionMerged = lineTipSelection.enter()
.append("g")
.merge(lineTipSelection);
lineTipSelectionMerged
.classed(LineDotChart.dotPointsClass, true);
const dotsSelection: d3.Selection<d3.BaseType, LineDotPoint, any, any> = lineTipSelectionMerged
.selectAll("circle." + LineDotChart.pointClassName)
.data(d => d);
const dotsSelectionMerged = dotsSelection.enter()
.append("circle")
.merge(dotsSelection);
dotsSelectionMerged
.classed(LineDotChart.pointClassName, true)
.on("mouseover.point", this.showDataPoint)
.on("mouseout.point", this.hideDataPoint);
dotsSelectionMerged
.style("fill", this.settings.dotoptions.color)
.style("stroke", this.settings.dotoptions.stroke)
.style("stroke-opacity", this.settings.dotoptions.strokeOpacity)
.style("stroke-width", this.settings.dotoptions.strokeWidth
? PixelConverter.toString(this.settings.dotoptions.strokeWidth)
: null)
.style("opacity", (dotPoint: LineDotPoint) => {
return getFillOpacity(
dotPoint,
dotPoint.selected,
dotPoint.highlight,
!dotPoint.highlight && hasSelection,
!dotPoint.selected && hasHighlights
);
})
.attr("r", (dotPoint: LineDotPoint) => {
return this.settings.dotoptions.dotSizeMin
+ dotPoint.dot * (this.settings.dotoptions.dotSizeMax - this.settings.dotoptions.dotSizeMin);
});
if (this.settings.misc.isAnimated) {
const maxTextLength: number = Math.min(
350,
this.xAxisProperties.scale.range()[1] - this.xAxisProperties.scale.range()[0] - 60
);
const lineText: d3.Selection<d3.BaseType, string, any, any> = this.line
.selectAll(LineDotChart.textSelector)
.data([""]);
const lineTextMerged = lineText
.enter()
.append("text")
.merge(lineText);
lineTextMerged
.attr("text-anchor", "end")
.classed("text", true);
lineTextMerged
.attr("x", this.layout.viewportIn.width - LineDotChart.widthMargin)
.attr("y", LineDotChart.yPosition)
.style("fill", this.settings.counteroptions.color)
.style("font-size", PixelConverter.toString(PixelConverter.fromPointToPixel(this.settings.counteroptions.textSize)))
.call(selection => TextMeasurementService.svgEllipsis(<any>selection.node(), maxTextLength));
lineText
.exit()
.remove();
dotsSelectionMerged
.interrupt()
.attr("transform", (dataPoint: LineDotPoint) => {
return SVGManipulations.translateAndScale(
this.xAxisProperties.scale(dataPoint.dateValue.value),
this.yAxisProperties.scale(dataPoint.value),
LineDotChart.pointScaleValue);
})
.transition()
.on("start", (d: LineDotPoint, i: number) => {
if (this.settings.counteroptions.show) {
let text: string = `${this.settings.counteroptions.counterTitle} `;
if (d.counter) {
text += this.settings.isCounterDateTime.isCounterDateTime
? this.data.dateColumnFormatter.format(d.counter)
: d.counter;
} else {
text += (i + 1);
}
this.updateLineText(lineTextMerged, text);
} else {
this.updateLineText(lineTextMerged, "");
}
})
.duration(point_time)
.delay((_, i: number) => this.pointDelay(this.data.dotPoints, i, this.animationDuration))
.ease(d3.easeLinear)
.attr("transform", (dataPoint: LineDotPoint) => {
return SVGManipulations.translateAndScale(
this.xAxisProperties.scale(dataPoint.dateValue.value),
this.yAxisProperties.scale(dataPoint.value),
LineDotChart.pointTransformScaleValue);
})
.transition()
.duration(point_time)
.delay((_, i: number) => {
return (this.pointDelay(this.data.dotPoints, i, this.animationDuration) + point_time) / LineDotChart.pointDelayCoefficient;
})
.ease(d3.easeElastic)
.attr("transform", (dataPoint: LineDotPoint) => {
return SVGManipulations.translateAndScale(
this.xAxisProperties.scale(dataPoint.dateValue.value),
this.yAxisProperties.scale(dataPoint.value),
1);
});
} else {
dotsSelectionMerged
.interrupt()
.attr("transform", (dataPoint: LineDotPoint) => {
return SVGManipulations.translateAndScale(
this.xAxisProperties.scale(dataPoint.dateValue.value),
this.yAxisProperties.scale(dataPoint.value),
1);
});
this.line
.selectAll(LineDotChart.textSelector)
.remove();
}
this.tooltipServiceWrapper.addTooltip<LineDotPoint>(
dotsSelectionMerged,
(tooltipEvent: TooltipEventArgs<LineDotPoint>) => {
return this.getTooltipDataItems(tooltipEvent.data);
});
dotsSelection
.exit()
.remove();
lineTipSelection
.exit()
.remove();
if (this.interactivityService) {
const behaviorOptions: BehaviorOptions = {
selection: dotsSelectionMerged,
clearCatcher: this.root,
hasHighlights: hasHighlights,
};
this.interactivityService.bind(
this.data.dotPoints,
this.behavior,
behaviorOptions,
);
}
}