-
-
Notifications
You must be signed in to change notification settings - Fork 83
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 scales: gradient-like interpolation across multiple color stops #506
Comments
I think gradients across multiple color stops is a good idea. I know I implemented this behavior in ColorAide, so I definitely think it is useful. |
Do you plan on supporting adjusting stop position? It may be something to consider up front if this is desired for the future. |
As soon as we move from linear two-stop interpolation we need to consider how we want to handle smooth curves and curve continuity (regardless of whether we also need to support piecewise linear with bolted-on fix-ups like midpoint position, ease-in ease-out, and the like which are crude approximations to true, easily-animatable multi-point curves). Ideally, multi-point smooth curves that can be
|
I'll let others define the API to introduce such functionality and I'll speak generally to multi-point smooth curves. Generally, I like the approach that Culori employed using cubic splines: https://culorijs.org/api/#interpolatorSplineBasis. The one thing I think Culori did not address is what to do with undefined channels when applying these approaches. I will speak to how I decided to handle such things. Using splines requires us to broaden the definition of what a piece is. While you must handle 2 color and 3 color cases, splines need a bit more context and ideally should take into account 4 colors if available. This will help shape the curve smoothly through the colors. Personally, I found undefined handling for the current linear interpolation insufficient considering the requirements of 4 colors (if available) for splines. In order to settle on what I found to be a reasonable solution, I needed to adjust undefined channel handling. To do this, undefined channels, for anything other than piecewise linear, are evaluated throughout the entire chain of colors, essentially filling in any gaps and holes before interpolation takes place. This is currently done by using simple linear interpolation to create points between the defined channels. Such gaps are considered and filled before easing functions are applied. Undefined channels not between two defined channels simply take on the value of the defined channel on either its left or right. Using this logic as a basis, splines were implemented on top of that. Overshoot is dependant upon the spline approach chosen. I'm not sure any approach perfectly eliminates overshoot, but monotone at least will keep it within the bounds of the data. Extrapolation beyond the endpoints is handled in a linear fashion, at least in my implementation. Stops and easing functions are generally handled as they were previously in normal linear, piecewise interpolation. Stops are applied to the current color stops, and easing functions adjust the progress between the two colors currently under evaluation, even if that evaluation is looking past those two colors to shape the curve in the spline. Hopefully, some of this is helpful for considering what direction Color.js should take. |
I think this has a fair amount of overlap with #18, unless I'm misunderstanding. I would be very interested in a convenience function (or just a flexible interpolation API) to interpolate over a custom domain (instead of fixed |
I think custom domains would be useful. I think this could easily be done now with a simple external function that you pass your value through before passing it to the interpolation function that coerces a defined domain to 0 - 1. It doesn't have to be implemented directly in Color.js, though I'm sure it would be appreciated if the domain could be specified in |
Currently we have
Color.range()
and friends which only interpolates between 2 colors. I just had to write this for a color component I’m writing (<color-slider>
), and it was no fun:And this is just equally spaced color stops. I dread to think about implementing the general case.
Which is why I think Color.js should provide it 😁
I’m thinking of something like:
Thoughts?
The text was updated successfully, but these errors were encountered: