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

Color gradient doesn't work as expected #307

Open
michael-soorys opened this issue Feb 17, 2022 · 5 comments
Open

Color gradient doesn't work as expected #307

michael-soorys opened this issue Feb 17, 2022 · 5 comments

Comments

@michael-soorys
Copy link

michael-soorys commented Feb 17, 2022

The problem

I want to use a line chart with datalabels, with a color gradient. I want the datalabel background color to be the same color as the line.

Expected behavior

When given the same CanvasGradient object to both the line color and datalabel color props, they should have the same color at any given point on the line.

Current behavior

When I pass the same CanvasGradient object as the backgroundColor property to the datalabel config, it seems to completely ignore the value of the datalabel and uses the top-most color in the gradient, rather than calculating its color based on the position in the context chart range.

I have isolated the problem in this fork of the demo - https://codesandbox.io/s/plugin-example-forked-wv2uxg?file=/src/App.vue

@stockiNail
Copy link
Contributor

@michael-soorys I think it's similar to #114

@michael-soorys
Copy link
Author

michael-soorys commented Feb 17, 2022

@stockiNail Ah, I see, guess I should have looked into your post more thoroughly. This does however not suffice since our charts can have multiple color stops through the data range. chroma.mix() supports only 2 colors, and as far as I can see there's no weighted mixing of more than 2 colors, like color gradient with multiple color stops.

This does give me an idea on how to implement a mixMore() type of method that would do the trick much like mix.

@stockiNail
Copy link
Contributor

@michael-soorys yes, you're right, it supports only 2 colors.

This does give me an idea on how to implement a mixMore() type of method that would do the trick much like mix.

Yes, that's the solution, I guess. I had played a bit (and quickly) on your sample with 3 colors but I think it can be generalized:

backgroundColor: function(ctx) {
  var count = ctx.dataset.data.length;
  var ratio = count ? ctx.dataIndex / count : 0;
  if (ratio <= 0.5) {
    return chroma.mix("#ff00ff", "#ff0000", ratio / 0.5);  
  }
  return chroma.mix("#ff0000", "#000000", (ratio - 0.5) / 0.5);
},

@michael-soorys
Copy link
Author

@stockiNail Thank you for your input : )

@michael-soorys
Copy link
Author

michael-soorys commented Feb 18, 2022

I managed to solve my problem. What I was looking for is a way for the user to set specific values on the chart to be color thresholds, which would for example change the line to red when bellow 10, be yellow above 40 and be green above 100. I solved this problem for my use case, but some of the code can still be used to mix less complex charts with more than 2 colors.

Here's the example code: https://codesandbox.io/s/plugin-example-forked-i5njjt?file=/src/App.vue

It basically does the same as mixing 2 colors, but it figures out what the 2 colors are based on the datalabel value in question. Luckily color gradient logic is not very sophisticated, just an average of RBG numbers, so it's the same color as the line, even though they're separate calculations.

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

No branches or pull requests

2 participants