Two options for gradient color of circular progress bar

Background

Implement the following gradient color ring progress bar

Solution

When it comes to the gradient color of the circular progress bar, I believe everyone first thinks of el-progress and echarts. Now we develop these two solutions.

Method 1: el-progress implementation

Guide element-plus, visit the official website

The official website provides a way to write a circular progress bar, but does not provide a gradient color configuration item, which requires us to modify it manually. The code is as follows:

<template>
          <div class="progress-class">
            <el-progress :show-text="false" type="circle" :percentage="75" />
            //The key code is as follows
            <svg width="100%" height="100%">
              <defs>
                //x,y are the control of gradient color direction and range
                <linearGradient id="yellow" x1="1" y1="0" x2="0.3" y2="1">
                  <stop
                    offset="0%"
                    style="stop-color: #eef2f9" //Gradient color
                    stop-opacity="0.1" //Transparency
                  ></stop>

                  <stop
                    offset="100%"
                    style="stop-color: #1a6dff" //Gradient color
                    stop-opacity="1" //Transparency
                  ></stop>
                </linearGradient>
              </defs>
            </svg>
          </div>
  </template>
 <style scoped lang="scss">
  .progress-class {<!-- -->
      position: relative;
      :deep(svg > path:nth-child(2)) {<!-- -->
        stroke: url(#yellow);
      }
    }
 </style>

We can see in the console that el-progress is actually composed of two paths. The first one is the background color ring, and the second one is the progress bar. By modifying the stroke, we see that the blue color has been changed to red. ,so
As shown in the above code, we need to manually add an svg to replace the second svg in element, and replace it by giving the specified id. The color only needs to be modified by ourselves as needed.

Method 2: echarts implementation

Old rules guide official website
If you want to realize the nesting of multiple gradient color progress bars, the above method has limitations, and it is much more convenient to use the echarts method. My solution is to use the dashboard gauge in echarts to implement it. The code is as follows:

<template>
  <div ref="chart" class="chart_wapper"></div>
</template>

<script setup>
import {<!-- --> ref, onMounted } from 'vue';
import * as echarts from 'echarts/core';
import {<!-- --> GaugeChart } from 'echarts/charts';
import {<!-- --> CanvasRenderer } from 'echarts/renderers';
//Register necessary components
echarts.use([GaugeChart, CanvasRenderer]);

const chart = ref();
const gaugeChart = ref();
var option;
const props = defineProps({<!-- -->
  gaugeData: {<!-- -->
    type: Array,
    default: () => []
  }
});

onMounted(() => {<!-- -->
  initChart(); // Initialization icon example
});
function initChart() {<!-- -->
  // Equivalent to using the Canvas renderer (default): echarts.init(containerDom, null, { renderer: 'canvas' })
  gaugeChart.value = echarts.init(chart.value);
  option = {<!-- -->
    color: ['#7CFFB2'],
    series: [
      {<!-- -->
        type: 'gauge',
        name: 'Dashboard', // Series name, used for tooltip display
        /*
          Strategy for picking colors from the palette option.color, optional 'series' | 'data'
          'series': Allocate colors in the palette according to series. All data in the same series use the same color.
          'data': Assign colors in the palette according to data items, using a different color for each data item
        */
        zlevel: 2,
        colorBy: 'data',
        center: ['50%', '50%'], // Circle center coordinates, [400, 300]: The first item in the array is the abscissa, the second item is the ordinate, and supports setting as a percentage. ['50%', '75%']: When set to a percentage, the first item is relative to the container width, and the second item is relative to the container height.
        radius: '100%', // Dashboard radius, which can be a percentage relative to half of the smaller item of container height and width, or an absolute value.
        legendHoverLink: true, // Whether to enable linkage highlighting when the legend hovers
        startAngle: 270, // Starting angle of the instrument panel. The center of the circle is 0 degrees on the right-hand side, 90 degrees directly above, and 180 degrees on the left-hand side.
        endAngle: -90, // End angle of the instrument panel.
        clockwise: true, // Whether the dashboard scale increases clockwise
        // min: 0, // The smallest data value, mapped to minAngle
        // max: 100, // Maximum data value, mapped to maxAngle
        // splitNumber: 0, // The number of segments of the dashboard scale

        axisLine: {<!-- -->
          // Instrument panel axis related configuration
          show: true, // Whether to display the dashboard axis
          roundCap: true, // Whether to display circles at both ends
          lineStyle: {<!-- -->
            // Dashboard axis style
            width: 6 // Axis width
            // color: [ // The axis of the instrument panel can be divided into segments of different colors. The end position and color of each segment can be represented by an array
            // [20, '#FF6E76'],
            // [40, '#FDDD60'],
            // [60, '#58D9F9'],
            // [80, '#7CFFB2'],
            // [100, '#1677FF']
            // ],
            // shadowBlur: 10, // Blur size of graphics shadow
            // shadowColor: 'rgba(0, 0, 0, 0.5)', // shadow color
            // shadowOffsetX: 3, // The offset distance of the shadow in the horizontal direction
            // shadowOffsetY: 3, // Offset distance in the vertical direction of the shadow
            // opacity: 1 // Graphic transparency. Supports numbers from 0 to 1. When it is 0, the graph is not drawn.
          }
        },
        progress: {<!-- -->
          // Show current progress
          show: true, // Whether to display the progress bar
          overlap: false, // Whether the progress bars overlap when there are multiple sets of data
          width: 12, // progress bar width
          roundCap: true, // Whether to display circles at both ends
          clip: true, // Whether to crop the excess part
          itemStyle: {<!-- -->
            //Progress bar style
            color:{<!-- -->
  // Custom gradient color
  type: 'linear',
  x: 1,
  y: 0,
  x2: 0.3,
  y2: 1,
  colorStops: [
    {<!-- -->
      offset: 0,
      color: '#1a6dff' // Color at 0%
    },

    {<!-- -->
      offset: 1,
      color: '#ECF2FF' // Color at 100%
    }
  ],
  global: false // Default is false
}, //The color of the graphic
            // borderColor: '#1677FF' // The stroke color of the graphic
            // borderWidth: 1, // Stroke line width. When 0, there is no stroke.
            // borderType: 'solid', // Stroke type, optional: 'solid' 'dashed' 'dotted'
          }
        },
        splitLine: {<!-- -->
          //divider style
          show: false // Whether to display the separator line
        },
        axisTick: {<!-- -->
          //Scale style
          show: false // Whether to display scale
        },
        axisLabel: {<!-- -->
          // tick labels
          show: false, // Whether to display labels
          color: '#aaa', // color of text
          fontStyle: 'normal', // Text font style, optional 'normal' 'italic' 'oblique'
          fontWeight: 'bold', // The weight of the text font, optional 'normal' 'bold' 'bolder' 'lighter' 100 | 200 | 300 | 400...
          fontFamily: 'sans-serif', // The font family of the text, it can also be 'serif', 'monospace', 'Arial', 'Courier New', 'Microsoft YaHei\ ', ...
          fontSize: 40 //The font size of the text
          // lineHeight: 28, // line height
          /*
            Color values can be used, for example: '#123234', 'red', 'rgba(0,23,11,0.3)'
            You can also use images directly, for example:
            backgroundColor: {
              image: 'xxx/xxx.png'
              // This can be the URL of the image,
              // Or the dataURI of the image,
              // Or HTMLImageElement object,
              // Or HTMLCanvasElement object.
            }
          */
          // backgroundColor: 'transparent', // text block background color
          // borderColor: 'red', // text block border color
          // borderWidth: 3, // Text block border width
          // borderType: 'solid', // Text block border stroke type, optional 'solid' 'dashed' 'dotted'
          // borderRadius: 10, // rounded corners of text block
          // padding: [6, 12], // The padding of the text block, the width and height of the text block do not include padding
          // width: 60, // Text display width
          // height: 60 // Text display height
        },
        pointer: {<!-- -->
          // Dashboard pointer
          show: true, // Whether to display the pointer
          showAbove: true, // Whether the pointer is displayed above the title and dashboard details
          // Can be set to an image via 'image://url', where URL is the link to the image, or dataURI.
          icon: 'circle', // Marker type, optional 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin' , 'arrow', 'none'
          offsetCenter: [0, '-45%'], // Relative to the offset position of the center of the instrument panel, the first item in the array is the horizontal offset, and the second item is the vertical offset. It can be an absolute value or a percentage relative to the dashboard radius.
          // length: '36%', // Pointer length, which can be an absolute value or a half ratio relative to the radius.
          width: 12, // pointer width
          itemStyle: {<!-- -->
            // pointer style
            // color: 'auto' // Graphic color
            // Linear gradient, the first four parameters are x0, y0, x2, y2, ranging from 0 - 1, equivalent to the percentage in the graphics bounding box. If globalCoord is `true`, the four values are absolute Pixel position
            color: '#157aff',
            borderColor: '#fff', // The stroke color of the graphic
            borderWidth: 2, // Stroke line width. When 0, there is no stroke.
            borderType: 'solid' // Stroke type, optional: 'solid' 'dashed' 'dotted'
          }
        },
        anchor: {<!-- -->
          //Fixed point of the pointer on the dial
          show: false, // Whether to display fixed points
          showAbove: false, // Whether the fixed point is displayed above the pointer
          size: 120, // Fixed point size
          // Can be set to an image via 'image://url', where URL is the link to the image, or dataURI.
          icon: 'circle', // Marker type, optional 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin' , 'arrow', 'none'
          offsetCenter: [0, '0%'], // Relative to the offset position of the center of the dashboard, the first item in the array is the horizontal offset, and the second item is the vertical offset. It can be an absolute value or a percentage relative to the dashboard radius.
          itemStyle: {<!-- -->
            // Pointer fixed point style
            color: 'pink', // The color of the graphic
            borderColor: 'red', // Fixed point border color
            borderWidth: 8, // Stroke width. When 0, there is no stroke.
            borderType: 'solid' // Stroke type, optional: 'solid' 'dashed' 'dotted'
          }
        },
        title: {<!-- -->
          // Dashboard title
          show: false, // Whether to display the title
                  },
        detail: {<!-- -->
          // Dashboard details, used to display data, that is, data display in the center of the dial
          show: false, // Whether to display details
          color: '#1677FF', // text color
          fontStyle: 'normal', // Text font style, optional 'normal' 'italic' 'oblique'
          fontWeight: 'bold', // The weight of the text font, optional 'normal' 'bold' 'bolder' 'lighter' 100 | 200 | 300 | 400...
          fontFamily: 'Microsoft YaHei', // The font family of the text can also be 'serif', 'monospace', 'Arial', 'Courier New', 'Microsoft YaHei' , ...
          fontSize: 24, //The font size of the text
          backgroundColor: '#fff', // Details background color
          // borderColor: '#fff', // Details border color
          // borderWidth: 1, // Details border width
          width: 80,
          height: 80,

          // borderType: 'solid', // 'solid' 'dashed' 'dotted'
          borderRadius: 80, // rounded corners of text block
          // padding: [3, 6], // padding of text block
          valueAnimation: true, // Whether to enable the digital animation of the label
          offsetCenter: [0, 0], // Relative to the offset position of the dashboard center, the first item in the array is the horizontal offset, and the second item is the vertical offset. It can be an absolute value or a percentage relative to the dashboard radius.
          formatter: function (value) {<!-- -->
            //Format function or string
            return value + '';
          },
          itemStyle: {<!-- -->
            color: '#FFF', // pointer color, default (auto) takes the color of the interval where the value is located
            opacity: 1, // Graphic transparency. Supports numbers from 0 to 1. When it is 0, the graph is not drawn.
            borderWidth: 0, // Stroke line width, default 0. When 0, there is no stroke.
            borderType: 'solid', // The stroke type of the column, the default is solid line, supports 'solid', 'dashed', 'dotted'.
            borderColor: '#000', // The stroke color of the graphic, the default is "#000". The supported color formats are the same as color, and callback functions are not supported.
            // shadowBlur: 10, // (Glow effect) The blur size of the graphics shadow. This property is used together with shadowColor, shadowOffsetX, shadowOffsetY to set the shadow effect of the graphic.
            shadowColor: '#fff'
          }
        },

        data: [{<!-- -->name:'1',value:80}]
      }
    ]
  };
  option & amp; & amp; gaugeChart.value.setOption(option);
}
</script>
<style scoped>
.chart_wapper {<!-- -->
  width: 200px;
  height: 200px;
}
</style>