饼图数据过多时,图例分成左右两列对称展示,可滚动翻页

使用echarts实现饼图

  • 1.饼图数据过多时,图例分成左右两列对称展示,垂直居中,可滚动翻页;
  • 2.图例文字大于8个字显示省略号;
  • 3.给定颜色数组,手动按索引循环取色渲染饼图;
  • 4.自定义提示框;鼠标悬浮时显示;

效果图:

完整代码:

css 复制代码
let colors = [  '#D25486',  '#DE7070',  '#EEBE3F',  '#23B5FF',  '#0043CB',  '#00CFB5',  '#0EEDFE',  '#0E96FE',  '#345EBF',  '#038CB6',  '#00FFBD',  '#FFC000',  '#A823FF',  '#0868FB',  '#FFD700',  '#EE82EE',  '#FF6347',  '#008000',  '#BA55D3',  '#FFFF00',  '#9370DB',  '#3CB371',  '#FF4500',  '#FFA500',  '#6B8E23'];

let data = [  { name: '百年孤独', value: '76' },  { name: '时间简史', value: '34' },  { name: '国富论', value: '89' },  { name: '人类简史', value: '12' },  { name: '追风筝的人', value: '53' },  { name: '1984', value: '98' },  { name: '傲慢与偏见', value: '21' },  { name: '物种起源', value: '67' },  { name: '悲惨世界', value: '45' },  { name: '资本论', value: '3' },  { name: '小王子', value: '82' },  { name: '麦田里的守望者', value: '60' },  { name: '局外人', value: '77' },  { name: '存在与时间', value: '29' },  { name: '不能承受的生命之轻', value: '91' },  { name: '战争与和平', value: '14' },  { name: '安娜·卡列尼娜', value: '55' },  { name: '罪与罚', value: '38' },  { name: '尤利西斯', value: '72' },  { name: '洛丽塔', value: '9' },  { name: '了不起的盖茨比', value: '64' },  { name: '飘', value: '17' },  { name: '简爱', value: '86' },  { name: '老人与海', value: '41' },  { name: '哈姆雷特', value: '95' },  { name: '双城记', value: '7' },  { name: '鲁滨逊漂流记', value: '50' },  { name: '三体', value: '23' },  { name: '白夜行', value: '68' },  { name: '活着', value: '83' }];
const richStyle = {
  b: {
    width: 120
  }
};
let total = 0;
let leftLenged = [];
let rightLenged = [];
for (let i = 0; i < data.length; i++) {
  total = total + Number(data[i].value);
  if (i < data.length / 2) {
    leftLenged.push(data[i].name);
  } else {
    rightLenged.push(data[i].name);
  }
}
option = {
  // color:color不会循环取色,暂时注释,采用下文手动取色。
  // 原因:ECharts默认行为对饼图的颜色分配存在限制。
  //      当数据项较多时,默认会优先使用内置的全局调色盘而非自定义的 color 数组。
  // color:color,
  // 设置中间背景图,此处没有链接到图片暂时注释
  // graphic: {
  //   elements: [
  //     {
  //       type: 'image',
  //       z: -10,
  //       left: 'center',
  //       top: 'center',
  //       style: {
  //         image: require('../img/sample/bg.png'),
  //         width: 100,
  //         height: 100
  //       }
  //     }
  //   ]
  // },
  tooltip: {
    trigger: 'item',
    formatter: '{b} <br/> {c} 个({d}%)',
    backgroundColor: '#002260',
    borderColor: '#0984F3',
    borderWidth: 1,
    padding: [5, 15],
    textStyle: {
      color: '#fff'
    }
  },
  legend: [
    {
      x: 'left',
      type: 'scroll',
      orient: 'vertical',
      height: '50%',
      top: 'center',
      left: '10%',
      itemWidth: 10,
      itemHeight: 10,
      icon: 'rect',
      pageIconColor: '#2F6EE4',
      pageIconSize: 12,
      pageTextStyle: {
        color: '#fff'
      },
      textStyle: {
        fontSize: 14,
        color: '#fff',
        rich: richStyle,
        lineHeight: 16
      },
      data: leftLenged,
      tooltip: {
        show: true
      },
      formatter: function (name) {
        const oa = option.series[0].data;
        for (let i = 0; i < oa.length; i++) {
          if (name == oa[i].name) {
            return (
              '{b' +
              '|' +
              (name.length > 8 ? name.substr(0, 8) + '...' : name) +
              '}' +
              '{style' +
              i +
              '|' +
              oa[i].value +
              '本}'
            );
          }
        }
      }
    },
    {
      x: 'right',
      type: 'scroll',
      orient: 'vertical',
      height: '50%',
      top: 'center',
      left: '68%',
      itemWidth: 10,
      itemHeight: 10,
      icon: 'rect',
      pageIconColor: '#2F6EE4',
      pageIconSize: 12,
      pageTextStyle: {
        color: '#fff'
      },
      textStyle: {
        fontSize: 14,
        color: '#fff',
        rich: richStyle,
        lineHeight: 16
      },
      data: rightLenged,
      tooltip: {
        show: true
      },
      formatter: function (name) {
        const oa = option.series[0].data;
        for (let i = 0; i < oa.length; i++) {
          if (name == oa[i].name) {
            return (
              '{b' +
              '|' +
              (name.length > 8 ? name.substr(0, 8) + '...' : name) +
              '}' +
              '{style' +
              i +
              '|' +
              oa[i].value +
              '本}'
            );
          }
        }
      }
    }
  ],
  series: [
    {
      type: 'pie',
      radius: ['32%', '45%'],
      center: ['50%', '50%'],
      itemStyle: {
        // 手动按索引循环颜色
        color: (params) => {
          return colors[params.dataIndex % colors.length];
        },
        borderColor: 'rgb(16, 12, 42)',
        borderWidth: 1
      },
      labelLine: {
        show: false
      },
      label: {
        show: true,
        position: 'center',
        formatter: () => {
          return `\n{${'bM'}|总数量 ` + total + `}`;
        },
        rich: {
          bM: {
            fontSize: 18,
            color: ' #fff'
          }
        }
      },
      data: data
    }
  ]
};
相关推荐
前端若水2 分钟前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
Bigger12 分钟前
mini-cc:一个轻量级 AI 编程助手的诞生
前端·ai编程·claude
涵涵(互关)25 分钟前
Naive-ui树型选择器只显示根节点
前端·ui·vue
BY组态34 分钟前
Ricon组态系统最佳实践:从零开始构建物联网监控平台
前端·物联网·iot·web组态·组态
BY组态39 分钟前
Ricon组态系统vs传统组态软件:为什么选择新一代Web组态平台
前端·物联网·iot·web组态·组态
SoaringHeart41 分钟前
Flutter进阶:OverlayEntry 插入图层管理器 NOverlayZIndexManager
前端·flutter
放下华子我只抽RuiKe51 小时前
React 从入门到生产(四):自定义 Hook
前端·javascript·人工智能·深度学习·react.js·自然语言处理·前端框架
IT_陈寒2 小时前
Redis缓存击穿把我整不会了,原来还有这手操作
前端·人工智能·后端
idcu3 小时前
深入 Lyt.js 组件系统:L2 渲染引擎层的核心
前端·typescript
这是程序猿3 小时前
Spring Boot自动配置详解
java·大数据·前端