deno.land / x / billboardjs@3.6.0 / Plugin / textoverlap / index.ts

نووسراو ببینە
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/** * Copyright (c) 2017 ~ present NAVER Corp. * billboard.js project is licensed under the MIT license */import type {d3Selection} from "billboard.js/types/types";import {Delaunay as d3Delaunay} from "d3-delaunay";import { polygonCentroid as d3PolygonCentroid, polygonArea as d3PolygonArea} from "d3-polygon";import {loadConfig} from "../../config/config";import Plugin from "../Plugin";import Options from "./Options";
/** * TextOverlap plugin<br> * Prevents label overlap using [Voronoi layout](https://en.wikipedia.org/wiki/Voronoi_diagram). * - **NOTE:** * - Plugins aren't built-in. Need to be loaded or imported to be used. * - Non required modules from billboard.js core, need to be installed separately. * - Appropriate and works for axis based chart. * - **Required modules:** * - [d3-polygon](https://github.com/d3/d3-polygon) * - [d3-delaunay](https://github.com/d3/d3-delaunay) * @class plugin-textoverlap * @requires d3-polygon * @requires d3-delaunay * @param {object} options TextOverlap plugin options * @augments Plugin * @returns {TextOverlap} * @example * // Plugin must be loaded before the use. * <script src="$YOUR_PATH/plugin/billboardjs-plugin-textoverlap.js"></script> * * var chart = bb.generate({ * data: { * columns: [ ... ] * }, * ... * plugins: [ * new bb.plugin.textoverlap({ * selector: ".bb-texts text", * extent: 8, * area: 3 * }) * ] * }); * @example * import {bb} from "billboard.js"; * import TextOverlap from "billboard.js/dist/billboardjs-plugin-textoverlap"; * * bb.generate({ * plugins: [ * new TextOverlap({ ... }) * ] * }) */export default class TextOverlap extends Plugin { private config;
constructor(options?: Options) { super(options); this.config = new Options();
return this; }
$init(): void { loadConfig.call(this, this.options); }
$redraw(): void { const {$$: {$el}, config: {selector}} = this; const text = selector ? $el.main.selectAll(selector) : $el.text;
!text.empty() && this.preventLabelOverlap(text); }
/** * Generates the voronoi layout for data labels * @param {Array} points Indices values * @returns {object} Voronoi layout points and corresponding Data points * @private */ generateVoronoi(points: [number, number][]) { const {$$} = this; const {scale} = $$; const [min, max] = ["x", "y"].map(v => scale[v].domain());
[min[1], max[0]] = [max[0], min[1]];
return d3Delaunay .from(points) .voronoi([ ...min as [number, number], ...max as [number, number] ]); // bounds = [xmin, ymin, xmax, ymax], default value: [0, 0, 960, 500] }
/** * Set text label's position to preventg overlap. * @param {d3Selection} text target text selection * @private */ preventLabelOverlap(text: d3Selection): void { const {extent, area} = this.config; const points = text.data().map(v => [v.index, v.value]) as [number, number][]; const voronoi = this.generateVoronoi(points); let i = 0;
text.each(function() { const cell = voronoi.cellPolygon(i);
if (cell && this) { const [x, y] = points[i]; // @ts-ignore wrong type definiton for d3PolygonCentroid const [cx, cy] = d3PolygonCentroid(cell);
// @ts-ignore wrong type definiton for d3PolygonArea const polygonArea = Math.abs(d3PolygonArea(cell));
const angle = Math.round(Math.atan2(cy - y, cx - x) / Math.PI * 2); const xTranslate = extent * (angle === 0 ? 1 : -1); const yTranslate = angle === -1 ? -extent : extent + 5;
const txtAnchor = Math.abs(angle) === 1 ? "middle" : (angle === 0 ? "start" : "end");
this.style.display = polygonArea < area ? "none" : ""; this.setAttribute("text-anchor", txtAnchor); this.setAttribute("dy", `0.${angle === 1 ? 71 : 35}em`); this.setAttribute("transform", `translate(${xTranslate}, ${yTranslate})`); }
i++; }); }}
billboardjs

Version Info

Tagged at
a year ago