Skip to content

fix: gradient for color thresholds - #1361

Open
fran68 wants to merge 2 commits into
kalkih:devfrom
fran68:dev-fix/gradient_for_color_thresholds
Open

fix: gradient for color thresholds#1361
fran68 wants to merge 2 commits into
kalkih:devfrom
fran68:dev-fix/gradient_for_color_thresholds

Conversation

@fran68

@fran68 fran68 commented Apr 21, 2026

Copy link
Copy Markdown

IMO this should fix the problem with the color thresholds. In function computeGradient in src/graph.js the thresholds are evaluated as real values. When displaying the graph the gradient course is distorted since the margins at top and bottom affect the gradient offset. So the offset of the gradient needs to be adapted by considering the margin.

This might fix
#1080
#1108
#1137
#723

Before:
fix_fill01bfix_fill01a

After applying the patch:
fix_fill01d
fix_fill01c

line_width: 6
color_thresholds_transition: hard
color_thresholds:
  - value: 14
    color: red
  - value: 15
    color: cyan
  - value: 16
    color: green
  - value: 17
    color: red

@fran68
fran68 force-pushed the dev-fix/gradient_for_color_thresholds branch from da5a819 to 16b2e31 Compare April 21, 2026 21:14
@fran68 fran68 changed the title fix: gradient for color thresholds fix: gradient for color thresholds Apr 22, 2026
@fran68
fran68 force-pushed the dev-fix/gradient_for_color_thresholds branch from 16b2e31 to 47aabd5 Compare May 4, 2026 19:47
@fran68
fran68 force-pushed the dev-fix/gradient_for_color_thresholds branch from 47aabd5 to fc1a471 Compare May 11, 2026 20:59
@ildar170975

ildar170975 commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

@fran68
I would suggest using a _calcY() function to convert a stop value to pixels.
It accounts max/min & logarithmic.

      ...
      let offset;
      if (scale <= 0) {
        offset = 0;
      } else {
        // limit stopValue within max/min
        const stopValue = (stop.value >= this._max)
          ? this._max
          : (stop.value <= this._min)
            ? this._min
            : stop.value;
        // get Y coord for stopValue
        const [stopCoord] = this._calcY([[0, 0, stopValue]]);
        const [, coordY] = stopCoord;
        // calculate absolute offset
        offset = coordY * 100 / (this.height + this.margin[Y] * 4);
      }
      return {
        color: color || stop.color,
        offset,
      };
      ...

Here:

  1. Limit a stop value within max/min.
  2. Convert the stop value to pixels.
  3. Calculate an offset.

What do you think?
In my opinion, this is a more proper & transparent way.
I can issue my own PR (with credits for you of course) if you have no time for testing this.

Also, I am a bit unsure about

      if (scale <= 0) {
        offset = 0;
      }

may be an offset should be 100?

@fran68
fran68 force-pushed the dev-fix/gradient_for_color_thresholds branch from fc1a471 to 52934d7 Compare July 24, 2026 15:05
@fran68

fran68 commented Jul 24, 2026

Copy link
Copy Markdown
Author

@ildar170975
I've tested your code and it's fine. It's better to handle it with the coordinates.

But I dont know how to deal with that logarithmic thing. Is there ever a scale value which is negative?

@fran68
fran68 force-pushed the dev-fix/gradient_for_color_thresholds branch from 7535bd5 to b4c7d3b Compare July 24, 2026 16:57
@ildar170975

Copy link
Copy Markdown
Collaborator

We can discuss it in our chat.

@ildar170975

ildar170975 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

@fran68

But I dont know how to deal with that logarithmic thing. Is there ever a scale value which is negative?

This logic:

      if (scale <= 0) {
        offset = 0;
      } else {

stands for a case when "max = min".
This happens, for instance, for an unchanging sensor with undefined bound options.
The offset is "measured" from a "top edge" in SVG space (0 - top edge, then the offset is increasing to a "bottom edge").
Setting the "offset = 0" creates gradients like "{color: xxx, offset: 0}, ..., {color: yyy, offset: 0}" where "yyy" will be a properly set color for a graph.
Now we have a gradient "color: yyy" starting from "offset=0" (from the top).
And the graph is drawn near a "bottom edge" (assume here a "red" color is a proper one):
image
and since we have a gradient "red, starting from 0" - we get proper colors for a line, point & fill.

Now, regarding NEGATIVE values (offset <0).
I do not think it should be possible.
First, we need to add checks in buildConfig() for upper_bound/lower_bound options (are they numeric - like in #1401, accounting a possible ~ prefix). Next we should add a check - "upper_bound cannot be smaller than lower_bound". Do you agree?
(I have questions about "syncing" bounds in the "main" module and in a "Graph" object, but this is a different issue)
(Update 06.08.26: #1420 added checks for lower/upper bounds.)

Regarding logarithmic values.
Currently, in case of logarithmic: true, converted values can be only 0 or more (positive values), see a description from Docs (check dev version):
Note that this option rounds up the input to 1 so negative numbers or numbers less than 1 are rendered as 0; this is different from the formal definition of logarithm, where log(x) < 0 when x > 0 && x < 1 and ∞ or NaN when x <= 0
So, an offset again can be either positive or 0; negative values can only be in case of wrongly defined upper/lower_bound options.

I think this PR is ready and can be merged. What do you think?

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

Successfully merging this pull request may close these issues.

2 participants