apache-echarts

How to remove white outline from label text in Apache E Charts Bar Chart


I have a Bar Chart made with Apache E Charts. For the label values, there is a white outline bordering the text. I have tried adjusting several options to try and get rid of it, but have had no luck. What is the option that would allow me to get rid of this white outline and just show black text?

Bar Chart

Full options code per request:

const option = useMemo(() => {
if (data) {
  return {
    dataset: {
      source: data,
    },
    textStyle: {
      fontFamily: "'Open Sans', sans-serif",
    },
    title: {
      text: "AR Aging",
      left: "left",
      textStyle: {
        fontFamily: "'Open Sans', sans-serif",
      },
    },
    tooltip: {
      trigger: "axis",
      axisPointer: {
        type: "shadow",
      },
    },
    color: ["#ff4242", "#ff4242", "#FFA500", "#fddc20", "#209c05"],
    grid: { containLabel: true, height: "70%" },
    xAxis: {
      name: "Amount",
      axisLabel: {
        formatter: (params) => formatMoney(params),
      },
    },
    yAxis: { name: "Period", type: "category" },
    series: [
      {
        type: "bar",
        colorBy: "data",
        legendHoverLink: true,
        label: {
          show: true,
          formatter: (params) => formatMoney(params.value[0]),
        },
        labelLayout(params) {
          return {
            x: params.rect.x + 10,
            y: params.rect.y + params.rect.height / 2,
            verticalAlign: "middle",
            align: "left",
          };
        },
        encode: {
          x: "Amount",
          y: "Period",
        },
      },
    ],
  };
}
}, [data]);

formatMoney() takes a number and returns a formatted currency string. And my data object is something like this:

const data = [
      ["Amount", "Period"],
      [100000, "180+"],
      [90000, "91-180"],
      [80000, "61-90"],
      [70000, "31-60"],
      [60000, "0-30"],
    ];

Solution

  • Edit

    What you found is very interesting, I think it's a bug or at least a missing feature in echarts - setting, in a bar chart, the labelLayout x or y properties messes with the coloring of the label. The cause for that is the fact that echarts (in zrender's function Element#updateInnerText) doesn't know that the label isInside. So, if you set x or y, it appears that it will use coloring for labels that are placed outside of the bar, on the background of the chart itself.

    Let's look at a couple of possible solutions:

    1. avoid setting x and y in labelLayout, but use dx and dy instead. The formula used in the original code to set the label 10px from the left margin of the bar was:
      x: params.rect.x + 10;
      the equivalent dx setting (taking into account that the default position is at the center of the params.rect is:
      dx: -params.rect.width/2 + 10.

      Note the animation of the labels in this case. That can of course be disabled by disabling the animation of the series (series[].animation: false).

    2. set an explicit backgroundColor: transparent in the label option. Note that transparent is the default value for label, but the result is not exactly the default behavior of inside label coloring - text color is black or white depending on the color of the bar.

      Note that for this second solution, one may as well set explicitly the color of the label, which precludes the need to set the backgroundColor. So one may juts use color: black instead of backgroundColor: transparent.

    In the snippet below the same bars are shown thrice: for the topmost one, the first solution (use dx instead of x) and the default coloring, for the second one the backgroundColor: transparent solution, and for the third one, the original version with the undesired outline.

    const data = [
      ["Amount", "Period"],
      [100000, "180+"],
      [80000, "61-90"],
      [70000, "31-60"],
      [60000, "0-30"]
    ];
    
    const option = {
      dataset: {
        source: data
      },
      color: ["#ff4242", "#FFA500", "#fddc20", "#209c05"],
      xAxis: {
        name: "Amount",
      },
      yAxis: {
        name: "Period",
        type: "category"
      },
      series: [{ // solution 1: replace x by dx
          type: "bar",
          colorBy: "data",
          label: {
            show: true,
            backgroundColor: 'transparent'
          },
          labelLayout(params) {
            return {
              dx: -params.rect.width / 2 + 10,
              verticalAlign: "middle",
              align: "left"
            };
          },
          encode: {
            x: "Amount",
            y: "Period"
          }
        },
        { // solution 2: backgroundColor: 'transparent'
          type: "bar",
          colorBy: "data",
          label: {
            show: true,
            backgroundColor: 'transparent'
            // or:
            // color: 'black'
          },
          labelLayout(params) {
            return {
              x: params.rect.x + 10,
              verticalAlign: "middle",
              align: "left"
            };
          },
          encode: {
            x: "Amount",
            y: "Period"
          }
        },
        { // original erroneous outline
          type: "bar",
          colorBy: "data",
          label: {
            show: true,
          },
          labelLayout(params) {
            return {
              x: params.rect.x + 10,
              verticalAlign: "middle",
              align: "left"
            };
          },
          encode: {
            x: "Amount",
            y: "Period"
          }
        }
      ]
    };
    
    const myChart = echarts.init(document.getElementById('chart-container'), null, {
      renderer: 'svg'
    });
    myChart.setOption(option);
    <div class="chart" id="chart-container" style="height:400px; width: 80vw"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.2/echarts.min.js"></script>

    The next snippet does the same, with the only difference that the chart background color is black:

    const data = [
      ["Amount", "Period"],
      [100000, "180+"],
      [80000, "61-90"],
      [70000, "31-60"],
      [60000, "0-30"]
    ];
    
    const option = {
      backgroundColor: '#000',
      dataset: {
        source: data
      },
      color: ["#ff4242", "#FFA500", "#fddc20", "#209c05"],
      xAxis: {
        name: "Amount",
      },
      yAxis: {
        name: "Period",
        type: "category"
      },
      series: [{ // solution 1: replace x by dx
          type: "bar",
          colorBy: "data",
          label: {
            show: true,
            backgroundColor: 'transparent'
          },
          labelLayout(params) {
            return {
              dx: -params.rect.width / 2 + 10,
              verticalAlign: "middle",
              align: "left"
            };
          },
          encode: {
            x: "Amount",
            y: "Period"
          }
        },
        { // solution 2: backgroundColor: 'transparent'
          type: "bar",
          colorBy: "data",
          label: {
            show: true,
            backgroundColor: 'transparent'
            // or:
            // color: 'black'
          },
          labelLayout(params) {
            return {
              x: params.rect.x + 10,
              verticalAlign: "middle",
              align: "left"
            };
          },
          encode: {
            x: "Amount",
            y: "Period"
          }
        },
        { // original erroneous outline
          type: "bar",
          colorBy: "data",
          label: {
            show: true,
          },
          labelLayout(params) {
            return {
              x: params.rect.x + 10,
              verticalAlign: "middle",
              align: "left"
            };
          },
          encode: {
            x: "Amount",
            y: "Period"
          }
        }
      ]
    };
    
    const myChart = echarts.init(document.getElementById('chart-container'), null, {
      renderer: 'canvas'
    });
    myChart.setOption(option);
    <div class="chart" id="chart-container" style="height:400px; width: 80vw"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.2/echarts.min.js"></script>

    One can see that the coloring of the labels in the first series (topmost bar in each group) makes a best contrast to the color of the bar, the second series has a fixed color, and the third (the original one) the color is to ensure the best contrast to the background color


    Original post

    I think you somehow activated the shadow of the label text. That's not the default behavior, see this echarts example.

    So to get something like you have I had to set the label option as

        label: {
            textShadowColor: 'white',
            textShadowOffsetX: 1,
            textShadowOffsetY: 1,
            textShadowBlur: 2,
            color: 'black',
            show: true
          }
    

    example fork - first series

    So to cancel it, I expect you may set any of

       label: {
            textShadowColor: 'transparent', // or
            textShadowOffsetX: 0,  textShadowOffsetY: 0, // or
            textShadowBlur: 0,
       }
    

    Please let me know if that doesn't help.