From 8eed428e8dabde31f2e6838bc087e27834789af1 Mon Sep 17 00:00:00 2001 From: Evgenii Elkin Date: Wed, 11 Oct 2017 12:13:44 +0300 Subject: [PATCH 1/3] New options for scale creation --- CHANGELOG.md | 3 ++ lib/index.d.ts | 6 +++- lib/index.js | 19 ++++++---- package-lock.json | 2 +- package.json | 2 +- src/axis/axis.ts | 19 ++++++---- src/axis/axisInterfaces.ts | 4 +++ test/axis/axisTest.ts | 41 +++++++++++++++++++++- test/axis/helpers/axisPropertiesBuilder.ts | 13 +++++++ 9 files changed, 93 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 983aa69..894b5f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 1.4.2 +* Added two new optional parameters for CreateScale function -- innerPadding and useRangePoint. The first lets set inner padding for scale instead of recieve it from constant. The second lets use rangePoint instead of rangeBands function for creation of ordinal scale. + ## 1.4.0 * Remove width restriction of title in legend * Added new option to drawDefaultLabelsForDataPointChart function to control behavior of collided labels diff --git a/lib/index.d.ts b/lib/index.d.ts index 54976f1..1259270 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -226,6 +226,10 @@ declare module powerbi.extensibility.utils.chart.axis { disableNice?: boolean; /** (optional) Disable "niceing" for numeric axis. Disabling nice will be applid only when creating scale obj (bestTickCount will be applied to 'ticks' method) */ disableNiceOnlyForScale?: boolean; + /** (optional) InnerPadding to be applied to the axis.*/ + innerPadding?: number; + /** (optioanl) Apply for using of RangePoints function instead of RangeBands inside CreateOrdinal scale function.*/ + useRangePoints?: boolean; } enum AxisOrientation { top = 0, @@ -364,7 +368,7 @@ declare module powerbi.extensibility.utils.chart.axis { function wordBreak(text: d3.Selection, axisProperties: IAxisProperties, maxHeight: number): void; function clip(text: d3.Selection, availableWidth: number, svgEllipsis: (textElement: SVGTextElement, maxWidth: number) => void): void; } - function createOrdinalScale(pixelSpan: number, dataDomain: any[], outerPaddingRatio?: number): d3.scale.Ordinal; + function createOrdinalScale(pixelSpan: number, dataDomain: any[], outerPaddingRatio?: number, innerPaddingRatio?: number, useRangePoints?: boolean): d3.scale.Ordinal; function isLogScalePossible(domain: any[], axisType?: ValueType): boolean; function createNumericalScale(axisScaleType: string, pixelSpan: number, dataDomain: any[], dataType: ValueType, outerPadding?: number, niceCount?: number, shouldClamp?: boolean): d3.scale.Linear; function createLinearScale(pixelSpan: number, dataDomain: any[], outerPadding?: number, niceCount?: number, shouldClamp?: boolean): d3.scale.Linear; diff --git a/lib/index.js b/lib/index.js index 77bd5d9..b76ef1d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -218,7 +218,6 @@ var powerbi; var ScalarTickLabelPadding = 3; var TickLabelPadding = 2; var MinOrdinalRectThickness = 20; - var InnerPaddingRatio = 0.2; /** * Default ranges are for when we have a field chosen for the axis, * but no values are returned by the query. @@ -777,7 +776,7 @@ var powerbi; return 1; } function createScale(options) { - var pixelSpan = options.pixelSpan, dataDomain = options.dataDomain, metaDataColumn = options.metaDataColumn, outerPadding = options.outerPadding || 0, isScalar = !!options.isScalar, isVertical = !!options.isVertical, forcedTickCount = options.forcedTickCount, categoryThickness = options.categoryThickness, shouldClamp = !!options.shouldClamp, maxTickCount = options.maxTickCount, disableNice = options.disableNice, disableNiceOnlyForScale = options.disableNiceOnlyForScale; + var pixelSpan = options.pixelSpan, dataDomain = options.dataDomain, metaDataColumn = options.metaDataColumn, outerPadding = options.outerPadding || 0, isScalar = !!options.isScalar, isVertical = !!options.isVertical, forcedTickCount = options.forcedTickCount, categoryThickness = options.categoryThickness, shouldClamp = !!options.shouldClamp, maxTickCount = options.maxTickCount, disableNice = options.disableNice, disableNiceOnlyForScale = options.disableNiceOnlyForScale, innerPadding = options.innerPadding, useRangePoint = options.useRangePoints; var dataType = getCategoryValueType(metaDataColumn, isScalar); var maxTicks = isVertical ? getRecommendedNumberOfTicksForYAxis(pixelSpan) : getRecommendedNumberOfTicksForXAxis(pixelSpan); if (maxTickCount && @@ -797,7 +796,7 @@ var powerbi; else dataDomain = []; if (isOrdinal(dataType)) { - scale = createOrdinalScale(pixelSpan, dataDomain, categoryThickness ? outerPadding / categoryThickness : 0); + scale = createOrdinalScale(pixelSpan, dataDomain, categoryThickness ? outerPadding / categoryThickness : 0, innerPadding, useRangePoint); } else { scale = createNumericalScale(options.scaleType, pixelSpan, dataDomain, dataType, outerPadding, bestTickCount); @@ -832,7 +831,7 @@ var powerbi; scale = createLinearScale(pixelSpan, scalarDomain, outerPadding, null, shouldClamp); // DO NOT PASS TICKCOUNT } else if (dataType.text || dataType.dateTime || dataType.numeric || dataType.bool) { - scale = createOrdinalScale(pixelSpan, scalarDomain, categoryThickness ? outerPadding / categoryThickness : 0); + scale = createOrdinalScale(pixelSpan, scalarDomain, categoryThickness ? outerPadding / categoryThickness : 0, innerPadding, useRangePoint); bestTickCount = maxTicks === 0 ? 0 : Math.min(scalarDomain.length, (pixelSpan - outerPadding * 2) / MinOrdinalRectThickness); } @@ -1230,10 +1229,17 @@ var powerbi; } LabelLayoutStrategy.clip = clip; })(LabelLayoutStrategy = axis_1.LabelLayoutStrategy || (axis_1.LabelLayoutStrategy = {})); - function createOrdinalScale(pixelSpan, dataDomain, outerPaddingRatio) { + function createOrdinalScale(pixelSpan, dataDomain, outerPaddingRatio, innerPaddingRatio, useRangePoints) { if (outerPaddingRatio === void 0) { outerPaddingRatio = 0; } + if (innerPaddingRatio === void 0) { innerPaddingRatio = 0.2; } + if (useRangePoints === void 0) { useRangePoints = false; } + if (useRangePoints === true) { + return d3.scale.ordinal() + .rangePoints([0, pixelSpan], outerPaddingRatio) + .domain(dataDomain); + } return d3.scale.ordinal() - .rangeBands([0, pixelSpan], InnerPaddingRatio, outerPaddingRatio) + .rangeBands([0, pixelSpan], innerPaddingRatio, outerPaddingRatio) .domain(dataDomain); } axis_1.createOrdinalScale = createOrdinalScale; @@ -3870,3 +3876,4 @@ var powerbi; })(utils = extensibility.utils || (extensibility.utils = {})); })(extensibility = powerbi.extensibility || (powerbi.extensibility = {})); })(powerbi || (powerbi = {})); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 27f8b34..f4903f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "powerbi-visuals-utils-chartutils", - "version": "1.4.1", + "version": "1.4.2", "lockfileVersion": 1, "dependencies": { "@types/d3": { diff --git a/package.json b/package.json index 79a87f4..d46e333 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "powerbi-visuals-utils-chartutils", - "version": "1.4.1", + "version": "1.4.2", "description": "ChartUtils", "main": "lib/index.js", "repository": { diff --git a/src/axis/axis.ts b/src/axis/axis.ts index 1e6641f..734c0ee 100644 --- a/src/axis/axis.ts +++ b/src/axis/axis.ts @@ -54,7 +54,6 @@ module powerbi.extensibility.utils.chart.axis { const TickLabelPadding: number = 2; const MinOrdinalRectThickness: number = 20; - const InnerPaddingRatio: number = 0.2; /** * Default ranges are for when we have a field chosen for the axis, @@ -760,7 +759,9 @@ module powerbi.extensibility.utils.chart.axis { shouldClamp = !!options.shouldClamp, maxTickCount = options.maxTickCount, disableNice = options.disableNice, - disableNiceOnlyForScale = options.disableNiceOnlyForScale; + disableNiceOnlyForScale = options.disableNiceOnlyForScale, + innerPadding = options.innerPadding, + useRangePoint = options.useRangePoints; let dataType: ValueType = getCategoryValueType(metaDataColumn, isScalar); @@ -786,7 +787,7 @@ module powerbi.extensibility.utils.chart.axis { dataDomain = []; if (isOrdinal(dataType)) { - scale = createOrdinalScale(pixelSpan, dataDomain, categoryThickness ? outerPadding / categoryThickness : 0); + scale = createOrdinalScale(pixelSpan, dataDomain, categoryThickness ? outerPadding / categoryThickness : 0, innerPadding, useRangePoint); } else { scale = createNumericalScale(options.scaleType, pixelSpan, dataDomain, dataType, outerPadding, bestTickCount); @@ -824,7 +825,7 @@ module powerbi.extensibility.utils.chart.axis { scale = createLinearScale(pixelSpan, scalarDomain, outerPadding, null, shouldClamp); // DO NOT PASS TICKCOUNT } else if (dataType.text || dataType.dateTime || dataType.numeric || dataType.bool) { - scale = createOrdinalScale(pixelSpan, scalarDomain, categoryThickness ? outerPadding / categoryThickness : 0); + scale = createOrdinalScale(pixelSpan, scalarDomain, categoryThickness ? outerPadding / categoryThickness : 0, innerPadding, useRangePoint); bestTickCount = maxTicks === 0 ? 0 : Math.min( scalarDomain.length, @@ -1338,10 +1339,16 @@ module powerbi.extensibility.utils.chart.axis { } } - export function createOrdinalScale(pixelSpan: number, dataDomain: any[], outerPaddingRatio: number = 0): d3.scale.Ordinal { + export function createOrdinalScale(pixelSpan: number, dataDomain: any[], outerPaddingRatio: number = 0, innerPaddingRatio: number = 0.2, useRangePoints: boolean = false): d3.scale.Ordinal { + if (useRangePoints === true) { + return d3.scale.ordinal() + .rangePoints([0, pixelSpan], outerPaddingRatio) + .domain(dataDomain); + } + return d3.scale.ordinal() /* Avoid using rangeRoundBands here as it is adding some extra padding to the axis*/ - .rangeBands([0, pixelSpan], InnerPaddingRatio, outerPaddingRatio) + .rangeBands([0, pixelSpan], innerPaddingRatio, outerPaddingRatio) .domain(dataDomain); } diff --git a/src/axis/axisInterfaces.ts b/src/axis/axisInterfaces.ts index b52cc28..f0f6a43 100644 --- a/src/axis/axisInterfaces.ts +++ b/src/axis/axisInterfaces.ts @@ -252,6 +252,10 @@ module powerbi.extensibility.utils.chart.axis { disableNice?: boolean; /** (optional) Disable "niceing" for numeric axis. Disabling nice will be applid only when creating scale obj (bestTickCount will be applied to 'ticks' method) */ disableNiceOnlyForScale?: boolean; + /** (optional) InnerPadding to be applied to the axis.*/ + innerPadding?: number; + /** (optioanl) Apply for using of RangePoints function instead of RangeBands inside CreateOrdinal scale function.*/ + useRangePoints?: boolean; } export enum AxisOrientation { diff --git a/test/axis/axisTest.ts b/test/axis/axisTest.ts index 30408b4..5ffc6c0 100644 --- a/test/axis/axisTest.ts +++ b/test/axis/axisTest.ts @@ -242,7 +242,6 @@ module powerbi.extensibility.utils.chart.axis.test { }; // TODO: add a getValueFn mock to provide to createAxis so we can test tickValue generation - it("create ordinal scale - without categoryThickness", () => { let axisProperties = axisPropertiesBuilder.buildAxisPropertiesString(); @@ -267,6 +266,46 @@ module powerbi.extensibility.utils.chart.axis.test { expect(xLabelMaxWidth).toBeCloseTo(29.7, 1); }); + it("create ordinal scale with defined inner padding", () => { + let axisProperties = axisPropertiesBuilder.buildAxisPropertiesWithDefinedInnerPadding(); + + let scale = axisProperties.scale; + expect(scale).toBeDefined(); + + let values = axisProperties.values; + expect(values).toBeDefined(); + expect(values.length).toEqual(3); + expect(values[0]).toBe("Sun"); + + // Proves scale is ordinal + expect(scale.invert).toBeUndefined(); + + // x label max width is derived from the scale interval + let xLabelMaxWidth = axisProperties.xLabelMaxWidth; + expect(xLabelMaxWidth).toBeDefined(); + expect(xLabelMaxWidth).toBeCloseTo(34, 1); + }); + + it("create ordinal scale with defined inner padding and using of RangePoints", () => { + let axisProperties = axisPropertiesBuilder.buildAxisPropertiesWithRangePointsUsing(); + + let scale = axisProperties.scale; + expect(scale).toBeDefined(); + + let values = axisProperties.values; + expect(values).toBeDefined(); + expect(values.length).toEqual(3); + expect(values[0]).toBe("Sun"); + + // Proves scale is ordinal + expect(scale.invert).toBeUndefined(); + + // x label max width is derived from the scale interval + let xLabelMaxWidth = axisProperties.xLabelMaxWidth; + expect(xLabelMaxWidth).toBeDefined(); + expect(xLabelMaxWidth).toBeCloseTo(44, 1); + }); + it("create ordinal scale with linear values", () => { let axisProperties = axisPropertiesBuilder.buildAxisPropertiesNumber(); diff --git a/test/axis/helpers/axisPropertiesBuilder.ts b/test/axis/helpers/axisPropertiesBuilder.ts index 9b3c2a9..856eba2 100644 --- a/test/axis/helpers/axisPropertiesBuilder.ts +++ b/test/axis/helpers/axisPropertiesBuilder.ts @@ -218,6 +218,19 @@ module powerbi.extensibility.utils.chart.axis.test.helper { return axis.createAxis(axisOptions); } + export function buildAxisPropertiesWithDefinedInnerPadding(): IAxisProperties { + let axisOptions = getAxisOptions(metaDataColumnText); + axisOptions.innerPadding = 0.5; + return axis.createAxis(axisOptions); + } + + export function buildAxisPropertiesWithRangePointsUsing(): IAxisProperties { + let axisOptions = getAxisOptions(metaDataColumnText); + axisOptions.innerPadding = 0.5; + axisOptions.useRangePoints = true; + return axis.createAxis(axisOptions); + } + export function buildAxisPropertiesNumeric( dataDomain: any[], categoryThickness?: number, From b271b8aa9c7b140a71d62cf87257f396dc181b3c Mon Sep 17 00:00:00 2001 From: Evgenii Elkin Date: Wed, 11 Oct 2017 12:26:23 +0300 Subject: [PATCH 2/3] Style fixes --- test/axis/axisTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/axis/axisTest.ts b/test/axis/axisTest.ts index 5ffc6c0..0c4d400 100644 --- a/test/axis/axisTest.ts +++ b/test/axis/axisTest.ts @@ -296,7 +296,7 @@ module powerbi.extensibility.utils.chart.axis.test { expect(values).toBeDefined(); expect(values.length).toEqual(3); expect(values[0]).toBe("Sun"); - + // Proves scale is ordinal expect(scale.invert).toBeUndefined(); From 9bd5a65a823b051eed4053fecccc20e64699a584 Mon Sep 17 00:00:00 2001 From: Evgenii Elkin Date: Wed, 11 Oct 2017 14:33:48 +0300 Subject: [PATCH 3/3] Version was increased --- CHANGELOG.md | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 894b5f1..f534c91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.4.2 +## 1.5.0 * Added two new optional parameters for CreateScale function -- innerPadding and useRangePoint. The first lets set inner padding for scale instead of recieve it from constant. The second lets use rangePoint instead of rangeBands function for creation of ordinal scale. ## 1.4.0 diff --git a/package-lock.json b/package-lock.json index f4903f7..a504c6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "powerbi-visuals-utils-chartutils", - "version": "1.4.2", + "version": "1.5.0", "lockfileVersion": 1, "dependencies": { "@types/d3": { diff --git a/package.json b/package.json index d46e333..c06b473 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "powerbi-visuals-utils-chartutils", - "version": "1.4.2", + "version": "1.5.0", "description": "ChartUtils", "main": "lib/index.js", "repository": {