vega icon indicating copy to clipboard operation
vega copied to clipboard

Allow per-segment and gradient coloring (line, trail, area-style marks)

Open nyurik opened this issue 7 years ago • 6 comments

The trail mark allows each segment to be sized dynamically, but it does not seem to allow the fill parameter to be used dynamically, even when placed inside the update encoding channel. There are some cases when each segment of a line/trail may need to have a different color.

There are several ways for the stroke and fill color to be dynamic for the connected shapes (line, trail, area). This setting could in theory be different for the fill and the stroke.

  • segment's color is a gradient from the starting to ending color
  • segment's color is based on starting point (similar to step-before interpolation)
  • segment's color is based on the ending point (similar to step-after interpolation)
  • all segments have the same static color as determined at the beginning of the mark drawing (current behavior)

P.S. as a theoretical workaround for this limitation, I might be able to wrap the trail mark inside a group, and make the group execute it once for each segment, but it seems overcomplicated and might have large performance implications.

nyurik avatar Mar 12 '18 21:03 nyurik

Implementation ideas:

  • Define two additional encoding parameters: strokeColorStyle and fillColorStyle, with these allowed values:
    • static - default, same as current behavior
    • starting - segment color is set from the starting point
    • ending - set from the ending point
    • gradient-segment - for each segment of the line, create a new gradient between the pair of points, with the start and end colors. This method might be slow but needed in some cases.
    • gradient - TBD: create one big gradient per mark run, using the first and the last points as gradient rectangle, and adding each point color as a stop. In a way, imagine a straight line that goes from the first to the last data point, and for each point in between, project point's coordinates to the line, and add it as a color stop.
    • gradient-N (e.g. gradient-0) - TBD: same as gradient, but force the gradient to go in predetermined direction, where N is a number of degrees from 0 for horizontal.

nyurik avatar Mar 13 '18 04:03 nyurik

Reading over the points above, it becomes clear that this kind of functionality would be pretty trick to implement properly in vega.

That said, I would just like to note that the lack of this functionality has made for some weird 'gotchas' downstream in packages that depend on vega (e.g., altair/issues/931).

TariqAHassan avatar Dec 31 '18 07:12 TariqAHassan

+1 I think this would be great as well

besquared avatar Aug 23 '19 03:08 besquared

There has not been any progress on this to-date as we don't have someone with the spare cycles to work on it. If anyone is interested, the vega-scenegraph package would be the place to start. Once the scenegraph model and rendering decisions are worked out (which may require significant effort), integration with the rest of Vega could proceed quickly.

jheer avatar Aug 23 '19 07:08 jheer

Please, any news on this? Need point to point gradient with lines

nan4k7 avatar Nov 12 '20 03:11 nan4k7

Also asked on Stack Overflow.

Here is a hacky way of creating a gradient line. Far from perfect but could be useful for some use cases until there is native support.

image



{
 "$schema": "https://vega.github.io/schema/vega/v5.json",
 "description": "A basic stacked area chart example.",
 "width": 500,
 "height": 200,
 "padding": 5,
 "data": [
   {
     "name": "table",
     "values": [
       {"x": 0, "y": 28},
       {"x": 1, "y": 43},
       {"x": 2, "y": 81},
       {"x": 3, "y": 19},
       {"x": 4, "y": 52},
       {"x": 5, "y": 24},
       {"x": 6, "y": 87},
       {"x": 7, "y": 17},
       {"x": 8, "y": 68},
       {"x": 9, "y": 49}
     ],
     "transform": [{"type": "formula", "as": "y2", "expr": "datum.y-1"}]
   }
 ],
 "scales": [
   {
     "name": "x",
     "type": "point",
     "range": "width",
     "domain": {"data": "table", "field": "x"}
   },
   {
     "name": "y",
     "type": "linear",
     "range": "height",
     "nice": true,
     "zero": true,
     "domain": {"data": "table", "field": "y"}
   },
   {"name": "color", "type": "sequential", "range": {"scheme": "rainbow"}}
 ],
 "axes": [
   {"orient": "bottom", "scale": "x", "zindex": 1},
   {"orient": "left", "scale": "y", "zindex": 1}
 ],
 "marks": [
   {
     "type": "area",
     "from": {"data": "table"},
     "encode": {
       "enter": {
         "interpolate": {"value": "monotone"},
         "x": {"scale": "x", "field": "x"},
         "y": {"scale": "y", "field": "y"},
         "y2": {"scale": "y", "field": "y2"},
         "fill": {"signal": "gradient('color', [0,1], [1,1])"}
       }
     }
   }
 ]
}

PBI-David avatar Apr 05 '23 08:04 PBI-David