Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xAxis.nameGap and yAxis.nameGap should be set automatically given grid.containLabel #9265

Open
jbadilla opened this issue Oct 22, 2018 · 22 comments · May be fixed by #16825
Open

xAxis.nameGap and yAxis.nameGap should be set automatically given grid.containLabel #9265

jbadilla opened this issue Oct 22, 2018 · 22 comments · May be fixed by #16825
Labels
en This issue is in English new-feature

Comments

@jbadilla
Copy link

jbadilla commented Oct 22, 2018

xAxis.nameGap and yAxis.nameGap should be set automatically given grid.containLabel; this would provide the user with an easy way to display his/her axis name in a way that it doesn't visually interfere with the axis labels

One-line summary [问题简述]

Version & Environment [版本及环境]

  • ECharts version [ECharts 版本]:
  • Browser version [浏览器类型和版本]:
  • OS Version [操作系统类型和版本]:

Expected behaviour [期望结果]

When containLabel is selected, and a name for the xAxis or the yAxis has been specified, these should always fit on the graph's rendering, taking into account the 'rotate' property of the axis labels.

ECharts option [ECharts配置项]

if:

option = {
    grid.containLabel = true
    xAxis.axisLabel.rotate: someValue
    yAxis.axisLabel.rotate: someValue
}

then:

option = {
    grid.containLabel : true
    xAxis.axisLabel.rotate: someValue
    yAxis.axisLabel.rotate: someValue
    xAxis.nameGap : auto //should be set automatically
    yAxis.nameGap :  auto //should be set automatically
}

Other comments [其他信息]

@deqingli
Copy link
Member

sorry, I don't quite understand what you mean, can you show me the ECharts option and the effect picture you want.

@deqingli deqingli added the missing-demo The author should provide a demo. label Oct 23, 2018
@jbadilla
Copy link
Author

jbadilla commented Oct 24, 2018

Certainly! I have included the option in the original post.

Explanation: I would like for the x-axis and y-axis names to be set based on the 'rotate' value of the axisLabel property inside xAxis and yAxis.

Justification: This is because sometimes the yAxis or xAxis labels overlaps with the yAxis or xAxis name. This is visually unpleasant, and it should be a standard feature that it automatically sets xAxis.nameGap and yAxis.nameGap so that it is not being overlapped by the axis labels.

How it should look:

screen shot 2018-10-24 at 9 05 38 am

@Ovilia Ovilia added the en This issue is in English label Oct 26, 2018
@Ovilia
Copy link
Contributor

Ovilia commented Oct 26, 2018

Do you mean that you want to rotate the axis name or where do you want to place it? Sorry I didn't quite follow.

@jbadilla
Copy link
Author

Here is how echarts behaves by default:

screen shot 2018-10-26 at 11 25 19 am

Here's how it should behave:

screen shot 2018-10-26 at 11 27 43 am

This has to be done by setting the xAxis.nameGap property to something reasonable

@100pah 100pah added enhancement new-feature and removed missing-demo The author should provide a demo. new-feature enhancement labels Oct 29, 2018
@100pah
Copy link
Member

100pah commented Oct 29, 2018

Currenly containLabel only considered axis labels, but not consider axis name.

@jbadilla


This axis lable is visually unpleasant because the default nameGap is 0.

Another issue #9286 gave a related situation that the axis name might overflow the rendering area.

To make the layout wisely, I think two enhancements can be taken into accout (and the two enhancement might be independent with each other in implementation):

(A) Enhanse the layout calculation of axis name: adjust it based on axis label and viewport.

Keep the current behaviors of nameLocation and nameGap, and add a new option nameLocationAdjust (or some likely name), which enable axis name to be auto adjusted to avoid interfering with axis labels and overflow the viewport, following the strategy below:

Procedure X:
Layout axis name by the given nameLoation and nameGap, and then adjust it to avoid interfering with axis labels. Finally the relative location of axis name with axis line get. Detailedly, in this case, nameGap is not the gap with axis line any more, but actually is the gap with the bounding rect of both axis line and axis labels.

Procedure X will be executed twices if containLabel is set, the same as current implementation:
1. The first execution is before the "coordinate system update stage", based on the estinamed axis label layout.
2. The second execution is on the "cartesian rendering stage", based on the accrate axis label layout.

Procedure Y:
Ajust the axis name to avoid overflowing the viewport (if it makes the axis name interfere with axis labels again, leave them there). Notice the overflow also need to be taken into account when nameLocation is start or end, like #9286 issued, which enables that when two cartesian exists axes align with each other without dynamic axis names overflow.

Procedure Y is only be executed in the "cartesian rendering stage", after Procedure X executed.

(B) Enhanse the cartesian rect determine calculation when containLabel

Currently containLabel has considdered axis label (and rotation). We should make it take into account the located axis name also, whatever the (A) is implemented or not.

But the logic looks not neat, a little complecated :(

What do you think @pissang

@sunzy0212
Copy link

Currently, is there any workaround?

@jbadilla
Copy link
Author

The workaround was offered in @100pah 's answer.

That being said, the 'nameGap' property is – in my opinion – flawed, because the property should not really exist.
Rather, the 'nameGap' should be calculated internally, taking into account the length of the 'xAxis.axisLabels' and 'yAxis.axisLabels', as well as the 'rotate' property, which says how much labels should be rotated.

Any ideas?

@sunzy0212
Copy link

@jbadilla Thanks for answers, but how can I get yAxis.axisLabels? Is there any api?

@jbadilla
Copy link
Author

jbadilla commented Apr 29, 2019

Hi @sunzy0212 ! Sorry I hadn't answered in a while; I've been neglecting this issue in my code, and have implemented a messy (albeit temporarily) solution so I could move on.

You should already have access to your categorical labels outside of echarts (e.g. in the data you use to build the chart). alternatively, you can use the echartsInstance object getOption function: https://ecomfe.github.io/echarts-doc/public/en/api.html#echartsInstance.getOption

Like @100pah says, the problem is not only the axis labels but also the viewport.

I will spend some time on this today

@jbadilla
Copy link
Author

@100pah @pissang any news? do you expect to push a fix for this anytime soon?

@fxxjdedd
Copy link

I have the same problem, most of the problems can be solved by calculating nameGap externally, but when yAxis is the category axis, and the categories are very large, echarts will perform display optimization according to interval: 'auto', but we have no way to get which labels will eventually be displayed, which can cause problems with our final nameGap calculations.

image

@fxxjdedd
Copy link

I have the same problem, most of the problems can be solved by calculating nameGap externally, but when yAxis is the category axis, and the categories are very large, echarts will perform display optimization according to interval: 'auto', but we have no way to get which labels will eventually be displayed, which can cause problems with our final nameGap calculations.

image

image

After reviewing the source code related to the axis, I finally found the way to get the viewLabels in the instance of echarts!

@AaronKauffman
Copy link

Hello I just came across this problem in a project I am working on and was wondering the progress for a solution to the nameGap issue?

@AbhaysinghBhosale
Copy link

Is there any fix/workaround for this issue?
In my case if nameGap set with static value it overlap once yAxis data reaches to 4 digit. and yAxis name overlap over ticks

@fxxjdedd
Copy link

@AbhaysinghBhosale
#9265 (comment)
use the axis.getViewLabel and calculate these labels's dom width, then you get a nameGap...

@jojozg7
Copy link

jojozg7 commented Nov 25, 2021

After 3 years, this problem is still relevant. Is there still hope that it will be fixed?

Either nameGap is set too high and the text disappears to the left, or it is set too low and overlaps with the numbers on the Y-axis.

Would be great if you could fix this.

@pissang pissang added this to the 5.4 milestone Nov 25, 2021
@konrad-amtenbrink konrad-amtenbrink linked a pull request Apr 1, 2022 that will close this issue
6 tasks
@DavidMarquezF
Copy link

Seems like proposed pull request will fix it. Any ideas if it will be merged at some point?

@tripathiarpit
Copy link

@pissang has this been fixed in the any version of Chart.js

@Ovilia
Copy link
Contributor

Ovilia commented Jun 29, 2022

Changed calculated label gap to be passed from top #16825

There is a PR #16825 under review.

@Ovilia Ovilia removed this from the 5.4 milestone Sep 1, 2022
@CrazyRedTime
Copy link

Any news?

@0x1f57
Copy link

0x1f57 commented Dec 5, 2023

在echarts实例setOption后调用下述方法可暂时解决此问题

/**
 * 修复Y轴名称间隔问题(Y轴名称与Y轴刻度标签重叠问题)
 * @param {EChartsType} chartInstance
 */
export function fixYAxisNameGap(chartInstance) {
  const globalModel = chartInstance._api.getModel()
  const yAxisList = globalModel.option.yAxis

  const ctx = document.createElement('canvas').getContext('2d')
  const nameGapList = []
  // 兼容多Y轴
  yAxisList.forEach(({ nameTextStyle, axisLabel }, index) => {
    const fontSize = nameTextStyle?.fontSize ?? 12
    const fontFamily = nameTextStyle?.fontFamily ?? 'sans-serif'
    ctx.save()
    ctx.font = `${fontSize}px ${fontFamily}`
    const yAxis = globalModel.getComponent('yAxis', index)?.axis
    // 计算刻度标签文字最大宽度
    const labelMaxWidth = Math.max(...yAxis.getViewLabels().map(item => ctx.measureText(item.formattedLabel).width))
    const axisLabelMargin = axisLabel?.margin ?? 8
    nameGapList.push(labelMaxWidth + axisLabelMargin + 5)
    ctx.restore()
  })

  chartInstance.setOption({
    yAxis: nameGapList.map(nameGap => ({ nameGap }))
  })
}

@gmuralidharreddy
Copy link

Is above PR will resolve this issue? If yes when can we expect it’s going to live?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
en This issue is in English new-feature
Projects
None yet