Skip to content

Commit 154467f

Browse files
t-mullentheiliad
authored andcommittedJan 18, 2019
fix($browser): Fixes the issue with pie labels not lining up on smaller sizes.
#151
1 parent 3a5ba2b commit 154467f

File tree

2 files changed

+26
-44
lines changed

2 files changed

+26
-44
lines changed
 

‎packages/core/src/configuration.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ export const pie = {
193193
sliceLimit: 6,
194194
label: {
195195
dy: ".32em",
196-
margin: 15,
197-
other: "Other"
196+
margin: 8,
197+
other: "Other",
198198
},
199199
default: {
200200
strokeWidth: 2

‎packages/core/src/pie-chart.ts

+24-42
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export class PieChart extends BaseChart {
105105

106106
// Compute the correct inner & outer radius
107107
const { pie: pieConfigs } = Configuration;
108-
const marginedRadius = radius - (pieConfigs.label.margin * (chartSize.width / pieConfigs.maxWidth));
108+
const marginedRadius = this.computeRadius();
109109
this.arc = arc()
110110
.innerRadius(this.options.type === "donut" ? (marginedRadius * (2 / 3)) : 0)
111111
.outerRadius(marginedRadius);
@@ -127,16 +127,17 @@ export class PieChart extends BaseChart {
127127
.each(function(d) { this._current = d; });
128128

129129
// Draw the slice labels
130+
const self = this;
130131
this.innerWrap
131132
.selectAll("text.chart-label")
132133
.data(this.pie(dataList), (d: any) => d.data.label)
133134
.enter()
134135
.append("text")
135136
.classed("chart-label", true)
136137
.attr("dy", Configuration.pie.label.dy)
137-
.style("text-anchor", this.deriveTextAnchor)
138-
.attr("transform", d => this.deriveTransformString(d, radius))
139-
.text(d => Tools.convertValueToPercentage(d.data.value, dataList));
138+
.style("text-anchor", "middle")
139+
.text(d => Tools.convertValueToPercentage(d.data.value, dataList))
140+
.attr("transform", function (d) { return self.deriveTransformString(this, d, radius); });
140141

141142
// Hide overlay
142143
this.updateOverlay().hide();
@@ -212,19 +213,18 @@ export class PieChart extends BaseChart {
212213
.append("text")
213214
.classed("chart-label", true)
214215
.attr("dy", Configuration.pie.label.dy)
215-
.style("text-anchor", this.deriveTextAnchor)
216-
.attr("transform", d => this.deriveTransformString(d, radius))
216+
.style("text-anchor", "middle")
217217
.text(d => Tools.convertValueToPercentage(d.data.value, dataList))
218+
.attr("transform", function (d) { return self.deriveTransformString(this, d, radius); })
218219
.style("opacity", 0)
219220
.transition()
220221
.duration(Configuration.transitions.default.duration / 2)
221222
.style("opacity", 1);
222223

223224
text
224-
.attr("dy", Configuration.pie.label.dy)
225-
.style("text-anchor", this.deriveTextAnchor)
226-
.attr("transform", d => this.deriveTransformString(d, radius))
225+
.style("text-anchor", "middle")
227226
.text(d => Tools.convertValueToPercentage(d.data.value, dataList))
227+
.attr("transform", function (d) { return self.deriveTransformString(this, d, radius); })
228228
.transition()
229229
.duration(Configuration.transitions.default.duration / 2)
230230
.style("opacity", 1);
@@ -342,8 +342,7 @@ export class PieChart extends BaseChart {
342342

343343
const chartSize: any = this.getChartSize(this.container);
344344
const dimensionToUseForScale = Math.min(chartSize.width, chartSize.height);
345-
const scaleRatio = dimensionToUseForScale / pieConfigs.maxWidth;
346-
const radius: number = dimensionToUseForScale / 2;
345+
const radius: number = this.computeRadius();
347346

348347
// Resize the SVG
349348
select(this.holder).select("svg")
@@ -353,17 +352,17 @@ export class PieChart extends BaseChart {
353352
.style("transform", `translate(${radius}px,${radius}px)`);
354353

355354
// Resize the arc
356-
const marginedRadius = radius - (pieConfigs.label.margin * scaleRatio);
357355
this.arc = arc()
358-
.innerRadius(this.options.type === "donut" ? (marginedRadius * (2 / 3)) : 0)
359-
.outerRadius(marginedRadius);
356+
.innerRadius(this.options.type === "donut" ? (radius * (2 / 3)) : 0)
357+
.outerRadius(radius);
360358

361359
this.innerWrap.selectAll("path")
362360
.attr("d", this.arc);
363361

362+
const self = this;
364363
this.innerWrap
365364
.selectAll("text.chart-label")
366-
.attr("transform", d => this.deriveTransformString(d, radius));
365+
.attr("transform", function (d) { return self.deriveTransformString(this, d, radius); });
367366

368367
// Reposition the legend
369368
this.positionLegend();
@@ -386,35 +385,18 @@ export class PieChart extends BaseChart {
386385
* @returns final transform string to be applied to the <text> element
387386
* @memberof PieChart
388387
*/
389-
private deriveTransformString(d, radius) {
390-
const theta = d.endAngle - d.startAngle;
391-
const xPosition = radius * Math.sin((theta / 2) + d.startAngle);
392-
const yPosition = -1 * radius * Math.cos((theta / 2) + d.startAngle);
388+
private deriveTransformString(element, d, radius) {
389+
const textLength = element.getComputedTextLength();
390+
const textOffsetX = textLength / 2;
391+
const textOffsetY = parseFloat(getComputedStyle(element).fontSize) / 2;
393392

394-
return `translate(${xPosition}, ${yPosition})`;
395-
}
393+
const marginedRadius = radius + Configuration.pie.label.margin;
396394

397-
/**
398-
* Decide what text-anchor value the slice label item would need based on the quadrant it's in
399-
*
400-
* @private
401-
* @param {any} d - d3 data item for slice
402-
* @returns computed decision on what the text-anchor string should be
403-
* @memberof PieChart
404-
*/
405-
private deriveTextAnchor(d) {
406-
const QUADRANT = Math.PI / 4;
407-
const rads = (d.endAngle - d.startAngle) / 2 + d.startAngle;
408-
409-
if (rads >= QUADRANT && rads <= 3 * QUADRANT) {
410-
return "start";
411-
} else if ((rads > 7 * QUADRANT && rads < QUADRANT) || (rads > 3 * QUADRANT && rads < 5 * QUADRANT)) {
412-
return "middle";
413-
} else if (rads >= 5 * QUADRANT && rads <= 7 * QUADRANT) {
414-
return "end";
415-
} else {
416-
return "middle";
417-
}
395+
const theta = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
396+
const xPosition = (textOffsetX + marginedRadius) * Math.sin(theta);
397+
const yPosition = (textOffsetY + marginedRadius) * -Math.cos(theta);
398+
399+
return `translate(${xPosition}, ${yPosition})`;
418400
}
419401
}
420402

0 commit comments

Comments
 (0)