admin管理员组

文章数量:1355592

I'm using this great library to create some reports. One of my challenges is with Custom Gauge, where I need to position the label with two values. In figure one, one can see what I built.

In Figure 2, this is the requirement of what I should design.
Is it possible to modify the labels' positioning and do it? Thank you for being so supportive,

What I made What expected

I'm using this great library to create some reports. One of my challenges is with Custom Gauge, where I need to position the label with two values. In figure one, one can see what I built.

In Figure 2, this is the requirement of what I should design.
Is it possible to modify the labels' positioning and do it? Thank you for being so supportive,

What I made What expected
// code to customise the labels
ing


import { Component } from '@angular/core';
import { NgxEchartsModule, NGX_ECHARTS_CONFIG } from 'ngx-echarts';
import * as echarts from 'echarts/core';
import { GaugeChart } from 'echarts/charts';
import { GridComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
import { offset } from '@popperjs/core';

echarts.use([GaugeChart, GridComponent, CanvasRenderer]);

@Component({
  selector: 'app-gauge',
  standalone: true,
  imports: [NgxEchartsModule],
  templateUrl: './gaugeponent.html',
  styleUrls: ['./gaugeponent.scss'],
  providers: [
    { provide: NGX_ECHARTS_CONFIG, useValue: { echarts } }
  ]
})
export class GaugeComponent {
  chartOptions = {
    series: [
      {
        type: 'gauge',
        startAngle: 180,
        endAngle: 0,
        center: ['50%', '75%'],
        radius: '90%',
        min: 0,
        max: 1,
        splitNumber: 8,
        axisLine: {
          lineStyle: {
            width: 20,
            color: [
              [0.125, '#FC0202FF'],
              [0.250, '#A15D39FF'],
              [0.375, '#F8C187FF'],
              [0.500, '#F5FF6EAF'],
              [0.625, '#A8FF6EFF'],
              [0.750, '#60FD72FF'],
              [0.875, '#2FCE77FF'],
              [1,     '#16852EFF']
            ]
          }
        },
        pointer: {
          icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
          length: '12%',
          width: 25,
          offsetCenter: [0, '-60%'],
          itemStyle: {
            color: 'auto'
          }
        },
        axisTick: {
          length: 12,
          lineStyle: {
            color: 'auto',
            width: 2
          }
        },
        splitLine: {
          lenth:20,
          lineStyle: {
            color: 'auto',
            width: 5
          }
        },
        axisLabel: {
          color: '#464646',
          fontSize: 15,
          distance: -40,
          offset: -20,
          rotate: 'tangential',
          formatter: function (value: number) {
            if (value >= 0.875 && value <= 1.00) {
              return 'AAA';

            } else if (value === 0.875) {
                return 'AA';
            } else if (value === 0.750) {
                return 'A';
            } else if (value === 0.625) {
                return 'BBB';
            } else if (value === 0.500) {
              return 'BB';
            } else if (value === 0.375) {
              return 'B';
            } else if (value === 0.250) {
              return 'C';
          }  else if (value >= 0.00 && value < 0.125) {
            return 'D';
          }
          return '';
          }
        },
        title: {
          offsetCenter: [0, '-10%'],
          fontSize: 20
        },
        detail: {
          fontSize: 30,
          offsetCenter: [0, '-30%'],
          valueAnimation: true,
          formatter: function (value: number) {
            return Math.round(value * 100) + '';
          },
          color: 'inherit'
        },
        data: [
          {
            value: 0.9,
            name: 'Grade Rating'
          }
        ]
      }
    ]
  };
}
Share Improve this question edited Mar 30 at 13:11 rozsazoltan 10.8k6 gold badges19 silver badges52 bronze badges asked Mar 30 at 11:49 EvangelosEvangelos 1 1
  • So, you don't want to place the labels of the gauge sections on the boundary lines but in the center instead? Figure 2 has a bit too much extra information, so it needs to be clarified. – rozsazoltan Commented Mar 30 at 11:56
Add a comment  | 

1 Answer 1

Reset to default 0

TLDR:

  • The labels can be placed towards each boundary value. To achieve this, the splitNumber parameter should be set to at least the number of boundary values we have.
  • The color of the section between two boundary values can be the same, allowing us to visually merge them.
  • I used this visual trick in my examples to position the label in the center. Then, with a calculation, I set the label string to an empty string "" for the boundary values that are not centered.
  • Since the exact center placement can be calculated, I tried to dynamically create the appropriate centerValue for each section from the sections and insert two colors between the startValue and endValue.

Correction of the boundary values mentioned in the question

NOTE: Not part of the canonical answer, see TLDR and solution.

First of all, you defined the boundary values in an interesting way. I have modified them. Now, each boundary value appears at the end of its respective section. This allows us to apply a consistent rule for placing them in reverse order.

  • So, D does not appear at 0 but does at 0.125.
  • Similarly, AAA does not overwrite AA but instead appears at 1.00.

const chartDom = document.getElementById('chart');
const chart = echarts.init(chartDom);

const option = {
  series: [
    {
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      radius: '90%',
      min: 0,
      max: 1,
      splitNumber: 8,
      axisLine: {
        lineStyle: {
          width: 20,
          color: [
            [0.125, '#FC0202FF'],
            [0.250, '#A15D39FF'],
            [0.375, '#F8C187FF'],
            [0.500, '#F5FF6EAF'],
            [0.625, '#A8FF6EFF'],
            [0.750, '#60FD72FF'],
            [0.875, '#2FCE77FF'],
            [1,     '#16852EFF']
          ]
        }
      },
      pointer: {
        icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
        length: '12%',
        width: 25,
        offsetCenter: [0, '-60%'],
        itemStyle: {
          color: 'auto'
        }
      },
      axisTick: {
        length: 12,
        lineStyle: {
          color: 'auto',
          width: 2
        }
      },
      splitLine: {
        length: 20,
        lineStyle: {
          color: 'auto',
          width: 5
        }
      },
      axisLabel: {
        color: '#464646',
        fontSize: 15,
        distance: -40,
        rotate: 'tangential',
        formatter: function (value) {
          /* do not replace AA with "value > 0.875" */
          if (value === 1.00) {
            return 'AAA';
          }
          else if (value === 0.875) {
            return 'AA';
          }
          else if (value === 0.750) {
            return 'A';
          }
          else if (value === 0.625) {
            return 'BBB';
          }
          else if (value === 0.500) {
            return 'BB';
          }
          else if (value === 0.375) {
            return 'B';
          }
          else if (value === 0.250) {
            return 'C';
          }
          /* move to first boundary line instead of starter value */
          else if (value === 0.125) {
            return 'D';
          }
          return '';
        }
      },
      title: {
        offsetCenter: [0, '-10%'],
        fontSize: 20
      },
      detail: {
        fontSize: 30,
        offsetCenter: [0, '-30%'],
        valueAnimation: true,
        formatter: function (value) {
          return Math.round(value * 100) + '';
        },
        color: 'inherit'
      },
      data: [
        {
          value: 0.9,
          name: 'Grade Rating'
        }
      ]
    }
  ]
};

chart.setOption(option);
<script src="https://cdn.jsdelivr/npm/[email protected]/dist/echarts.min.js"></script>

<div id="chart" style="width: 400px; height: 350px;"></div>

Solution

NOTE: This is my canonical solution, in which I demonstrate that by inserting multiple sections with the same color, the label position can be "modified" and placed at any desired boundary value by introducing additional breakpoints.

Now that clarified this, let's highlight the maximum boundary values, the letters, and the colors. I placed these into a sections array. After that, I determined the start and center values for each section.

let sections = [
  { endValue: 0.125, color: '#FC0202FF', label: 'D' },
  { endValue: 0.250, color: '#A15D39FF', label: 'C' },
  { endValue: 0.375, color: '#F8C187FF', label: 'B' },
  { endValue: 0.500, color: '#F5FF6EAF', label: 'BB' },
  { endValue: 0.625, color: '#A8FF6EFF', label: 'BBB' },
  { endValue: 0.750, color: '#60FD72FF', label: 'A' },
  { endValue: 0.875, color: '#2FCE77FF', label: 'AA' },
  { endValue: 1, color: '#16852EFF', label: 'AAA' },
]
sections = sections.map((section, index) => {
  const prevSection = sections[index - 1]
  section.startValue = prevSection?.endValue ?? 0
  section.centerValue = section.startValue + (section.endValue - section.startValue) / 2
  
  return section
})

I dynamically generate the colors based on the center value from sections, assigning two colors to each section:

  • First part: From startValue to centerValue (this allows placing a label at centerValue).
  • Second part: From centerValue to endValue (this allows placing a label at endValue).
  • Of course, the coloring of the two parts is the same.
const createAxisLineColors = () => {
  const colors = []
  for (const section of sections) {
    colors.push([section.centerValue, section.color])
    colors.push([section.endValue, section.color])
  }
  return colors
}
{
  axisLine: {
    lineStyle: {
      width: 20,
      color: createAxisLineColors(),
    },
  },
}

Then, I set up the label formatter so that if a given value is greater than a section's startValue but less than its endValue, it must be the center value, and I request it to display section.label.

const getLabelForValue = (value) => {
  for (const section of sections) {
    /* startValue < value < endValue  <<<  center */
    if (value > section.startValue && value < section.endValue) {
      return section.label
    }
  }
  
  return ''
}
{
  axisLabel: {
    color: '#464646',
    fontSize: 15,
    distance: -40,
    rotate: 'tangential',
    formatter: function (value) {
      return getLabelForValue(value);
    },
  },
}

To ensure the correct number of labels appear, splitnumber should be set to sections.length * 2, since each section has two ranges (start-center and center-end), but the colors remain the same across these ranges.

{
  splitNumber: sections.length * 2,
}

Now that split each section in half, we have the opportunity to place a label at the midpoint of the sections, while removing the label from the end of the sections.

Example #1

const chartDom = document.getElementById('chart');
const chart = echarts.init(chartDom);

let sections = [
  { endValue: 0.125, color: '#FC0202FF', label: 'D' },
  { endValue: 0.250, color: '#A15D39FF', label: 'C' },
  { endValue: 0.375, color: '#F8C187FF', label: 'B' },
  { endValue: 0.500, color: '#F5FF6EAF', label: 'BB' },
  { endValue: 0.625, color: '#A8FF6EFF', label: 'BBB' },
  { endValue: 0.750, color: '#60FD72FF', label: 'A' },
  { endValue: 0.875, color: '#2FCE77FF', label: 'AA' },
  { endValue: 1, color: '#16852EFF', label: 'AAA' },
]
sections = sections.map((section, index) => {
  const prevSection = sections[index - 1]
  section.startValue = prevSection?.endValue ?? 0
  section.centerValue = section.startValue + (section.endValue - section.startValue) / 2
  
  return section
})

const createAxisLineColors = () => {
  const colors = []
  for (const section of sections) {
    colors.push([section.centerValue, section.color])
    colors.push([section.endValue, section.color])
  }
  return colors
}

const getLabelForValue = (value) => {
  for (const section of sections) {
    /* startValue < value < endValue  <<<  center */
    if (value > section.startValue && value < section.endValue) {
      return section.label
    }
  }
  
  return ''
}

const option = {
  series: [
    {
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      radius: '90%',
      min: 0,
      max: 1,
      splitNumber: sections.length * 2, // sections length * 2
      axisLine: {
        lineStyle: {
          width: 20,
          color: createAxisLineColors(),
        },
      },
      pointer: {
        icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
        length: '12%',
        width: 25,
        offsetCenter: [0, '-60%'],
        itemStyle: {
          color: 'auto'
        }
      },
      axisTick: {
        length: 12,
        lineStyle: {
          color: 'auto',
          width: 2
        }
      },
      splitLine: {
        length: 20,
        lineStyle: {
          color: 'auto',
          width: 5
        }
      },
      axisLabel: {
        color: '#464646',
        fontSize: 15,
        distance: -40,
        rotate: 'tangential',
        formatter: function (value) {
          // console.log(value, getLabelForValue(value))
          return getLabelForValue(value);
        },
      },
      title: {
        offsetCenter: [0, '-10%'],
        fontSize: 20,
      },
      detail: {
        fontSize: 30,
        offsetCenter: [0, '-30%'],
        valueAnimation: true,
        formatter: function (value) {
          return Math.round(value * 100) + '';
        },
        color: 'inherit'
      },
      data: [
        {
          value: 0.9,
          name: 'Grade Rating',
        },
      ],
    },
  ],
}

chart.setOption(option)
<script src="https://cdn.jsdelivr/npm/[email protected]/dist/echarts.min.js"></script>

<div id="chart" style="width: 400px; height: 400px;"></div>

Example #2

To swap the colors, you just need to edit the sections array. For example, when reversed, it looks like this, but it's important to always go from 0 to 1.

const chartDom = document.getElementById('chart');
const chart = echarts.init(chartDom);

let sections = [
  { endValue: 0.125, color: '#16852EFF', label: 'AAAA' },
  { endValue: 0.250, color: '#2FCE77FF', label: 'AA' },
  { endValue: 0.375, color: '#60FD72FF', label: 'A' },
  { endValue: 0.500, color: '#A8FF6EFF', label: 'BBB' },
  { endValue: 0.625, color: '#F5FF6EAF', label: 'BB' },
  { endValue: 0.750, color: '#F8C187FF', label: 'B' },
  { endValue: 0.875, color: '#A15D39FF', label: 'C' },
  { endValue: 1, color: '#FC0202FF', label: 'D' },
]
sections = sections.map((section, index) => {
  const prevSection = sections[index - 1]
  section.startValue = prevSection?.endValue ?? 0
  section.centerValue = section.startValue + (section.endValue - section.startValue) / 2
  
  return section
})

const createAxisLineColors = () => {
  const colors = []
  for (const section of sections) {
    colors.push([section.centerValue, section.color])
    colors.push([section.endValue, section.color])
  }
  return colors
}

const getLabelForValue = (value) => {
  for (const section of sections) {
    /* startValue < value < endValue  <<<  center */
    if (value > section.startValue && value < section.endValue) {
      return section.label
    }
  }
  
  return ''
}

const option = {
  series: [
    {
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      radius: '90%',
      min: 0,
      max: 1,
      splitNumber: sections.length * 2, // sections length * 2
      axisLine: {
        lineStyle: {
          width: 20,
          color: createAxisLineColors(),
        },
      },
      pointer: {
        icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
        length: '12%',
        width: 25,
        offsetCenter: [0, '-60%'],
        itemStyle: {
          color: 'auto'
        }
      },
      axisTick: {
        length: 12,
        lineStyle: {
          color: 'auto',
          width: 2
        }
      },
      splitLine: {
        length: 20,
        lineStyle: {
          color: 'auto',
          width: 5
        }
      },
      axisLabel: {
        color: '#464646',
        fontSize: 15,
        distance: -40,
        rotate: 'tangential',
        formatter: function (value) {
          // console.log(value, getLabelForValue(value))
          return getLabelForValue(value);
        },
      },
      title: {
        offsetCenter: [0, '-10%'],
        fontSize: 20,
      },
      detail: {
        fontSize: 30,
        offsetCenter: [0, '-30%'],
        valueAnimation: true,
        formatter: function (value) {
          return Math.round(value * 100) + '';
        },
        color: 'inherit'
      },
      data: [
        {
          value: 0.1,
          name: 'Grade Rating',
        },
      ],
    },
  ],
}

chart.setOption(option)
<script src="https://cdn.jsdelivr/npm/[email protected]/dist/echarts.min.js"></script>

<div id="chart" style="width: 400px; height: 400px;"></div>

Example #3

Can also interpret the value as 0.9 instead of 0.1 if we customize its formatter.

const chartDom = document.getElementById('chart');
const chart = echarts.init(chartDom);

let sections = [
  { endValue: 0.125, color: '#16852EFF', label: 'AAAA' },
  { endValue: 0.250, color: '#2FCE77FF', label: 'AA' },
  { endValue: 0.375, color: '#60FD72FF', label: 'A' },
  { endValue: 0.500, color: '#A8FF6EFF', label: 'BBB' },
  { endValue: 0.625, color: '#F5FF6EAF', label: 'BB' },
  { endValue: 0.750, color: '#F8C187FF', label: 'B' },
  { endValue: 0.875, color: '#A15D39FF', label: 'C' },
  { endValue: 1, color: '#FC0202FF', label: 'D' },
]
sections = sections.map((section, index) => {
  const prevSection = sections[index - 1]
  section.startValue = prevSection?.endValue ?? 0
  section.centerValue = section.startValue + (section.endValue - section.startValue) / 2
  
  return section
})

const createAxisLineColors = () => {
  const colors = []
  for (const section of sections) {
    colors.push([section.centerValue, section.color])
    colors.push([section.endValue, section.color])
  }
  return colors
}

const getLabelForValue = (value) => {
  for (const section of sections) {
    /* startValue < value < endValue  <<<  center */
    if (value > section.startValue && value < section.endValue) {
      return section.label
    }
  }
  
  return ''
}

const option = {
  series: [
    {
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      radius: '90%',
      min: 0,
      max: 1,
      splitNumber: sections.length * 2, // sections length * 2
      axisLine: {
        lineStyle: {
          width: 20,
          color: createAxisLineColors(),
        },
      },
      pointer: {
        icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
        length: '12%',
        width: 25,
        offsetCenter: [0, '-60%'],
        itemStyle: {
          color: 'auto'
        }
      },
      axisTick: {
        length: 12,
        lineStyle: {
          color: 'auto',
          width: 2
        }
      },
      splitLine: {
        length: 20,
        lineStyle: {
          color: 'auto',
          width: 5
        }
      },
      axisLabel: {
        color: '#464646',
        fontSize: 15,
        distance: -40,
        rotate: 'tangential',
        formatter: function (value) {
          // console.log(value, getLabelForValue(value))
          return getLabelForValue(value);
        },
      },
      title: {
        offsetCenter: [0, '-10%'],
        fontSize: 20,
      },
      detail: {
        fontSize: 30,
        offsetCenter: [0, '-30%'],
        valueAnimation: true,
        formatter: function (value) {
          return Math.round((1 - value) * 100) + '' // HERE
        },
        color: 'inherit'
      },
      data: [
        {
          value: 0.1,
          name: 'Grade Rating',
        },
      ],
    },
  ],
}

chart.setOption(option)
<script src="https://cdn.jsdelivr/npm/[email protected]/dist/echarts.min.js"></script>

<div id="chart" style="width: 400px; height: 400px;"></div>



Solution with calculating ASC/DESC values

NOTE: My canonical answer is that the appropriate colored sections should be declared with the same background color. Therefore, this additional solution is just an interesting approach and is not part of the canonical answer.

If you want the colors to be reversed like in Example #2, but you want the values to decrease from 1 to 0, then you need to swap the min and max values in the chart option, and update the sections array accordingly.

It's important to note that the color-generating script I wrote assumes that your smallest value is sections[0], so it's crucial that the order of values in the sections array is correct.

By default, it's simple to write the code if MIN is always smaller than MAX. However, if MIN is greater than MAX, meaning creating a decreasing list, you need to prepare custom functions to generate the sections and color ranges. This is because, if MIN is greater than MAX, for example, we go from 1 to 0, but the colors still go from 0 to 100%. In this case, the simpler functions mentioned above are modified accordingly.

NOTE: I haven't perfected it; it's only perfect in cases like 0-1 or 1-0, or similar cases that cover 100%.

const chartDom = document.getElementById('chart');
const chart = echarts.init(chartDom);

const MIN = 1
const MAX = 0

// ASC: 0, 0.125, ..., 1
// DESC: 1, ..., 0.125, 0
const isAsc = MIN < MAX

let sections = [
  { endValue: 0.875, color: '#16852EFF', label: 'AAA' },
  { endValue: 0.750, color: '#2FCE77FF', label: 'AA' },
  { endValue: 0.650, color: '#60FD72FF', label: 'A' },
  { endValue: 0.500, color: '#A8FF6EFF', label: 'BBB' },
  { endValue: 0.375, color: '#F5FF6EAF', label: 'BB' },
  { endValue: 0.250, color: '#F8C187FF', label: 'B' },
  { endValue: 0.125, color: '#A15D39FF', label: 'C' },
  { endValue: 0, color: '#FC0202FF', label: 'D' },
]
sections = sections.map((section, index) => {
  const prevSection = sections[index - 1]
  section.startValue = prevSection?.endValue ?? MIN
  
  if (isAsc) {
    section.centerValue = section.startValue + (section.endValue - section.startValue) / 2
  }
  else {
    section.centerValue = section.endValue + (section.startValue - section.endValue) / 2
  }
  
  return section
})

const createAxisLineColors = () => {
  const colors = []
  for (const section of sections) {
    colors.push([MIN + (isAsc ? 1 : -1) * section.centerValue, section.color])
    colors.push([MIN + (isAsc ? 1 : -1) * section.endValue, section.color])
  }
  return colors
}

const getLabelForValue = (value) => {
  for (const section of sections) {
    /* ASC: startValue < value < endValue  <<<  center */
    if (isAsc && value > section.startValue && value < section.endValue) {
      return section.label
    }
    /* DESC: endValue < value < startValue  <<<  center */
    else if (! isAsc && value > section.endValue && value < section.startValue) {
      return section.label
    }
  }
  
  return ''
}

const option = {
  series: [
    {
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      radius: '90%',
      min: MIN, // HERE
      max: MAX, // HERE
      splitNumber: sections.length * 2, // sections length * 2
      axisLine: {
        lineStyle: {
          width: 20,
          color: createAxisLineColors(),
        },
      },
      pointer: {
        icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
        length: '12%',
        width: 25,
        offsetCenter: [0, '-60%'],
        itemStyle: {
          color: 'auto'
        }
      },
      axisTick: {
        length: 12,
        lineStyle: {
          color: 'auto',
          width: 2
        }
      },
      splitLine: {
        length: 20,
        lineStyle: {
          color: 'auto',
          width: 5
        }
      },
      axisLabel: {
        color: '#464646',
        fontSize: 15,
        distance: -40,
        rotate: 'tangential',
        formatter: function (value) {
          // console.log(value, getLabelForValue(value))
          return getLabelForValue(value);
        },
      },
      title: {
        offsetCenter: [0, '-10%'],
        fontSize: 20,
      },
      detail: {
        fontSize: 30,
        offsetCenter: [0, '-30%'],
        valueAnimation: true,
        formatter: function (value) {
          return Math.round(value * 100) + '';
        },
        color: 'inherit'
      },
      data: [
        {
          value: 0.9,
          name: 'Grade Rating',
        },
      ],
    },
  ],
}

chart.setOption(option)
<script src="https://cdn.jsdelivr/npm/[email protected]/dist/echarts.min.js"></script>

<div id="chart" style="width: 400px; height: 400px;"></div>

And final code with original (Example #1) data:

const chartDom = document.getElementById('chart');
const chart = echarts.init(chartDom);

const MIN = 0
const MAX = 1

// ASC: 0, 0.125, ..., 1
// DESC: 1, ..., 0.125, 0
const isAsc = MIN < MAX

let sections = [
  { endValue: 0.125, color: '#FC0202FF', label: 'D' },
  { endValue: 0.250, color: '#A15D39FF', label: 'C' },
  { endValue: 0.375, color: '#F8C187FF', label: 'B' },
  { endValue: 0.500, color: '#F5FF6EAF', label: 'BB' },
  { endValue: 0.625, color: '#A8FF6EFF', label: 'BBB' },
  { endValue: 0.750, color: '#60FD72FF', label: 'A' },
  { endValue: 0.875, color: '#2FCE77FF', label: 'AA' },
  { endValue: 1, color: '#16852EFF', label: 'AAA' },
]
sections = sections.map((section, index) => {
  const prevSection = sections[index - 1]
  section.startValue = prevSection?.endValue ?? MIN
  
  if (isAsc) {
    section.centerValue = section.startValue + (section.endValue - section.startValue) / 2
  }
  else {
    section.centerValue = section.endValue + (section.startValue - section.endValue) / 2
  }
  
  return section
})

const createAxisLineColors = () => {
  const colors = []
  for (const section of sections) {
    colors.push([MIN + (isAsc ? 1 : -1) * section.centerValue, section.color])
    colors.push([MIN + (isAsc ? 1 : -1) * section.endValue, section.color])
  }
  return colors
}

const getLabelForValue = (value) => {
  for (const section of sections) {
    /* ASC: startValue < value < endValue  <<<  center */
    if (isAsc && value > section.startValue && value < section.endValue) {
      return section.label
    }
    /* DESC: endValue < value < startValue  <<<  center */
    else if (! isAsc && value > section.endValue && value < section.startValue) {
      return section.label
    }
  }
  
  return ''
}

const option = {
  series: [
    {
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      radius: '90%',
      min: MIN, // HERE
      max: MAX, // HERE
      splitNumber: sections.length * 2, // sections length * 2
      axisLine: {
        lineStyle: {
          width: 20,
          color: createAxisLineColors(),
        },
      },
      pointer: {
        icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
        length: '12%',
        width: 25,
        offsetCenter: [0, '-60%'],
        itemStyle: {
          color: 'auto'
        }
      },
      axisTick: {
        length: 12,
        lineStyle: {
          color: 'auto',
          width: 2
        }
      },
      splitLine: {
        length: 20,
        lineStyle: {
          color: 'auto',
          width: 5
        }
      },
      axisLabel: {
        color: '#464646',
        fontSize: 15,
        distance: -40,
        rotate: 'tangential',
        formatter: function (value) {
          // console.log(value, getLabelForValue(value))
          return getLabelForValue(value);
        },
      },
      title: {
        offsetCenter: [0, '-10%'],
        fontSize: 20,
      },
      detail: {
        fontSize: 30,
        offsetCenter: [0, '-30%'],
        valueAnimation: true,
        formatter: function (value) {
          return Math.round(value * 100) + '';
        },
        color: 'inherit'
      },
      data: [
        {
          value: 0.9,
          name: 'Grade Rating',
        },
      ],
    },
  ],
}

chart.setOption(option)
<script src="https://cdn.jsdelivr/npm/[email protected]/dist/echarts.min.js"></script>

<div id="chart" style="width: 400px; height: 400px;"></div>

本文标签: javascriptApache Echarts Custom Gauge Label positioningStack Overflow