Skip to content

Commit c1308ac

Browse files
authored
v2.1.2 - Fix axis ticks by computing the required width (#87)
* Fix axis ticks by computing the required width * Run GitHub actions on ubuntu-22.04 * Add report tooltip support * Tailor title text if it's too long * Ensure to use the correct transform value 'translate' for getGroupTransformValue method * Refactor 'getGroupTransformValue' method * Refactor 'getGroupTransformValue' method
1 parent 384c781 commit c1308ac

File tree

7 files changed

+119
-30
lines changed

7 files changed

+119
-30
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ on:
1212
jobs:
1313
build:
1414

15-
runs-on: ubuntu-latest
15+
runs-on: ubuntu-22.04
1616

1717
strategy:
1818
matrix:

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## 2.1.2
2+
### Visual changes
3+
* Tailor title text if it's too long
4+
5+
## 2.1.1
6+
### Visual changes
7+
* Fix axis ticks by computing the required width
8+
* Add report tooltip support
9+
110
## 2.1.0
211
### Visual changes
312
* Add new font settings
@@ -48,4 +57,4 @@
4857
* Converted legacy API visual version 1.3.4 to API 1.10.0
4958

5059
## 1.2.18
51-
* Fix chart drawing issue when the visual get dataset without sorting by date
60+
* Fix chart drawing issue when the visual get dataset without sorting by date

capabilities.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,5 +435,14 @@
435435
}
436436
}
437437
},
438+
"tooltips": {
439+
"supportedTypes": {
440+
"default": true,
441+
"canvas": true
442+
},
443+
"roles": [
444+
"tooltips"
445+
]
446+
},
438447
"privileges": []
439-
}
448+
}

package-lock.json

Lines changed: 40 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "dualkpi",
33
"displayName": "Dual KPI",
4-
"version": "2.1.0.0",
4+
"version": "2.1.2.0",
55
"description": "Dual KPI efficiently visualizes two measures over time. It shows their trend based on a joint timeline, while absolute values may use different scales, for example Profit and Market share or Sales and Profit. Each KPI can be visualized as line chart or area chart. The visual has dynamic behavior and can show historical value and the change from the latest value when you hover over it. It also has small icons and labels to convey KPI definitions and alerts about data freshness. Customize colors, titles, axis properties, tooltips, and more, to create visually appealing and functional executive dashboards.",
66
"author": {
77
"name": "Microsoft",

pbiviz.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"visual": {
33
"name": "dualKpi",
4-
"displayName": "Dual KPI 2.1.0.0",
4+
"displayName": "Dual KPI 2.1.2.0",
55
"guid": "PBI_CV_3C80B1F2_09AF_4123_8E99_C3CBC46B23E0",
66
"visualClassName": "DualKpi",
7-
"version": "2.1.0.0",
7+
"version": "2.1.2.0",
88
"description": "Dual KPI efficiently visualizes two measures over time. It shows their trend based on a joint timeline, while absolute values may use different scales, for example Profit and Market share or Sales and Profit. Each KPI can be visualized as line chart or area chart. The visual has dynamic behavior and can show historical value and the change from the latest value when you hover over it. It also has small icons and labels to convey KPI definitions and alerts about data freshness. Customize colors, titles, axis properties, tooltips, and more, to create visually appealing and functional executive dashboards.",
99
"supportUrl": "http://community.powerbi.com",
1010
"gitHubUrl": "https://github.com/Microsoft/powerbi-visuals-dualkpi"

src/visual.ts

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import { ColorHelper } from "powerbi-visuals-utils-colorutils";
4848
import {
4949
valueFormatter as ValueFormatter,
5050
displayUnitSystemType,
51+
textMeasurementService,
5152
} from "powerbi-visuals-utils-formattingutils";
5253
import DisplayUnitSystemType = displayUnitSystemType.DisplayUnitSystemType;
5354

@@ -213,7 +214,7 @@ export class DualKpi implements IVisual {
213214
private timeFormatter: (date: Date) => string;
214215
private dataBisector: (array: ArrayLike<IDualKpiDataPoint>, x: Date, lo?: number, hi?: number) => number;
215216

216-
private chartLeftMargin = 45;
217+
private chartLeftMargin = 35;
217218
private viewport: IViewport;
218219

219220
private axisNumberFormatter: (d: NumberValue) => string;
@@ -517,6 +518,7 @@ export class DualKpi implements IVisual {
517518
this.displayRootElement(wasDataSetRendered);
518519
this.drawTopChart({data, chartHeight, chartWidth, chartSpaceBetween});
519520
this.drawBottomChart({data, chartHeight, chartWidth, chartSpaceBetween});
521+
this.adjustAxisGroupPosition();
520522

521523
if (wasDataSetRendered) {
522524
this.drawBottomContainer(chartWidth, chartHeight, chartTitleSpace, chartSpaceBetween, iconOffset);
@@ -526,6 +528,44 @@ export class DualKpi implements IVisual {
526528
}
527529
}
528530

531+
private adjustAxisGroupPosition() {
532+
const axisTicks = this.svgRoot.selectAll("g.tick");
533+
const axisMaxWidth = Math.ceil(Math.max(...axisTicks.nodes().map((x: SVGGElement) => x.getBBox().width))) || 0;
534+
535+
const topGroupTransform = this.getGroupTransformValue(this.chartGroupTop.group.node());
536+
const bottomGroupTransform = this.getGroupTransformValue(this.chartGroupBottom.group.node());
537+
let transformX: number = axisMaxWidth;
538+
539+
if (this.formattingSettings.properties.topChartShow.value) {
540+
transformX = Math.max(transformX, topGroupTransform.x);
541+
}
542+
if (this.formattingSettings.properties.bottomChartShow.value) {
543+
transformX = Math.max(transformX, bottomGroupTransform.x);
544+
}
545+
546+
if (this.formattingSettings.properties.topChartShow.value) {
547+
this.chartGroupTop.group.attr("transform", `translate(${Math.max(transformX)}, ${topGroupTransform.y})`);
548+
}
549+
550+
if (this.formattingSettings.properties.bottomChartShow.value) {
551+
this.chartGroupBottom.group.attr("transform", `translate(${Math.max(transformX)}, ${bottomGroupTransform.y})`);
552+
}
553+
}
554+
555+
private getGroupTransformValue(group: SVGGElement): { x: number; y: number; } {
556+
const transformList = group?.transform?.baseVal;
557+
if (!transformList || transformList.length === 0) {
558+
return { x: 0, y: 0 };
559+
}
560+
561+
562+
const svgTransformTranslate = Array.from(transformList).find((x) => x.type === SVGTransform.SVG_TRANSFORM_TRANSLATE);
563+
564+
return svgTransformTranslate
565+
? { x: svgTransformTranslate.matrix.e, y: svgTransformTranslate.matrix.f }
566+
: { x: 0, y: 0 };
567+
}
568+
529569
private setChartLayout(availableHeight: number, availableWidth: number) {
530570
let chartSpaceBetween: number, chartTitleSpace: number, iconOffset: number;
531571
const size: DualKpiSize = DualKpi.getChartSize({ height: availableHeight, width: availableWidth });
@@ -1162,12 +1202,25 @@ export class DualKpi implements IVisual {
11621202
dayRangeLeft -= (iconWidth); // width of icon + 8px padding
11631203
}
11641204
dayRangeElement.attr("transform", "translate(" + (dayRangeLeft) + ",0)");
1205+
1206+
const titleMaxWidth = dayRangeLeft - dayRangeElement.node().getBBox().width;
1207+
this.tailorTextByMaxWidth(chartTitleElement, titleMaxWidth);
11651208
}
11661209

11671210
this.bottomContainer.bottomContainer.attr("transform", "translate(5," + (this.viewport.height - 5) + ")");
11681211
this.bottomContainer.bottomContainer.classed(DualKpi.INVISIBLE, false);
11691212
}
11701213

1214+
private tailorTextByMaxWidth(text: d3Selection<SVGTextElement, unknown, null, undefined>, maxWidth: number) {
1215+
const tailoredText = textMeasurementService.getTailoredTextOrDefault({
1216+
text: text.text(),
1217+
fontSize: text.style("font-size"),
1218+
fontFamily: text.style("font-family"),
1219+
}, maxWidth);
1220+
1221+
text.text(tailoredText);
1222+
}
1223+
11711224
private createWarningMessage(chartTitleElement, iconY: number, iconScaleTransform: string, iconWidth: number) {
11721225
const warning = this.bottomContainer.warning;
11731226
warning.group
@@ -1252,7 +1305,7 @@ export class DualKpi implements IVisual {
12521305
};
12531306

12541307
if (this.size === DualKpiSize.medium || this.size === DualKpiSize.large) {
1255-
margin.left = 45;
1308+
margin.left = 40;
12561309
}
12571310

12581311
const calcWidth = options.width - margin.right - margin.left,
@@ -1335,7 +1388,6 @@ export class DualKpi implements IVisual {
13351388
}
13361389
return axisTickLabel;
13371390
})
1338-
.tickPadding(0)
13391391

13401392
const axis = chartGroup.yAxis;
13411393
axis

0 commit comments

Comments
 (0)