Search code examples
javascripttypescriptechartsapache-echarts

How does the API for ECharts LinearGradient work?


As illustrated in this question we can add a linear gradient to an echart like this:

  areaStyle: {
          color: new graphic.LinearGradient(0, 0, 0, 1, [
            {
              offset: 0,
              color: 'rgb(255, 158, 68)'
            },
            {
              offset: 1,
              color: 'rgb(255, 70, 131)'
            }])
        }

Also created a Stackblitz demo here.

In all the examples I've seen the LinearGradient instance starts with LinearGradient(0, 0, 0, 1 ... and I'm wondering what the arguments 0, 0, 0, 1 mean / do?


Solution

  • For the LinearGradient coordinates are for the whole plot area:

    • if global parameter is false (default): (0, 0) is the top left corner, (1, 1) is the bottom-right corner
    • if global is true, then the coordinates are in pixels, again (0, 0) is the top left-corner, but the coordinates of the right-bottom corner are (w-1, h-1), where w and h are the width and height of the plot area, in pixels.

    (x0, y0) - (x1, y1) are the ends of a segment in these coordinates: along the line of this segment (and along all parallel lines) colors change according to the data in the stops. Along lines perpendicular to this segment the colors will be the same.

    The fact that the gradient can be expressed only in terms of the whole plot area is often a disadvantage: one would want for instance the fill colors to be a fraction of the value of the function that is plotted, but that is not possible.

    Examples:

    • LinearGradient(0, 0, 0, 1, ....) means a gradient that changes vertically (from top=0 to bottom=1), while all horizontal lines have the same color. It is equivalent to LinearGradient(1, 0, 1, 1, ....) or LinearGradient(0.43, 0, 0.43, 1, ....) for that matter.
    • LinearGradient(0, 0, 1, 0, ....) means a gradient that changes horizontally (from left=0 to right=1), while all vertical lines have the same color.
    • LinearGradient(0, 0, 1, 1, ....) changes along the top-left to bottom-right at an angle that depends on the aspect ratio of the plot area (would be 450 if the width and height were equal).

    colorStops is an array of objects with color and offset properties. Offsets are numbers from 0 to 1, signifying points on the (x0, y0)-(x1, y1), obviously, offset: 0is(x0, y0), offset: 1means(x1, y1)andoffset 0.5` is the middle of the segment.

    The colors of the gradient are calculated along that segment by linear interpolation between each two consecutive colorStops.

    Outside the offsets (if the first offset is greater than 0 or the last one less than 1) and outside the segment (if (x0, y0) and/or (x1, y1) are points interior to the (0, 0) - (1, 1) the color is constant (that is the color of the first or the color of the last offset).

    In the example below, the left chart has two color stops, blue at top-left and yellow at bottom-right. The chart on the right has four color stops: blue at bottom-left and yellow at top-right and in between two red color stops - in between those the color is constant as the interpolation yields always red.

    const myChart1 = echarts.init(document.getElementById('chart-container1'), null, {
      renderer: 'canvas',
      useDirtyRect: false
    });
    
    const myChart2 = echarts.init(document.getElementById('chart-container2'), null, {
      renderer: 'canvas',
      useDirtyRect: false
    });
    
    const option = {
      xAxis: {
        type: 'value',
        data: [1, 2, 3]
      },
      yAxis: {
        type: 'value'
      },
      series: [{
        data: [
          [0, 200],
          [1, 190],
          [2, 200]
        ],
        type: 'line'
      }]
    };
    
    myChart1.setOption(option);
    myChart2.setOption(option);
    
    myChart1.setOption({
      series: [{
        areaStyle: {
          opacity: 0.9,
          color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [{
              offset: 0,
              color: 'blue',
            },
            {
              offset: 1,
              color: 'yellow',
            },
          ]),
        }
      }]
    });
    
    myChart2.setOption({
      series: [{
        areaStyle: {
          opacity: 0.9,
          color: new echarts.graphic.LinearGradient(0, 1, 1, 0, [{
              offset: 0,
              color: 'blue',
            },
            {
              offset: 0.2,
              color: 'red',
            },
            {
              offset: 0.8,
              color: 'red',
            },
            {
              offset: 1,
              color: 'yellow',
            },
          ]),
        }
      }]
    })
    <div id="chart-container1" style="height:300px; width:45vw;display:inline-block"></div>
    <div id="chart-container2" style="height:300px; width:45vw; display:inline-block"></div>
    <script src="https://fastly.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>

    Another technique used often is to set the color constant for various offset intervals (as was the case with red above) and change it for intervals of zero length, (repeating the same offset with a different color) producing uniform color stripes, like in:

    [{
        offset: 0,
        color: 'blue' // start of blue stripe
     },
     {
       offset: 0.33,
       color: 'blue' // end of blue stripe
     },
     {
       offset: 0.33, // start of red stripe
       color: 'red'
     },
     {
       offset: 0.67, // end of red stripe
       color: 'red'
     }
    //.....
    ]
    

    const myChart3 = echarts.init(document.getElementById('chart-container3'), null, {
      renderer: 'canvas',
      useDirtyRect: false
    });
    
    const option = {
      xAxis: {
        type: 'value',
        data: [1, 2, 3]
      },
      yAxis: {
        type: 'value'
      },
      series: [{
        data: [
          [0, 200],
          [1, 190],
          [2, 200]
        ],
        type: 'line'
      }]
    };
    
    myChart3.setOption(option);
    
    myChart3.setOption({
      series: [{
        areaStyle: {
          opacity: 0.9,
          color: new echarts.graphic.LinearGradient(
            0, 0, 1, 0.1, // almost vertical
            [{
                offset: 0,
                color: 'blue', // start of blue stripe
              },
              {
                offset: 0.33,
                color: 'blue', // end of blue stripe
              },
              {
                offset: 0.33,
                color: 'red', // start of red stripe
              },
              {
                offset: 0.67, // end of red stripe
                color: 'red',
              },
              {
                offset: 0.67, // start of green stripe
                color: 'green',
              },
              {
                offset: 1,
                color: 'green', // end of green stripe
              },
            ]),
        }
      }]
    });
    <div id="chart-container3" style="height:300px; width:45vw;display:inline-block"></div>
    <script src="https://fastly.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>