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

Customizeable Axis Title Rendering #3214

Open
sassomedia opened this issue Aug 25, 2016 · 4 comments
Open

Customizeable Axis Title Rendering #3214

sassomedia opened this issue Aug 25, 2016 · 4 comments

Comments

@sassomedia
Copy link
Contributor

In order to make 2-axis (opposing axis) charts a bit more readable than this https://jsfiddle.net/tah74jm4/ (which line belongs to which label?), the designer wanted a color indication on the label for each line. I know there are legends, however that takes up additional space and is also not very flexible in positioning the legend items. In this case, a legend next to each label would better indicate which values belong to which line.

One option we were considering was coloring the label in the matching color of the line, however since the colors can be dynamic based on user selection, there could be colors which would make the label text hard to read. So this option was thrown out.

The option chosen was a black label with a dot next to it in the color of the line, as you can see here:

screen shot 2016-08-25 at 1 55 06 pm

This is a screenshot of an actual graph, which I was able to generate by making a slight modification in the draw function in core.scale.js in the scaleLabel.display part:

if (scaleLabel.display) {
  // Draw the scale label
  scaleLabelX = options.position === 'left' ? this.left + (scaleLabelFontSize / 2) : this.right - (scaleLabelFontSize / 2);
  scaleLabelY = this.top + ((this.bottom - this.top) / 2);
  var rotation = options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;

  // added "if-condition" allows for multi-colored label
  if (scaleLabel.labelString instanceof Array) {
    var x = 0;
    var fullText = '';
    var fullTextOffset;
    var labelOffset;

    context.save();

    helpers.each(scaleLabel.labelString, function (obj) {
      fullText += obj.text;
    });

    fullTextOffset = context.measureText(fullText).width / 2;
    labelOffset = options.position === 'left' ? fullTextOffset : fullTextOffset * -1;

    context.translate(scaleLabelX, scaleLabelY + labelOffset);
    context.rotate(rotation);
    context.font = scaleLabelFont;
    context.textBaseline = 'middle';

    helpers.each(scaleLabel.labelString, function (obj) {
      context.fillStyle = obj.color;
      context.fillText(obj.text, x, 0);
      x += context.measureText(obj.text).width;
    });

    context.restore();
  } else {
    context.save();
    context.translate(scaleLabelX, scaleLabelY);
    context.rotate(rotation);
    context.textAlign = "center";
    context.fillStyle = scaleLabelFontColor; // render in correct colour
    context.font = scaleLabelFont;
    context.textBaseline = 'middle';
    context.fillText(scaleLabel.labelString, 0, 0);
    context.restore();
  }
}

This would allow me to pass in an Array of Objects into the labelString as opposed to just a String. This looks like the following:

'yAxes': [{
  'id': 'y-axis-1',
  'type': 'linear',
  'position': 'left',
  'scaleLabel': {
    'display': true,
    'labelString': [{
      'text': '● ',
      'color': '#fc6062'
    }, {
      'text': 'My Left Label Text',
      'color': '#000'
    }],
    'fontFamily': 'AB',
    'fontColor': '#000',
    'fontSize': 11
  },
}, {
  'id': 'y-axis-2',
  'type': 'linear',
  'position': 'right',
  'scaleLabel': {
    'display': true,
    'labelString': [{
      'text': '● ',
      'color': '#4dc1e7'
    }, {
      'text': 'My Right Label Text',
      'color': '#000'
    }],
    'fontFamily': 'AB',
    'fontColor': '#000',
    'fontSize': 11
  }
}]

Obviously, a change like that should not be done directly in the library. If I were to create a custom Scale though, I would have to override the whole draw function, which is not ideal either as there is a lot of code in there which might change with library versions going forward.

Question is, how would I be able to implement something like this in the least intrusive way? Any suggestions would be greatly appreciated, thanks!

@etimberg
Copy link
Member

One idea would be to factor out a drawLabel function. The current implementation would do what we currently do. Then only that function could be overridden. The challenge would be figuring out the API to that function so that we don't have a lot of duplicated code for getting config options, etc.

@sassomedia
Copy link
Contributor Author

Thanks for the suggestion! And yes, good point, that does get a bit tricky with the API. I'll give this some thought...

@etimberg
Copy link
Member

If anyone is wanting to implement this, the idea is to replace these lines with a separate function that could be overridden to provide this behaviour. Shouldn't be too hard to do, the key will be documenting the API and explicitly making this function for public use.

@etimberg etimberg changed the title Custom labelString implementation? Use-case: 2-axis (opposing axis) chart Customizeable Axis Title Rendering Dec 22, 2020
@poojavirgo
Copy link

Hi , Is this issue is open , i want to work on it.

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

4 participants