Skip to content

Commit

Permalink
feat(bar): Intent to ship bar.indices.removeNull
Browse files Browse the repository at this point in the history
Implement bar.indices.removeNull option, where
make positioning each bar shape's position on each tick
removing nullish values.

Close #1687
  • Loading branch information
netil authored Dec 21, 2021
1 parent 1e2df4e commit b16605d
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 48 deletions.
36 changes: 36 additions & 0 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3741,6 +3741,42 @@ d3.select(".chart_area")
]
},
BarChartOptions: {
BarIndices: [
{
options: {
data: {
columns: [
['data1', 4, null, 4],
['data2', null, 3, null],
['data3', 1, 4, 4]
],
type: "bar"
},
bar: {
indices: {
removeNull: true
}
}
}
},
{
options: {
data: {
columns: [
['data1', 4, null, 4],
['data2', null, 3, null],
['data3', 1, 4, 4]
],
type: "bar"
},
bar: {
indices: {
removeNull: false
}
}
}
},
],
BarPadding: {
options: {
data: {
Expand Down
7 changes: 3 additions & 4 deletions src/Chart/api/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
*/
import {DataItem} from "../../../types/types";
import {extend, isUndefined, isArray} from "../../module/util";

type DataParam = {x: number, value: number, id: string, index: number}[];
import {IDataRow} from "../../ChartInternal/data/IData";

/**
* Get data loaded in the chart.
Expand Down Expand Up @@ -173,7 +172,7 @@ extend(data, {
* chart.data.min();
* // --> [{x: 0, value: 30, id: "data1", index: 0}, ...]
*/
min: function(): DataParam {
min: function(): IDataRow[] {
return this.internal.getMinMaxData().min;
},

Expand All @@ -188,7 +187,7 @@ extend(data, {
* chart.data.max();
* // --> [{x: 3, value: 400, id: "data1", index: 3}, ...]
*/
max: function(): DataParam {
max: function(): IDataRow[] {
return this.internal.getMinMaxData().max;
}
});
Expand Down
9 changes: 9 additions & 0 deletions src/ChartInternal/data/IData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,12 @@ export interface IGridData {
text: string;
value: number;
}

export interface IDataIndice {
[key: string]: number;
__max__: number;
}

export type TIndices = {} | {
[key:string]: IDataIndice
};
2 changes: 1 addition & 1 deletion src/ChartInternal/data/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export default {
.map(t => $$.addName($$.getValueOnIndex(t.values, index)));

if (filterNull) {
value = value.filter(v => isValue(v.value));
value = value.filter(v => v && "value" in v && isValue(v.value));
}

return value;
Expand Down
35 changes: 26 additions & 9 deletions src/ChartInternal/shape/shape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {select as d3Select} from "d3-selection";
import {d3Selection} from "../../../types/types";
import CLASS from "../../config/classes";
import {capitalize, getPointer, getRectSegList, getUnique, isObjectType, isNumber, isValue, isUndefined, notEmpty} from "../../module/util";
import {IDataRow, IDataIndice, TIndices} from "../data/IData";

export default {
/**
Expand Down Expand Up @@ -88,12 +89,12 @@ export default {
* @param {Function} typeFilter Chart type filter function
* @returns {object} Indices object with its position
*/
getShapeIndices(typeFilter): {[key: string]: number} {
getShapeIndices(typeFilter): TIndices {
const $$ = this;
const {config} = $$;
const xs = config.data_xs;
const hasXs = notEmpty(xs);
const indices = {};
const indices: TIndices = {};
let i: any = hasXs ? {} : 0;

if (hasXs) {
Expand Down Expand Up @@ -134,12 +135,28 @@ export default {
/**
* Get indices value based on data ID value
* @param {object} indices Indices object
* @param {string} id Data id value
* @param {object} d Data row
* @param {string} caller Caller function name (Used only for 'sparkline' plugin)
* @returns {object} Indices object
* @private
*/
getIndices(indices, id: string) {
const xs = this.config.data_xs;
getIndices(indices: TIndices, d: IDataRow, caller?: string): IDataIndice { // eslint-disable-line
const $$ = this;
const {data_xs: xs, bar_indices_removeNull: removeNull} = $$.config;
const {id, index} = d;

if ($$.isBarType(id) && removeNull) {
const ind = {} as IDataIndice;

// redefine bar indices order
$$.getAllValuesOnIndex(index, true)
.forEach((v, i) => {
ind[v.id] = i;
ind.__max__ = i;
});

return ind;
}

return notEmpty(xs) ?
indices[xs[id]] : indices;
Expand All @@ -151,12 +168,12 @@ export default {
* @returns {number} Max number
* @private
*/
getIndicesMax(indices): number {
getIndicesMax(indices: TIndices | IDataIndice): number {
return notEmpty(this.config.data_xs) ?
// if is multiple xs, return total sum of xs' __max__ value
Object.keys(indices)
.map(v => indices[v].__max__ || 0)
.reduce((acc, curr) => acc + curr) : indices.__max__;
.reduce((acc, curr) => acc + curr) : (indices as IDataIndice).__max__;
},

getShapeX(offset, indices, isSub?: boolean): (d) => number {
Expand All @@ -170,7 +187,7 @@ export default {
);

return d => {
const ind = $$.getIndices(indices, d.id, "getShapeX");
const ind = $$.getIndices(indices, d, "getShapeX");
const index = d.id in ind ? ind[d.id] : 0;
const targetsNum = (ind.__max__ || 0) + 1;
let x = 0;
Expand Down Expand Up @@ -289,7 +306,7 @@ export default {

return (d, idx) => {
const {id, value, x} = d;
const ind = $$.getIndices(indices, id);
const ind = $$.getIndices(indices, d);
const scale = $$.getYScaleById(id, isSub);

if ($$.isBarRangeType(d)) {
Expand Down
4 changes: 2 additions & 2 deletions src/Plugin/sparkline/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ export default class Sparkline extends Plugin {
const {getBarW, getIndices} = $$;

// override internal methods to positioning bars
$$.getIndices = function(indices, id, caller) {
return caller === "getShapeX" ? {} : getIndices.call(this, indices, id);
$$.getIndices = function(indices, d, caller) {
return caller === "getShapeX" ? {} : getIndices.call(this, indices, d);
};

$$.getBarW = function(type, axis) {
Expand Down
8 changes: 8 additions & 0 deletions src/config/Options/shape/bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default {
* @memberof Options
* @type {object}
* @property {object} bar Bar object
* @property {number} [bar.indices.removeNull=false] Remove nullish data on bar indices positions.
* @property {number} [bar.label.threshold=0] Set threshold ratio to show/hide labels.
* @property {number} [bar.padding=0] The padding pixel value between each bar.
* @property {number} [bar.radius] Set the radius of bar edge in pixel.
Expand All @@ -27,12 +28,18 @@ export default {
* @property {number} [bar.width.dataname.ratio=0.6] Change the width of bar chart by ratio.
* @property {number} [bar.width.dataname.max] The maximum width value for ratio.
* @property {boolean} [bar.zerobased=true] Set if min or max value will be 0 on bar chart.
* @see [Demo: bar indices](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarIndices)
* @see [Demo: bar padding](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarPadding)
* @see [Demo: bar radius](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarRadius)
* @see [Demo: bar width](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarWidth)
* @see [Demo: bar width variant](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarWidthVariant)
* @example
* bar: {
* // remove nullish data on bar indices postions
* indices: {
* removeNull: true
* },
*
* padding: 1,
*
* // bar radius
Expand Down Expand Up @@ -72,6 +79,7 @@ export default {
* }
*/
bar_label_threshold: 0,
bar_indices_removeNull: false,
bar_padding: 0,
bar_radius: <number|{ratio: number}|undefined> undefined,
bar_radius_ratio: <number|undefined> undefined,
Expand Down
32 changes: 32 additions & 0 deletions test/shape/bar-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,38 @@ describe("SHAPE BAR", () => {
});
});

describe("bar indices", () => {
before(() => {
args = {
data: {
columns: [
["data1", 4, null, 4],
["data2", null, 3, null],
["data3", 1, 4, 4]
],
type: "bar"
},
bar: {
indices: {
removeNull: true
}
}
}
});

it("should redefined bar indices removing nullish values.", () => {
const {$: {bar}, internal} = chart;

bar.bars.each(d => {
const indices = internal.getIndices(null, d);

expect(indices.__max__).to.be.equal(1);
expect(indices.data3).to.be.equal(1);
expect(indices["data1" in indices ? "data1" : "data2"]).to.be.equal(0);
});
});
});

describe("bar radius", () => {
before(() => {
args = {
Expand Down
64 changes: 32 additions & 32 deletions types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,31 +275,6 @@ export interface ChartOptions {
};

bar?: {
/**
* Change the width of bar chart. If ratio is specified, change the width of bar chart by ratio.
*/
width?: number | {
/**
* Set the width of each bar by ratio
*/
ratio: number;

/**
* Set max width of each bar
*/
max?: number;
} | {
/**
* Set the width option for specific dataset
*/
[key: string]: number | {
ratio: number;
max: number;
}
};

headers?: Array<{ [key: string]: string; }>;

/**
* Set threshold ratio to show/hide labels.
*/
Expand All @@ -308,14 +283,11 @@ export interface ChartOptions {
}

/**
* Set if min or max value will be 0 on bar chart.
*/
zerobased?: boolean;

/**
* Set space between bars in bar charts
* Remove nullish data on bar indices positions.
*/
space?: number;
indices?: {
removeNull?: boolean;
}

/**
* The padding pixel value between each bar.
Expand All @@ -337,6 +309,34 @@ export interface ChartOptions {
* The senstivity offset value for interaction boundary.
*/
sensitivity?: number;

/**
* Change the width of bar chart. If ratio is specified, change the width of bar chart by ratio.
*/
width?: number | {
/**
* Set the width of each bar by ratio
*/
ratio: number;

/**
* Set max width of each bar
*/
max?: number;
} | {
/**
* Set the width option for specific dataset
*/
[key: string]: number | {
ratio: number;
max: number;
}
};

/**
* Set if min or max value will be 0 on bar chart.
*/
zerobased?: boolean;
};

bubble?: {
Expand Down

0 comments on commit b16605d

Please sign in to comment.