c3js / c3js/c3

(Proposed solution) Multiline x-axis labels interfere with the bottom legend

Open
#1,044 4 comments 0 reactions 0 assignees View on GitHub
C-feature-request
Dominant language
JavaScript
Stars
9.3k
Forks
1.4k
Avg merge
6d 16h
Merged PRs (30d)
1

Description

I'd like to propose a fix that would handle the mess that emerges when one is having multiline labels on the x-axis while having the legend positioned at the bottom. _(which happens at least with the newest Chrome)_

**The problem:** _(don't mind the labels repeating - it's just to make them longer)_

![image](https://cloud.githubusercontent.com/assets/6860713/6506007/bb357648-c347-11e4-9e7c-81466bce1b65.png)

After a few hours of figuring out how to do this I came up with a rather simplified and **_naive solution**_, that consists of 4 actual changes to the c3.js file:

Step 1: **c3.js, lines 128 - 132**

```
$$.currentMaxTickWidths = {
x: 0,
y: 0,
y2: 0
};
```

...replaced with...

```
$$.currentMaxTickWidths = $$.currentMaxTickHeights = {
x: 0,
y: 0,
y2: 0
};
```
#

Step 2: **c3.js, line 345**

```
xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'),
```

...replaced with...

```
xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x') + $$.getMaxTickHeight('x', true),
```
#

Step 3: **c3.js, insert new method after the body of `c3_chart_internal_fn.getMaxTickWidth` method**

```
c3_chart_internal_fn.getMaxTickHeight = function (id, withoutRecompute) {
var $$ = this, config = $$.config,
maxHeight = 0, targetsToShow, scale, axis, body, svg;
if (withoutRecompute && $$.currentMaxTickHeights[id]) {
return $$.currentMaxTickHeights[id];
}
if ($$.svg) {
targetsToShow = $$.filterTargetsToShow($$.data.targets);
if (id === 'y') {
scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
axis = $$.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues);
} else if (id === 'y2') {
scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
axis = $$.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues);
} else {
scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
axis = $$.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues);
$$.updateXAxisTickValues(targetsToShow, axis);
}
body = this.d3.select('body').classed('c3', true);
svg = body.append('svg').style('visibility', 'hidden').style('height', 0);
svg.append('g').call(axis).each(function () {
$$.d3.select(this).selectAll('text tspan').each(function () {
var box = this.getBoundingClientRect();
if (box.height >= 0 && maxHeight < box.height) { maxHeight = box.height; }
});
});
// TODO: time lag to get maxHeight
window.setTimeout(function () {
svg.remove();
}, 100);
body.classed('c3', false);
}
$$.currentMaxTickHeights[id] = maxHeight <= 0 ? $$.currentMaxTickHeights[id] : maxHeight;
return $$.currentMaxTickHeights[id];
};
```
#

Step 4: **c3.js, remove lines 2624 - 2627**

```
// Calculate x axis height when tick rotated
if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
h = $$.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180);
}
```
#

**Results:**

_Solved the original problem:_
![image](https://cloud.githubusercontent.com/assets/6860713/6506281/202298f4-c34a-11e4-8684-94deacab97e5.png)

_Problem with rotated labels:_
![image](https://cloud.githubusercontent.com/assets/6860713/6506286/2f74a392-c34a-11e4-836c-21b5f5620bde.png)

_Solved problem with rotated labels:_
![image](https://cloud.githubusercontent.com/assets/6860713/6506291/354bdd58-c34a-11e4-8216-5a891c4ca8d0.png)

I am aware of this solution being quite naive :) ..but for the time being it fixes the problem I faced with long multiline tick labels on the x-axis, so - I wanted to share this and maybe offer this as a basis for the proper solution to be implemented in the official code. :cat2:

*_EDIT: I just found out the solution above works only in Chrome (41), not in Firefox or IE. *_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.