Skip to content

Commit

Permalink
feat(data): Intent to ship data.label multiline
Browse files Browse the repository at this point in the history
- Implement multiline using '\n'
- Update description for line break

Ref naver#1784
  • Loading branch information
netil committed Nov 17, 2020
1 parent bc56479 commit e232601
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 18 deletions.
21 changes: 18 additions & 3 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -2108,9 +2108,7 @@ setTimeout(function() {chart.resize();}, 3000)
labels: {
// format: function(v, id, i, j) { return "Default Format"; },
format: {
data1: function(x) {
return d3.format('$')(x);
}
data1: function(x) { return d3.format('$')(x); }
// data1: function(v, id, i, j) { return "Format for data1"; },
}
}
Expand All @@ -2122,6 +2120,23 @@ setTimeout(function() {chart.resize();}, 3000)
}
}
},
DataLabelMultiline: {
options: {
data: {
columns: [
["data1", 30,400, -200, -100, 150, 250],
],
type: "line",
labels: {
format: (v, id ,i, j) => {
return v > 0 ?
"Ipsum is\nsimply dummy text" :
"Lorem Ipsum is simply dummy text";
}
}
}
}
},
DataLabelPosition: [
{
options: {
Expand Down
42 changes: 32 additions & 10 deletions src/ChartInternal/internals/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from "d3-selection";
import {KEY} from "../../module/Cache";
import CLASS from "../../config/classes";
import {capitalize, getBoundingRect, getRandom, isNumber, isObject, isString, getTranslation} from "../../module/util";
import {capitalize, getBoundingRect, getRandom, isNumber, isObject, isString, getTranslation, setTextValue} from "../../module/util";
import {AxisType} from "../../../types/types";


Expand Down Expand Up @@ -82,10 +82,18 @@ export default {
.attr("text-anchor", d => (config.axis_rotated ? (d.value < 0 ? "end" : "start") : "middle"))
.style("fill", $$.updateTextColor.bind($$))
.style("fill-opacity", "0")
.text((d, i, j) => {
const value = $$.isBubbleZType(d) ? $$.getBubbleZData(d.value, "z") : d.value;

return $$.dataLabelFormat(d.id)(value, d.id, i, j);
.call(selection => {
selection.each(function(d, i, j) {
let value = $$.isBubbleZType(d) ? $$.getBubbleZData(d.value, "z") : d.value;

value = $$.dataLabelFormat(d.id)(value, d.id, i, j);

if (isNumber(value)) {
this.textContent = value;
} else {
setTextValue(d3Select(this), value);
}
});
});
},

Expand Down Expand Up @@ -121,15 +129,29 @@ export default {
const t: any = getRandom();
const opacityForText = forFlow ? 0 : $$.opacityForText.bind($$);

$$.$el.text.each(function(d, i: number) {
$$.$el.text.each(function() {
const text = d3Select(this);

// do not apply transition for newly added text elements
(withTransition && text.attr("x") ? text.transition(t) : text)
.attr("x", x.bind(this)(d, i))
.attr("y", d => y.bind(this)(d, i))
.style("fill", $$.updateTextColor.bind($$))
.style("fill-opacity", opacityForText);
.call(selection => {
selection.each(function(d, i) {
d3Select(this)
.style("fill", $$.updateTextColor.bind($$))
.style("fill-opacity", opacityForText);

const posX = x.bind(this)(d, i);
const posY = y.bind(this)(d, i);

// when is multiline
if (this.children.length) {
this.setAttribute("transform", `translate(${posX} ${posY})`);
} else {
this.setAttribute("x", posX);
this.setAttribute("y", posY);
}
});
});
});

// need to return 'true' as of being pushed to the redraw list
Expand Down
10 changes: 8 additions & 2 deletions src/config/Options/data/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,8 @@ export default {
* @property {boolean} [data.labels=false] Show or hide labels on each data points
* @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>
* The formatter function receives 4 arguments such as v, id, i, j and it **must return a string**(`\n` character will be used as line break) that will be shown as the label.<br><br>
* 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.
* - `i` is the index of the data point where the label is shown.
Expand All @@ -297,6 +298,7 @@ export default {
* @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataLabel)
* @see [Demo: label colors](https://naver.github.io/billboard.js/demo/#Data.DataLabelColors)
* @see [Demo: label format](https://naver.github.io/billboard.js/demo/#Data.DataLabelFormat)
* @see [Demo: label multiline](https://naver.github.io/billboard.js/demo/#Data.DataLabelMultiline)
* @see [Demo: label overlap](https://naver.github.io/billboard.js/demo/#Data.DataLabelOverlap)
* @see [Demo: label position](https://naver.github.io/billboard.js/demo/#Data.DataLabelPosition)
* @example
Expand All @@ -305,7 +307,11 @@ export default {
*
* // or set specific options
* labels: {
* format: function(v, id, i, j) { ... },
* format: function(v, id, i, j) {
* ...
* // to multiline, return with '\n' character
* return "Line1\nLine2";
* },
*
* // it's possible to set for each data
* format: {
Expand Down
2 changes: 1 addition & 1 deletion src/config/Options/shape/donut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default {
* @property {number} [donut.expand.rate=0.98] Set expand rate.
* @property {number} [donut.expand.duration=50] Set expand transition time in ms.
* @property {number} [donut.width] Set width of donut chart.
* @property {string} [donut.title=""] Set title of donut chart. Use `\n` character to enter line break.
* @property {string} [donut.title=""] Set title of donut chart. Use `\n` character for line break.
* @property {number} [donut.padAngle=0] Set padding between data.
* @property {number} [donut.startingAngle=0] Set starting angle where data draws.
* @example
Expand Down
2 changes: 1 addition & 1 deletion src/config/Options/shape/gauge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default {
* @property {number} [gauge.min=0] Set min value of the gauge.
* @property {number} [gauge.max=100] Set max value of the gauge.
* @property {number} [gauge.startingAngle=-1 * Math.PI / 2] Set starting angle where data draws.
* @property {string} [gauge.title=""] Set title of gauge chart. Use `\n` character to enter line break.
* @property {string} [gauge.title=""] Set title of gauge chart. Use `\n` character for line break.
* @property {string} [gauge.units] Set units of the gauge.
* @property {number} [gauge.width] Set width of gauge chart.
* @property {string} [gauge.type="single"] Set type of gauge to be displayed.<br><br>
Expand Down
39 changes: 39 additions & 0 deletions test/internals/data-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1999,4 +1999,43 @@ describe("DATA", () => {
expect(emptyLabelText.empty()).to.be.true;
});
});

describe("Multilined data.label text", () => {
before(() => {
args = {
data: {
columns: [
["x1", 30,400, -200, -100, 150, 250],
],
type: "line",
labels: {
format: (v, id ,i, j) => {
return v > 0 ?
"Ipsum is\nsimply dummy text" :
"Lorem Ipsum is simply dummy text";
}
}
}
}
});

it("label texts should be multilined correctly.", () => {
chart.$.text.texts.each(function(d) {
if (d.value > 0) {
expect(this.children.length).to.be.equal(2);

expect(this.getAttribute("transform")).to.not.be.null;
expect(this.getAttribute("x")).to.be.null;
expect(this.getAttribute("y")).to.be.null;
} else {
expect(this.children.length).to.be.equal(0);

expect(this.getAttribute("transform")).to.be.null;
expect(this.getAttribute("x")).to.not.be.null;
expect(this.getAttribute("y")).to.not.be.null;
}

});
});
});
});
8 changes: 7 additions & 1 deletion types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1402,7 +1402,13 @@ export interface Data {
colors?: string | { [key: string]: string };

/**
* Formatter function can be defined for each data by specifying as an object and D3 formatter function can be set (e.g. d3.format('$'))
* The formatter function receives 4 arguments such as v, id, i, j and it **must return a string**(`\n` character will be used as line break) that will be shown as the label.<br><br>
* 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.
* - `i` is the index of the data point where the label is shown.
* - `j` is the sub index of the data point where the label is shown.<br><br>
* Formatter function can be defined for each data by specifying as an object and D3 formatter function can be set (ex. d3.format('$'))
*/
format?: FormatFunction | { [key: string]: FormatFunction };

Expand Down

0 comments on commit e232601

Please sign in to comment.