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

Better Support for Removing Margins/Padding #4997

Open
dan24678 opened this issue Nov 27, 2017 · 6 comments
Open

Better Support for Removing Margins/Padding #4997

dan24678 opened this issue Nov 27, 2017 · 6 comments

Comments

@dan24678
Copy link

I'm working on developing a plugin for the Wavesurfer project (https://github.com/katspaugh/wavesurfer.js) which will use Chart.js to overlay a line chart on top of an audio waveform, per the screenshot below:

wavesurfer_js___graph

As you can see from the screenshot, I have a 20 second audio file with the initial data point at 0 seconds and the final data point at 20 seconds. I need the initial and final data points to line up with the beginning and end of the graph so that each data point corresponds precisely to the timestamps in the audio file but this is proving difficult.

Ideally, there would be an option to place the X and Y axis labels inside the graph itself, rather than treating them as having a discrete width/height that acts as a padding around the graph. This setting would vastly simplify things, so I guess that would be the "feature request" part of this issue.

Failing this setting, this is the current approach I'm using (which gets me very close to where I want to be):

Step 1 -- Remove the Y-Axis label with "display: false". This removes most but not all of the padding on the right-hand side.

Step 2 -- Suppress the initial and final labels from displaying via:

ticks: {
  callback: function(value, index, values) {
    if (index !== 0 && index !== 10) {
      return value;
    } else {
      return '';
    }
  },

This gets me very close to having no padding but there is still 5px or so of padding at the beginning and end:

wavesurfer_js___graph

This seems like a bug to me. Why is there a 5px margin by default when there are no labels to draw? An additional potential bug is that I can only reduce the padding in the ticks callback by returning an empty string. If I return null instead, the resulting padding is much larger than is produced by using an empty string (which is counter-intuitive so I almost didn't think to try the empty string).

Step 3 -- Use negative margins in an xAxes afterBuildTicks callback to remove the slim padding that's left:

afterBuildTicks: function(axis) {
    axis.margins.left = '-5px';
    axis.margins.right = '-5px';
},

This gets us where we want to be:

wavesurfer_js___graph

Step 4 -- You can actually reintroduce the xAxes labels now by manually adding spaces into the values to pad them out so the first and last labels are offset inward:

ticks: {
  callback: function(value, index, values) {
    const padding = '    ',
       lastValue = values.length - 1;

    if (index !== 0 && index !== lastValue) {
      return value;
    } else if (index) {
      return value + padding;
    } else {
      return padding + value;
    }
  },

You can see I'm almost there...

wavesurfer_js___graph

Step 5 -- Step 5 would be to find a way to reintroduce the Y-Axes label in a way that won't add more padding back in. Note that increasing the amount of negative padding to compensate does not work. I suspect I can theoretically render a second graph which does contain the Y-Axis labels and overlay this second graph on top of the first to achieve the effect of having the labels visible inside the graph. Unfortunately, I'm not sure how I'd have the second graph show the labels but not the data. Is that possible?

Anyway, I wanted to submit all this as an issue because when I googled what I'm trying to do, all that came up is #4135

In that issue, other users were asking essentially about my use case and (in my opinion) an incorrect answer was given -- that the desired styling is only possible by modifying the core library. I believe that through the use of what I outlined above, you can eliminate the padding in many cases without touching Chart.js source.

That said:

  1. I'd love to see the whole thing simplified via a setting that lets all the labels render inside the chart area itself, instead of in the margins. Is this doable currently via using the lifecycle hooks to manually manipulate certain values?

  2. I still am not sure how I can render the YAxes labels without reintroducing padding, so I'd also appreciate any help there.

Thanks!

@etimberg
Copy link
Member

@DrLongGhost thanks for the descriptive feature request!

I had an old branch somewhere that auto changed the labels at the ends of the axis to have different alignments to remove the padding. I think the extra bit might be coming from https://github.com/chartjs/Chart.js/blob/master/src/core/core.scale.js#L352

One option you can use on the Y axis is the mirror setting. It will draw the labels inside the chart area instead of on the outside. I looked through the docs and don't see it so that seems like an oversight on our part. Unfortunately it only works for the Y axis at the moment, but it could easily be implemented for the x axis.

options: {
  scales: {
    yAxes: [{
      ticks: {
        mirror: true
      }
    }]
  }
}

@dan24678
Copy link
Author

dan24678 commented Nov 28, 2017

@etimberg -- Thanks for pointing out the mirror option. It removes about half the padding from the YAxes label, but unfortunately, as you can see from the screenshot below, there remains about 10px or so of padding that remains and can't be removed via negative padding/margin settings:

wavesurfer_js___graph

The mirror setting is exactly what I'm looking for though, so I guess the feature request would be to:

  • Add support for "mirror: true" to the xAxes
  • Remove the padding that is left when you use "mirror: true" or come up with a way that it can be modified via the ability to set negative margins.

Thanks for the follow up!

@etimberg
Copy link
Member

To remove a bit more padding on the Y axis you could try setting gridLines.drawTicks to false.

@SantiagoMoyano
Copy link

@etimberg Thank you so much, i couldn't find the way!! saved my day

@Prosen-Ghosh
Copy link

@etimberg thank you 👍 gridLines.drawTicks to false worked for me.

@kurkle
Copy link
Member

kurkle commented Jan 14, 2020

For the padding caused by x-axis labels, you can use offset: true
https://www.chartjs.org/docs/latest/axes/cartesian/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants