自学内容网 自学内容网

echarts自定义tooltip、legend等

一. tooltip自定义

1. 因为指标数过多,一行展示一个指标会造成高度很高,呈现效果不佳,优化成一行展现两个指标,从而减少高度

关键代码如下:

formatter: function (params) {
      // 初始化一个空字符串来存储 tooltip 的内容
      var tooltipContent = '';
      // 对数据进行排序
      const data = params.sort((a, b) => (b.value ?? 0) - (a.value ?? 0));

      // 创建一个数组来存储每行的内容
      var rowContents = [];

      // 遍历 params 数组
      data.forEach(function (item, index) {
        // 拼接 series 名称、类目值和数值
        const { marker, seriesName, value } = item;
        const formatValue = value || value === 0 ? `${value}%` : '';

        // 构建每个数据点的 HTML 内容
        const cellContent = `
          <div style="display:inline-block;width:50%;">
            <div style="display:flex;justify-content:space-between;line-height:24px;">
              <div>
                ${marker}
                <span>${seriesName}</span>
              </div>
              <div>${formatValue}</div>
            </div>
          </div>
        `;

        // 如果是偶数索引或者第一个元素,则开始新的一行
        if (index % 2 === 0) {
          rowContents.push(cellContent);
        } else {
          // 否则,将当前单元格附加到前一个单元格后面
          rowContents[rowContents.length - 1] += cellContent;
        }
      });

      // 将所有行的内容连接起来
      rowContents.forEach((row) => {
        tooltipContent += `<div style="width:200px;">${row}</div>`;
      });

      return `${params[0].name}<br/>${tooltipContent}`;
    },

核心知识点:

  1. marker属性为文字左边的图标,展示的是html字符串格式;
  2. index % 2 === 0是为了使一行同时具备两个指标的数据
    为便于理解,可参考这个代码
const initData = [
  { id: 1, value: 11 },
  { id: 2, value: 12 },
  { id: 3, value: 13 },
  { id: 4, value: 14 },
  { id: 5, value: 15 },
];
// rowContent

// 期望得到
const getData = () => {
  const resultData = [];
  initData.forEach((item, index) => {
    if (index % 2 === 0) {
      resultData.push(item.id + '');
    } else {
      resultData[resultData.length - 1] = resultData[resultData.length - 1] + item.id + '';
    }
  });
  return resultData;
};

const res = getData();
console.log(res, 'res99');

2. 如何仅仅是想更改数据的展示格式,应该怎么处理?
比如在数据的基础上加%

可以使用valueFormatter(tooltip.valueFormatter)

const formatVal = (val) => {
  return val || val === 0 ? `${val}%` : '-';
};
valueFormatter: (val) => formatVal(val),

3. 如何对展示数据进行排序?

可以用order属性(tooltip.order)

order: 'valueDesc',

注意:上述例子为折线图场景,其它图形场景可能略有差异。

二. legend自定义

1. 假如legend排列想要自定义成
名称 百分比 数据 的格式,应该怎么处理?

关键代码如下:

 // legend初始化赋值
  legend: {
    orient: 'horizontal',
    bottom: '10%',
    left: 'left',
    icon: 'circle',
    itemWidth: 10,
    itemHeight: 10,
    textStyle: {
      rich: {
        name: {
          fontSize: '10px',
          width: 45,
        },
        percentage: {
          color: '#303133',
          fontWeight: 700,
          width: 45,
        },
        value: {
          color: '#303133',
          fontWeight: 700,
        },
      },
    },
  },
// 设置legend formatter属性,进行自定义
echartLayoutVal.value.byFeePercent.option.legend.formatter = (params) => {
      const findItem = pieData.find((item) => item.name === params);
      const { value, percentage } = findItem;
      return `{name|${params}}{percentage|${percentage}%}{value|${value} 万元}`;
    };

核心知识点:

  1. rich属性的使用

注意:上述例子为饼图场景,其它图形场景可能略有差异。

三. 如何保证饼图百分比总和为100

测试代码

const initData = [
  {
    id: null,
    wufyhs: 20747.5,
    datestr: null,
    tm: '汽运',
  },
  {
    id: null,
    wufyhs: 137.38,
    datestr: null,
    tm: '空运',
  },
  {
    id: null,
    wufyhs: 1705.48,
    datestr: null,
    tm: '船运',
  },
  {
    id: null,
    wufyhs: 3991.72,
    datestr: null,
    tm: '铁路',
  },
];

const getPiePercentData = (initData, key) => {
  // 计算总和
  const total = initData.reduce((sum, item) => {
    return sum + item.wufyhs;
  }, 0);
  let sumPercentage = 0;
  const mapData = initData.map((item, index) => {
    const { wufyhs } = item;
    let percentage = (wufyhs / total) * 100;
    if (index !== initData.length - 1) {
      percentage = Math.round(percentage); // 四舍五入到两位小数
      sumPercentage += percentage;
    }
    return {
      value: wufyhs,
      name: item[key],
      percentage,
    };
  });
  // 设置最后一项的百分比
  mapData[initData.length - 1].percentage = 100 - sumPercentage;
  const sortData = mapData.sort((a, b) => b.percentage - a.percentage);
  return sortData;
};
const getData = getPiePercentData(initData, 'tm');
console.log(getData, 'getData');

主要思路:将除最后一项前的百分比总和计算出来,最后一项百分比值赋值为100减去除最后一项前的百分比总和

此种方法可能还不是最优,有更好的思路欢迎大家指教!

四. Promise.all和Promise.allSettled

业务场景:希望一次调用多个promise接口,但是promise接口之间希望不相互影响

测试代码

const promise1 = Promise.resolve(42);
const promise2 = Promise.reject('show error');
const promise3 = Promise.resolve('Hello World');

Promise.all([promise1.catch(() => null), promise2.catch(() => null), promise3.catch(() => null)])
  .then((values) => {
    console.log(values); // 不会执行,因为 promise2 被拒绝了
  })
  .catch((error) => {
    console.log(error); // 输出 'error'
  });

Promise.allSettled([promise1, promise2, promise3])
  .then((values) => {
    console.log(values, 'values'); // 不会执行,因为 promise2 被拒绝了
  })
  .catch((error) => {
    console.log(error, 'error'); // 输出 'error'
  });


以上两种方法都可以达到效果

核心知识点:

  1. 使用 Promise.all 结合 catch:
    如果任何一个 Promise 对象被拒绝(rejected),Promise.all 将立即返回一个拒绝的 Promise,并且拒绝理由(reason)是第一个被拒绝的 Promise 的拒绝理由。

使用 Promise.all 结合 catch,这种方法通过在每个 promise 后添加 .catch(() => null) 来确保即使某个 promise 被拒绝,Promise.all 也不会被拒绝,而是会将该 promise 的结果视为 null(或其他你指定的默认值
2. Promise.allSettled
可以同时处理所有 promise 的结果,无论它们是成功还是失败。
不需要额外的错误处理,因为即使某个 promise 被拒绝,Promise.allSettled 仍然会解析而不会进入 catch 块


原文地址:https://blog.csdn.net/m0_45093055/article/details/143920230

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!