in src/visual.ts [1565:1761]
private renderLegend(): void {
let layers: IColumnChart[] = this.layers,
legendData: ILegendData = {
title: "",
dataPoints: []
};
for (let i: number = 0; i < layers.length; i++) {
this.layerLegendData = layers[i].calculateLegend();
if (this.layerLegendData) {
legendData.title = i === 0
? this.layerLegendData.title || ""
: legendData.title;
legendData.dataPoints = legendData.dataPoints
.concat(this.layerLegendData.dataPoints || []);
if (this.layerLegendData.grouped) {
legendData.grouped = true;
}
}
}
const legendProperties: powerbi.DataViewObject = this.legendObjectProperties;
if (legendProperties) {
if (!legendProperties["fontSize"]) {
legendProperties["fontSize"] = MekkoChart.DefaultLabelFontSizeInPt;
}
LegendData.update(legendData, legendProperties);
const position: string = legendProperties[legendProps.position] as string;
if (position) {
this.legend.changeOrientation(LegendPosition[position]);
}
}
else {
this.legend.changeOrientation(LegendPosition.Top);
}
if ((legendData.dataPoints.length === 1 && !legendData.grouped) || this.hideLegends()) {
legendData.dataPoints = [];
}
let reducedLegends: IGrouppedLegendData[] = [];
let legendSortSettings: MekkoLegendSortSettings = (<BaseColumnChart>this.layers[0]).getLegendSortSettings();
if (legendSortSettings.enabled) {
if (legendSortSettings.groupByCategory) {
let mappedLegends = legendData.dataPoints.map((dataPoint: MekkoLegendDataPoint) => {
let maxVal = max(dataPoint.categoryValues as Number[]);
let index = dataPoint.categoryValues.indexOf(maxVal as PrimitiveValue);
return {
categoryIndex: index,
data: dataPoint,
categoryValue: 0
};
});
mappedLegends.forEach(element => {
reducedLegends[element.categoryIndex] =
reducedLegends[element.categoryIndex] || {
category: this.layers[0].getData().categories[element.categoryIndex],
index: element.categoryIndex,
data: [],
dataValues: 0,
categorySorting: null
};
reducedLegends[element.categoryIndex].data.push(element.data);
});
reducedLegends.forEach(element => {
element.dataValues = sum(element.data.map((d) => d.valueSum));
});
reducedLegends.forEach(legend => {
if (legend === undefined) {
return;
}
legend.data = legend.data.sort((a, b) => a["valueSum"] > b["valueSum"] ? 1 : -1);
if (legendSortSettings.groupByCategoryDirection === MekkoChart.SortDirectionDescending) {
legend.data = legend.data.reverse();
}
});
reducedLegends = reducedLegends.sort((a, b) => a["categorySort"] > b["categorySort"] ? 1 : -1);
if (legendSortSettings.direction === MekkoChart.SortDirectionDescending) {
reducedLegends = reducedLegends.reverse();
}
legendData.dataPoints = [];
reducedLegends.forEach(legend => {
if (legend === undefined) {
return;
}
legendData.dataPoints = legendData.dataPoints.concat(legend.data);
});
}
else {
legendData.dataPoints = legendData.dataPoints.sort((a, b) => a["valueSum"] > b["valueSum"] ? 1 : -1);
if (legendSortSettings.direction === MekkoChart.SortDirectionDescending) {
legendData.dataPoints = legendData.dataPoints.reverse();
}
}
}
let svgHeight: number = textMeasurementService.estimateSvgTextHeight({
fontFamily: MekkoChart.LegendBarTextFont,
fontSize: PixelConverter.toString(+legendProperties["fontSize"] + MekkoChart.LegendBarHeightMargin),
text: "AZ"
});
select(this.rootElement.node()).selectAll("div.legendParent").remove();
this.categoryLegends = [];
let legendParents = select(this.rootElement.node()).selectAll("div.legendParent");
reducedLegends = reducedLegends.filter((l: IGrouppedLegendData) => l !== undefined);
let legendParentsWithData = legendParents.data(reducedLegends);
let legendParentsWithChilds = legendParentsWithData.enter().append("div");
let legendParentsWithChildsAttr = legendParentsWithChilds.classed("legendParent", true)
.style("position", "absolute")
.style("top", (data, index) => PixelConverter.toString(svgHeight * index));
let mekko = this;
this.categoryLegends = this.categoryLegends || [];
legendParentsWithChildsAttr.each(function (data, index) {
let legendSvg = select(this);
if (legendSvg.select("svg").node() === null) {
let legend: ILegend = createLegend(
<any>this,
false,
mekko.interactivityService,
true);
mekko.categoryLegends[index] = <ILegend>legend;
}
});
if (reducedLegends.length) {
this.legendMargins = this.categoryLegends[0].getMargins();
this.legendMargins.height = this.legendMargins.height - MekkoChart.LegendBarHeightMargin;
this.legendMargins.height = this.legendMargins.height * reducedLegends.length;
}
if (reducedLegends.length > 0) {
this.categoryLegends.forEach((legend: ILegend, index: number) => {
(<ILegendGroup>legend).position = +select((<ILegendGroup>legend).element).style("top").replace("px", "");
});
this.categoryLegends = this.categoryLegends.sort((a, b) => a["position"] > b["position"] ? 1 : -1).reverse();
this.categoryLegends.forEach((legend, index) => {
if (reducedLegends[index] === undefined) {
LegendData.update({
dataPoints: []
}, legendProperties);
legend.changeOrientation(LegendPosition.None);
legend.drawLegend({
dataPoints: []
}, this.currentViewport);
return;
}
let legendData: ILegendData = {
title: reducedLegends[index].category,
dataPoints: reducedLegends[index].data
};
LegendData.update(legendData, legendProperties);
legend.drawLegend(legendData, this.currentViewport);
if (index === 0) {
if (legendParentsWithChildsAttr.node() === null) {
svgHeight = +legendParents.select("svg").attr("height").replace("px", "");
} else {
svgHeight = +select(legendParentsWithChildsAttr.node()).select("svg").attr("height").replace("px", "");
}
}
});
}
legendParentsWithData.exit().remove();
if (legendProperties["show"] === false) {
legendData.dataPoints = [];
this.categoryLegends.forEach(legend => {
legend.changeOrientation(LegendPosition.None);
LegendData.update(legendData, legendProperties);
legend.drawLegend(legendData, this.currentViewport);
});
}
if (reducedLegends.length > 0) {
this.legend.changeOrientation(LegendPosition.None);
}
this.legend.drawLegend(legendData, this.currentViewport);
}