Skip to content

Commit 728e879

Browse files
authored
feat(plugin): Intent to ship TextOverlap
- Split data.labels.overlap into TextOverlap plugin - Update head license comments & describe name for stanford diagram Fix #1048
1 parent 05de6cf commit 728e879

File tree

13 files changed

+328
-172
lines changed

13 files changed

+328
-172
lines changed

demo/demo.js

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,26 +1886,6 @@ var demos = {
18861886
}
18871887
}
18881888
},
1889-
DataLabelOverlap: {
1890-
options: {
1891-
data: {
1892-
columns: [
1893-
["data1", 3, 3.8, 2, 3.8, 15, 2.5, 5.4, 6, 5.5, 2.4],
1894-
["data2", 1.7, 1.0, 10, 20, 8.4, 5, 2.5, 12.3, 8.5, 9.8],
1895-
["data3", 2.3, 15.3, 8.5, 30, 25, 12.0, 5, 8.4, 9.9, 28],
1896-
["data4", 30, 35, 20, 38, 19, 28, 5.6, 8, 5.5, 22],
1897-
["data5", 13, 10, 10, 20, 8, 5, 20, 13, 18.5, 9.8]
1898-
],
1899-
labels:{
1900-
overlap: {
1901-
extent: 8,
1902-
area : 3
1903-
}
1904-
}
1905-
}
1906-
},
1907-
description: "Prevents data label texts overlap using <a href='https://en.wikipedia.org/wiki/Voronoi_diagram' target='_new'>Voronoi layout</a>."
1908-
},
19091889
DataLabelPosition: {
19101890
options: {
19111891
data: {
@@ -2453,6 +2433,33 @@ d3.select(".chart_area")
24532433
"#stanfordDiagram .test-polygon5 { fill: orange; }",
24542434
"#stanfordDiagram .test-polygon5 text { fill: black; }"
24552435
]
2436+
},
2437+
TextOverlap: {
2438+
description: "Prevents data label texts overlap using <a href='https://en.wikipedia.org/wiki/Voronoi_diagram' target='_new'>Voronoi layout</a>.<br>Must load or import plugin before the use.",
2439+
options: {
2440+
data: {
2441+
columns: [
2442+
["data1", 3, 3.8, 2, 3.8, 15, 2.5, 5.4, 6, 5.5, 2.4],
2443+
["data2", 1.7, 1.0, 10, 20, 8.4, 5, 2.5, 12.3, 8.5, 9.8],
2444+
["data3", 2.3, 15.3, 8.5, 30, 25, 12.0, 5, 8.4, 9.9, 28],
2445+
["data4", 30, 35, 20, 38, 19, 28, 5.6, 8, 5.5, 22],
2446+
["data5", 13, 10, 10, 20, 8, 5, 20, 13, 18.5, 9.8]
2447+
],
2448+
labels:{
2449+
overlap: {
2450+
extent: 8,
2451+
area : 3
2452+
}
2453+
}
2454+
},
2455+
_plugins: [{
2456+
textoverlap: {
2457+
selector: ".bb-texts text",
2458+
extent: 8,
2459+
area : 3
2460+
}
2461+
}]
2462+
}
24562463
}
24572464
},
24582465

demo/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ <h4 class="sub_tit">Sample code</h4>
170170
fallback.load({
171171
plugins_stanford: path.map(function(p) {
172172
return p + "plugin/billboardjs-plugin-stanford.js"
173+
}),
174+
plugins_textoverlap: path.map(function(p) {
175+
return p + "plugin/billboardjs-plugin-textoverlap.js"
173176
})
174177
});
175178

spec/internals/data-spec.js

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -557,71 +557,6 @@ describe("DATA", () => {
557557
});
558558
});
559559

560-
it("set options data.labels.overlap", () => {
561-
args.data.labels = {
562-
overlap: false
563-
};
564-
});
565-
566-
it("should move data labels into correct position", () => {
567-
const expectedTextDy = {
568-
data1: ["0.35em", "0.71em", "0.71em"],
569-
data2: ["0.35em", "0.35em", "0.71em"],
570-
data3: ["0.71em", "0.71em", "0.35em"],
571-
data4: ["0.71em", "0.35em", "0.35em"]
572-
};
573-
const expectedTextTransform = {
574-
data1: ["translate(-1, -1)", "translate(-1, 6)", "translate(-1, 6)"],
575-
data2: ["translate(-1, -1)", "translate(-1, -1)", "translate(-1, 6)"],
576-
data3: ["translate(-1, 6)", "translate(-1, 6)", "translate(-1, -1)"],
577-
data4: ["translate(-1, 6)", "translate(-1, -1)", "translate(-1, -1)"]
578-
};
579-
580-
Object.keys(expectedTextDy).forEach(key => {
581-
chart.internal.main.selectAll(`.${CLASS.texts}-${key} text.${CLASS.text}`).each(function(d, i) {
582-
const text = d3.select(this);
583-
584-
expect(text.attr("dy")).to.be.equal(expectedTextDy[key][i]);
585-
expect(text.attr("transform")).to.be.equal(expectedTextTransform[key][i]);
586-
});
587-
});
588-
589-
});
590-
591-
it("set options data.labels.overlap", () => {
592-
args.data.labels = {
593-
overlap: {
594-
extent: 8,
595-
area: 3
596-
}
597-
};
598-
});
599-
600-
it("should move data labels into correct position with specified extent and area", () => {
601-
const expectedTextDy = {
602-
data1: ["0.35em", "0.71em", "0.71em"],
603-
data2: ["0.35em", "0.35em", "0.71em"],
604-
data3: ["0.71em", "0.71em", "0.35em"],
605-
data4: ["0.71em", "0.35em", "0.35em"]
606-
};
607-
const expectedTextTransform = {
608-
data1: ["translate(-8, -8)", "translate(-8, 13)", "translate(-8, 13)"],
609-
data2: ["translate(-8, -8)", "translate(-8, -8)", "translate(-8, 13)"],
610-
data3: ["translate(-8, 13)", "translate(-8, 13)", "translate(-8, -8)"],
611-
data4: ["translate(-8, 13)", "translate(-8, -8)", "translate(-8, -8)"]
612-
};
613-
614-
Object.keys(expectedTextDy).forEach(key => {
615-
chart.internal.main.selectAll(`.${CLASS.texts}-${key} text.${CLASS.text}`).each(function(d, i) {
616-
const text = d3.select(this);
617-
618-
expect(text.attr("dy")).to.be.equal(expectedTextDy[key][i]);
619-
expect(text.attr("transform")).to.be.equal(expectedTextTransform[key][i]);
620-
});
621-
});
622-
623-
});
624-
625560
it("set options data.labels.position", () => {
626561
args.data.labels = {
627562
position: {

spec/plugin/stanford/stanford-elements-spec.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
/**
2+
* Copyright (c) 2017 ~ present NAVER Corp.
3+
* billboard.js project is licensed under the MIT license
4+
*/
15
/* eslint-disable */
26
import util from "../../assets/util";
37
import Stanford from "../../../src/plugin/stanford/index";
48
import CLASS from "../../../src/plugin/stanford/classes";
59

6-
describe("STANFORD ELEMENTS", () => {
10+
describe("PLUGIN: STANFORD ELEMENTS", () => {
711
let chart;
812
const expectedLines = [
913
{x1: 0, y1: 0, x2: 65, y2: 65, class: "line1"},

spec/plugin/stanford/stanford-spec.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
/**
2+
* Copyright (c) 2017 ~ present NAVER Corp.
3+
* billboard.js project is licensed under the MIT license
4+
*/
15
/* eslint-disable */
26
import util from "../../assets/util";
37
import Stanford from "../../../src/plugin/stanford/index";
48
import {compareEpochs, getCentroid, getRegionArea, pointInRegion} from "../../../src/plugin/stanford/util";
59

6-
describe("STANFORD", () => {
10+
describe("PLUGIN: STANFORD", () => {
711
let chart;
812
let stanford = new Stanford({ epochs: [30, 35] });
913
let args = {
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* Copyright (c) 2017 ~ present NAVER Corp.
3+
* billboard.js project is licensed under the MIT license
4+
*/
5+
/* eslint-disable */
6+
import util from "../../assets/util";
7+
import CLASS from "../../../src/config/classes";
8+
import TextOverlap from "../../../src/plugin/textoverlap";
9+
10+
describe("PLUGIN: TEXTOVERLAP", () => {
11+
let chart;
12+
let args = {
13+
padding: {
14+
left: 50
15+
},
16+
data: {
17+
columns: [
18+
["data1", 1030, 2200, 2100],
19+
["data2", 1150, 2010, 1200],
20+
["data3", -1150, -2010, -1200],
21+
["data4", -1030, -2200, -2100]
22+
],
23+
type: "line",
24+
labels: true,
25+
groups: [
26+
["data1", "data2"],
27+
["data3", "data4"]
28+
]
29+
},
30+
plugins: [
31+
new TextOverlap()
32+
]
33+
};
34+
35+
beforeEach(() => {
36+
chart = util.generate(args);
37+
});
38+
39+
it("should move data labels into correct position", () => {
40+
const expectedTextDy = {
41+
data1: ["0.35em", "0.71em", "0.71em"],
42+
data2: ["0.35em", "0.35em", "0.71em"],
43+
data3: ["0.71em", "0.71em", "0.35em"],
44+
data4: ["0.71em", "0.35em", "0.35em"]
45+
};
46+
const expectedTextTransform = {
47+
data1: ["translate(-1, -1)", "translate(-1, 6)", "translate(-1, 6)"],
48+
data2: ["translate(-1, -1)", "translate(-1, -1)", "translate(-1, 6)"],
49+
data3: ["translate(-1, 6)", "translate(-1, 6)", "translate(-1, -1)"],
50+
data4: ["translate(-1, 6)", "translate(-1, -1)", "translate(-1, -1)"]
51+
};
52+
53+
Object.keys(expectedTextDy).forEach(key => {
54+
chart.internal.main.selectAll(`.${CLASS.texts}-${key} text.${CLASS.text}`).each(function(d, i) {
55+
const text = d3.select(this);
56+
57+
expect(text.attr("dy")).to.be.equal(expectedTextDy[key][i]);
58+
expect(text.attr("transform")).to.be.equal(expectedTextTransform[key][i]);
59+
});
60+
});
61+
});
62+
63+
it("set options extent & area options", () => {
64+
args.plugins = [
65+
new TextOverlap({
66+
extent: 8,
67+
area: 3
68+
})
69+
];
70+
});
71+
72+
it("should move data labels into correct position with specified extent and area", () => {
73+
const expectedTextDy = {
74+
data1: ["0.35em", "0.71em", "0.71em"],
75+
data2: ["0.35em", "0.35em", "0.71em"],
76+
data3: ["0.71em", "0.71em", "0.35em"],
77+
data4: ["0.71em", "0.35em", "0.35em"]
78+
};
79+
const expectedTextTransform = {
80+
data1: ["translate(-8, -8)", "translate(-8, 13)", "translate(-8, 13)"],
81+
data2: ["translate(-8, -8)", "translate(-8, -8)", "translate(-8, 13)"],
82+
data3: ["translate(-8, 13)", "translate(-8, 13)", "translate(-8, -8)"],
83+
data4: ["translate(-8, 13)", "translate(-8, -8)", "translate(-8, -8)"]
84+
};
85+
86+
Object.keys(expectedTextDy).forEach(key => {
87+
chart.internal.main.selectAll(`.${CLASS.texts}-${key} text.${CLASS.text}`).each(function(d, i) {
88+
const text = d3.select(this);
89+
90+
expect(text.attr("dy")).to.be.equal(expectedTextDy[key][i]);
91+
expect(text.attr("transform")).to.be.equal(expectedTextTransform[key][i]);
92+
});
93+
});
94+
});
95+
});

src/config/Options.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -615,15 +615,6 @@ export default class Options {
615615
* data3: "green"
616616
* },
617617
*
618-
* //turn on overlap prevention
619-
* overlap: false,
620-
*
621-
* //set extent of prevent overlap, and minimum area needed to show a data label
622-
* overlap: {
623-
* extent : 6,
624-
* area: 2,
625-
* },
626-
*
627618
* // set x, y coordinate position
628619
* position: {
629620
* x: -10,
@@ -635,7 +626,6 @@ export default class Options {
635626
data_labels: {},
636627
data_labels_colors: undefined,
637628
data_labels_position: {},
638-
data_labels_overlap: true,
639629

640630
/**
641631
* This option changes the order of stacking data and pieces of pie/donut.

src/internals/text.js

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ import {
66
select as d3Select,
77
selectAll as d3SelectAll
88
} from "d3-selection";
9-
import {voronoi as d3Voronoi} from "d3-voronoi";
10-
import {
11-
polygonCentroid as d3PolygonCentroid,
12-
polygonArea as d3PolygonArea
13-
} from "d3-polygon";
149
import ChartInternal from "./ChartInternal";
1510
import CLASS from "../config/classes";
1611
import {capitalize, extend, getBoundingRect, getRandom, isNumber, isObject, isString} from "./util";
@@ -100,40 +95,6 @@ extend(ChartInternal.prototype, {
10095
return color || $$.color(d);
10196
},
10297

103-
/**
104-
* Set text label's position to preventg overlap.
105-
* @param {Object} overlap Overlap config object
106-
* @private
107-
*/
108-
preventLabelOverlap(overlap) {
109-
const $$ = this;
110-
const {extent = 1, area = 0} = overlap;
111-
const cells = $$.generateVoronoi($$.mainText.data().map(v => [v.x, v.value]));
112-
let i = 0;
113-
114-
$$.mainText.each(function() {
115-
const cell = cells[i++];
116-
117-
if (cell && this) {
118-
const [x, y] = cell.data;
119-
const [cx, cy] = d3PolygonCentroid(cell);
120-
const angle = Math.round(Math.atan2(cy - y, cx - x) / Math.PI * 2);
121-
122-
const xTranslate = extent * (angle === 0 ? 1 : -1);
123-
const yTranslate = angle === -1 ? -extent : extent + 5;
124-
125-
const txtAnchor = Math.abs(angle) === 1 ?
126-
"middle" : (angle === 0 ? "start" : "end");
127-
128-
d3Select(this)
129-
.attr("display", d3PolygonArea(cell) < area ? "none" : null)
130-
.attr("text-anchor", txtAnchor)
131-
.attr("dy", `0.${angle === 1 ? 71 : 35}em`)
132-
.attr("transform", `translate(${xTranslate}, ${yTranslate})`);
133-
}
134-
});
135-
},
136-
13798
/**
13899
* Redraw chartText
139100
* @param {Function} x Positioning function for x
@@ -146,11 +107,6 @@ extend(ChartInternal.prototype, {
146107
const $$ = this;
147108
const t = getRandom();
148109
const opacityForText = forFlow ? 0 : $$.opacityForText.bind($$);
149-
const overlap = $$.config.data_labels_overlap;
150-
151-
if (overlap === false || isObject(overlap)) {
152-
$$.preventLabelOverlap(overlap);
153-
}
154110

155111
return [
156112
this.mainText.each(function() {
@@ -230,22 +186,6 @@ extend(ChartInternal.prototype, {
230186
};
231187
},
232188

233-
/**
234-
* Generates the voronoi layout for data labels
235-
* @param {Object} data Indices values
236-
* @returns {Object} Voronoi layout points and corresponding Data points
237-
* @private
238-
*/
239-
generateVoronoi(data) {
240-
const $$ = this;
241-
const min = ["x", "y"].map(v => $$[v].domain()[0]);
242-
const max = ["x", "y"].map(v => $$[v].domain()[1]);
243-
244-
return d3Voronoi()
245-
.extent([min, max])
246-
.polygons(data);
247-
},
248-
249189
/**
250190
* Get centerized text position for bar type data.label.text
251191
* @private

0 commit comments

Comments
 (0)