Skip to content

Commit

Permalink
feat(data): Intent to ship data.labels.centered
Browse files Browse the repository at this point in the history
Implementation on data label texts align for bar type

Fix #876
  • Loading branch information
netil committed May 10, 2019
1 parent 56c2f99 commit cbe95b7
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 27 deletions.
64 changes: 45 additions & 19 deletions demo/demo.js
Expand Up @@ -1703,27 +1703,53 @@ var demos = {
];
}
},
DataLabel: {
options: {
data: {
columns: [
["data1", 30, -200, -100, 400, 150, 250],
["data2", -50, 150, -150, 150, -50, -150],
["data3", -100, 100, -40, 100, -150, -50]
],
groups: [
["data1", "data2"]
],
type: "bar",
labels: true
},
grid: {
y: {
lines: [{value: 0}]
DataLabel: [
{
options: {
data: {
columns: [
["data1", 30, -200, -100, 400, 150, 250],
["data2", -50, 150, -150, 150, -50, -150],
["data3", -100, 100, -40, 100, -150, -50]
],
groups: [
["data1", "data2"]
],
type: "bar",
labels: true
},
grid: {
y: {
lines: [{value: 0}]
}
}
}
},
{
options: {
data: {
columns: [
["data1", 230, -200, 400],
["data2", -250, 350, -170],
["data3", -123, 100, -240]
],
groups: [
["data1", "data2"]
],
type: "bar",
labels: {
colors: "white",
centered: true
}
},
grid: {
y: {
lines: [{value: 0}]
}
}
}
}
},
],
DataLabelColors: [
{
options: {
Expand Down Expand Up @@ -2532,7 +2558,7 @@ d3.select(".chart_area")
"01-10-2019 01:00",
"01-10-2019 01:30",
"01-10-2019 02:00",
"01-10-2019 02:30",
"01-10-2019 02:30",
"01-10-2019 03:00",
"01-10-2019 03:30",
"01-10-2019 04:00",
Expand Down
45 changes: 45 additions & 0 deletions spec/internals/data-spec.js
Expand Up @@ -729,6 +729,51 @@ describe("DATA", () => {
.each(checkXY(expectedTextX[key], expectedTextY[key], "", 4));
});
});

it("set options data.labels.centered=true", () => {
args.data.labels = {
centered: true,
colors: "white"
};
});

it("check for data label text position", () => {
const index = 1;
let j = 0;
const bars = chart.$.bar.bars.filter(d => d.index === index);
const texts = chart.$.text.texts.filter(d => d.index === index).nodes();

bars.each(function(d) {
const barRect = this.getBoundingClientRect();
const textRect = texts[j++].getBoundingClientRect();

expect(
(barRect.height / 2) - (textRect.y - barRect.y)
).to.be.closeTo(textRect.height / 2, 3);
});
});

it("set options axis.rotated=true", () => {
args.axis = {
rotated: true
}
});

it("check for data label text position when is rotated", () => {
const index = 1;
let j = 0;
const bars = chart.$.bar.bars.filter(d => d.index === index);
const texts = chart.$.text.texts.filter(d => d.index === index).nodes();

bars.each(function(d) {
const barRect = this.getBoundingClientRect();
const textRect = texts[j++].getBoundingClientRect();

expect(
(barRect.width / 2) - (textRect.x - barRect.x)
).to.be.closeTo(textRect.width / 2, 3);
});
});
});

describe("for all targets", () => {
Expand Down
8 changes: 6 additions & 2 deletions src/config/Options.js
Expand Up @@ -560,7 +560,8 @@ export default class Options {
* @memberof Options
* @type {Object}
* @property {Boolean} [data.labels=false] Show or hide labels on each data points
* @property {Function} [data.labels.format={}] Set formatter function for data labels.<br>
* @property {Boolean} [data.labels.centered=false] Centerize labels on `bar` shape. (**NOTE:** works only for 'bar' type)
* @property {Function} [data.labels.format] Set formatter function for data labels.<br>
* The formatter function receives 4 arguments such as v, id, i, j and it must return a string that will be shown as the label. The arguments are:<br>
* - `v` is the value of the data point where the label is shown.
* - `id` is the id of the data where the label is shown.
Expand Down Expand Up @@ -591,6 +592,9 @@ export default class Options {
* ...
* },
*
* // align text to center of the 'bar' shape (works only for 'bar' type)
* centered: true,
*
* // apply for all label texts
* colors: "red",
*
Expand Down Expand Up @@ -1457,7 +1461,7 @@ export default class Options {
axis_x_categories: [],

/**
* Centerise ticks on category axis.
* centerize ticks on category axis.
* @name axis鈥鈥ick鈥entered
* @memberof Options
* @type {Boolean}
Expand Down
62 changes: 56 additions & 6 deletions src/internals/text.js
Expand Up @@ -181,6 +181,45 @@ extend(ChartInternal.prototype, {
};
},

/**
* Get centerized text position for bar type data.label.text
* @private
* @param {Object} d Data object
* @param {Array} points Data points position
* @param {HTMLElement} textElement Data label text element
* @returns {Number} Position value
*/
getCenteredTextPos(d, points, textElement) {
const $$ = this;
const config = $$.config;
const isRotated = config.axis_rotated;

if (config.data_labels.centered && $$.isBarType(d)) {
const rect = textElement.getBoundingClientRect();
const isPositive = d.value >= 0;

if (isRotated) {
const w = (
isPositive ?
points[1][1] - points[0][1] :
points[0][1] - points[1][1]
) / 2 + (rect.width / 2);

return isPositive ? -w - 3 : w + 4;
} else {
const h = (
isPositive ?
points[0][1] - points[1][1] :
points[1][1] - points[0][1]
) / 2 + (rect.height / 2);

return isPositive ? h : -h - 4;
}
}

return 0;
},

/**
* Gets the x coordinate of the text
* @private
Expand All @@ -192,10 +231,11 @@ extend(ChartInternal.prototype, {
getXForText(points, d, textElement) {
const $$ = this;
const config = $$.config;
const isRotated = config.axis_rotated;
let xPos;
let padding;

if (config.axis_rotated) {
if (isRotated) {
padding = $$.isBarType(d) ? 4 : 6;
xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);
} else {
Expand All @@ -210,6 +250,10 @@ extend(ChartInternal.prototype, {
}
}

if (isRotated) {
xPos += $$.getCenteredTextPos(d, points, textElement);
}

return xPos + (config.data_labels_position.x || 0);
},

Expand All @@ -224,12 +268,14 @@ extend(ChartInternal.prototype, {
getYForText(points, d, textElement) {
const $$ = this;
const config = $$.config;
const isRotated = config.axis_rotated;
const r = config.point_r;
const rect = textElement.getBoundingClientRect();
let baseY = 3;
let yPos;

if (config.axis_rotated) {
yPos = (points[0][0] + points[2][0] + textElement.getBoundingClientRect().height * 0.6) / 2;
if (isRotated) {
yPos = (points[0][0] + points[2][0] + rect.height * 0.6) / 2;
} else {
yPos = points[2][1];

Expand All @@ -238,7 +284,7 @@ extend(ChartInternal.prototype, {
}

if (d.value < 0 || (d.value === 0 && !$$.hasPositiveValue)) {
yPos += textElement.getBoundingClientRect().height;
yPos += rect.height;

if ($$.isBarType(d) && $$.isSafari()) {
yPos -= baseY;
Expand All @@ -259,8 +305,8 @@ extend(ChartInternal.prototype, {
}

// show labels regardless of the domain if value is null
if (d.value === null && !config.axis_rotated) {
const boxHeight = textElement.getBoundingClientRect().height;
if (d.value === null && !isRotated) {
const boxHeight = rect.height;

if (yPos < boxHeight) {
yPos = boxHeight;
Expand All @@ -269,6 +315,10 @@ extend(ChartInternal.prototype, {
}
}

if (!isRotated) {
yPos += $$.getCenteredTextPos(d, points, textElement);
}

return yPos + (config.data_labels_position.y || 0);
}
});
5 changes: 5 additions & 0 deletions types/options.d.ts
Expand Up @@ -1174,6 +1174,11 @@ export interface Data {
* - j is the sub index of the data point where the label is shown.
*/
labels?: boolean | {
/**
* Centerize labels on `bar` shape. (**NOTE:** works only for 'bar' type)
*/
centered?: boolean;

/**
* Set label text colors.
*/
Expand Down

0 comments on commit cbe95b7

Please sign in to comment.