Skip to content

Commit

Permalink
feat(region): Enhance regions accept category range
Browse files Browse the repository at this point in the history
- Enhance regions start/end to use category name values
- Reinforce documentation and demo

Ref naver#3920
  • Loading branch information
netil authored and netil committed Jan 14, 2025
1 parent 477b823 commit 4ac2ae9
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 100 deletions.
102 changes: 73 additions & 29 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4396,36 +4396,80 @@ d3.select(".chart_area")
},

Region: {
Region: {
options: {
data: {
columns: [
["data1", 30, 200, 100, 400, 150, 250, 400],
["data2", 830, 1200, 1100, 1400, 1150, 1250, 1500]
],
type: "line",
axes: {
data2: "y2"
}
},
axis: {
y2: {
show: true
}
},
regions: [
{axis: "x", end: 1, class: "regionX"},
{axis: "x", start: 2, end: 4, class: "regionX"},
{axis: "x", start: 5, class: "regionX"},
{axis: "y", end: 50, class: "regionY"},
{axis: "y", start: 80, end: 140, class: "regionY"},
{axis: "y", start: 400, class: "regionY"},
{axis: "y2", end: 900, class: "regionY2"},
{axis: "y2", start: 1150, end: 1250, class: "regionY2"},
{axis: "y2", start: 1300, class: "regionY2"}
]
Region: [
{
options: {
data: {
columns: [
["data1", 30, 200, 100, 400, 150, 250, 400],
["data2", 830, 1200, 1100, 1400, 1150, 1250, 1500]
],
type: "line",
axes: {
data2: "y2"
}
},
axis: {
y2: {
show: true
}
},
regions: [
{axis: "x", end: 1, class: "regionX"},
{axis: "x", start: 2, end: 4, class: "regionX"},
{axis: "x", start: 5, class: "regionX"},
{axis: "y", end: 50, class: "regionY"},
{axis: "y", start: 80, end: 140, class: "regionY"},
{axis: "y", start: 400, class: "regionY"},
{axis: "y2", end: 900, class: "regionY2"},
{axis: "y2", start: 1150, end: 1250, class: "regionY2"},
{axis: "y2", start: 1300, class: "regionY2"}
]
}
},
{
options: {
data: {
columns: [
["data1", 30, 200, 100, 400, 150, 250],
["data2", 100, 150, 130, 200, 220, 190]
],
axes: {
data2: "y2"
},
type: "line",
colors: {
data1: "#ff0000"
}
},
axis: {
x: {
type: "category",
categories: [
"cat1",
"cat2",
"cat3",
"cat4",
"cat5",
"cat6"
]
}
},
regions: [
{
axis: "x",
start: "cat2",
end: "cat3"
},
{
axis: "x",
start: "cat5",
end: 5
}
]
}
}
},
],
RegionLabel: {
options: {
data: {
Expand Down
4 changes: 2 additions & 2 deletions src/Chart/api/regions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function regionsFn(regions: RegionsParam, isAdd = false): RegionsParam {
* @function regions
* @instance
* @memberof Chart
* @param {Array} regions Regions will be replaced with this argument. The format of this argument is the same as regions.
* @param {Array} regions Regions will be replaced with this argument. The format of this argument is the same as [regions](./Options.html#.regions) option.
* @returns {Array} regions
* @example
* // Show 2 regions
Expand Down Expand Up @@ -65,7 +65,7 @@ extend(regions, {
* @function regions․add
* @instance
* @memberof Chart
* @param {Array|object} regions New region will be added. The format of this argument is the same as regions and it's possible to give an Object if only one region will be added.
* @param {Array|object} regions New region will be added. The format of this argument is the same as [regions](./Options.html#.regions) and it's possible to give an Object if only one region will be added.
* @returns {Array} regions
* @example
* // Add a new region
Expand Down
90 changes: 44 additions & 46 deletions src/ChartInternal/internals/region.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* billboard.js project is licensed under the MIT license
*/
import {select as d3Select} from "d3-selection"; // selection
import type {AxisType, RegionsType} from "../../../types/types";
import type {RegionOptions} from "../../../types/options";
import type {AxisType} from "../../../types/types";
import {$REGION} from "../../config/classes";
import {isValue, parseDate} from "../../module/util";

Expand Down Expand Up @@ -98,76 +99,73 @@ export default {
];
},

getRegionXY(type: AxisType, d: RegionsType): number {
const $$ = this;
const {config, scale} = $$;
const isRotated = config.axis_rotated;
const isX = type === "x";
let key = "start";
let currScale;
let pos = 0;

if (d.axis === "y" || d.axis === "y2") {
if (!isX) {
key = "end";
}

if ((isX ? isRotated : !isRotated) && key in d) {
currScale = scale[d.axis];
pos = currScale(d[key]);
}
} else if ((isX ? !isRotated : isRotated) && key in d) {
currScale = scale.zoom || scale.x;
pos = currScale($$.axis.isTimeSeries() ? parseDate.call($$, d[key]) : d[key]);
}
regionX(d: RegionOptions): number {
return this.getRegionSize("x", d);
},

return pos;
regionY(d: RegionOptions): number {
return this.getRegionSize("y", d);
},

regionX(d: RegionsType): number {
return this.getRegionXY("x", d);
regionWidth(d: RegionOptions): number {
return this.getRegionSize("width", d);
},

regionY(d: RegionsType): number {
return this.getRegionXY("y", d);
regionHeight(d: RegionOptions): number {
return this.getRegionSize("height", d);
},

getRegionSize(type: "width" | "height", d: RegionsType): number {
/**
* Get Region size according start/end position
* @param {string} type Type string
* @param {ojbect} d Data object
* @returns {number}
* @private
*/
getRegionSize(type: AxisType | "width" | "height", d: RegionOptions): number {
const $$ = this;
const {config, scale, state} = $$;
const isRotated = config.axis_rotated;
const isWidth = type === "width";
const start = $$[isWidth ? "regionX" : "regionY"](d);
const isAxisType = /(x|y|y2)/.test(type);

const isType = isAxisType ? type === "x" : type === "width";
const start = !isAxisType && $$[isType ? "regionX" : "regionY"](d);
let key = isAxisType ? "start" : "end";
let pos = isAxisType ? 0 : state[type];
let currScale;
let key = "end";
let end = state[type];

if (d.axis === "y" || d.axis === "y2") {
if (!isWidth) {
if (!isAxisType && !isType) {
key = "start";
} else if (isAxisType && !isType) {
key = "end";
}

if ((isWidth ? isRotated : !isRotated) && key in d) {
if ((isType ? isRotated : !isRotated) && key in d) {
currScale = scale[d.axis];
end = currScale(d[key]);
}
} else if ((isWidth ? !isRotated : isRotated) && key in d) {
} else if ((isType ? !isRotated : isRotated) && key in d) {
currScale = scale.zoom || scale.x;
end = currScale($$.axis.isTimeSeries() ? parseDate.call($$, d[key]) : d[key]);
}

return end < start ? 0 : end - start;
},
if (currScale) {
let offset = 0;
pos = d[key];

regionWidth(d: RegionsType): number {
return this.getRegionSize("width", d);
},
if ($$.axis.isTimeSeries(d.axis)) {
pos = parseDate.call($$, pos);
} else if (/(x|width)/.test(type) && $$.axis.isCategorized() && isNaN(pos)) {
pos = config.axis_x_categories.indexOf(pos);
offset = $$.axis.x.tickOffset() * (key === "start" ? -1 : 1);
}

regionHeight(d: RegionsType): number {
return this.getRegionSize("height", d);
pos = currScale(pos) + offset;
}

return isAxisType ? pos : pos < start ? 0 : pos - start;
},

isRegionOnX(d: RegionsType): boolean {
isRegionOnX(d: RegionOptions): boolean {
return !d.axis || d.axis === "x";
}
};
32 changes: 23 additions & 9 deletions src/config/Options/common/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
import type {RegionsType} from "../../../../types/types";
import type {RegionOptions} from "../../../../types/options";

/**
* main config options
Expand Down Expand Up @@ -399,17 +399,31 @@ export default {

/**
* Show rectangles inside the chart.<br><br>
* This option accepts array including object that has axis, start, end and class.
* The keys start, end and class are optional.
* axis must be x, y or y2. start and end should be the value where regions start and end.
* If not specified, the edge values will be used.
* If timeseries x axis, date string, Date object and unixtime integer can be used.
* If class is set, the region element will have it as class.
* - **NOTE:**<br>
* - axis must be x, y or y2. start and end should be the value where regions start and end.
* - If not specified, the edge values will be used.
* - If timeseries x axis, date string, Date object and unixtime integer can be used.
* - If category x axis, category name can be used for start and end.
* - If class is set, the region element will have it as class.
*
* This option accept array of object with below values:
* - `axis {string}`: 'x', 'y', or 'y2'
* - `[start] {number|Date|string}`: Start position of the region. If not set, the start will be the edge of the chart.
* - `[end] {number|Date|string}`: End position of the region. If not set, the end will be the edge of the chart.
* - `[class] {string}`: Class value to apply to the region.
* - `[label] {object}` Lable text option.
* - `text {string}`: Text value.
* - `x {number}`: x Position.
* - `y {number}`: y Position.
* - `color {string}`: Color string.
* - `rotated (boolean)`: Whether rotate label or not.
* @name regions
* @memberof Options
* @type {Array}
* @default []
* @see [Demo](https://naver.github.io/billboard.js/demo/#Region.RegionLabel)
* @see [Demo: Regions](https://naver.github.io/billboard.js/demo/#Region.Region)
* @see [Demo: Regions Timeseries](https://naver.github.io/billboard.js/demo/#Region.RegionWithTimeseries)
* @see [Demo: Regions Label](https://naver.github.io/billboard.js/demo/#Region.RegionLabel)
* @example
* regions: [
* {
Expand All @@ -427,5 +441,5 @@ export default {
* }
* ]
*/
regions: <RegionsType[]>[]
regions: <RegionOptions[]>[]
};
Loading

0 comments on commit 4ac2ae9

Please sign in to comment.