echart饼图中玫瑰图添加外边框,只有弧度增加边框。

效果如下:

 具体方案:

使用两个pie的series,通过z控制层级遮盖住底层的pie。

控制底层radius外环略微大于表层的pie的radius来模拟出边框。

series: [
      {
        name: "Nightingale Chart",
        type: "pie",
        z: 20,
        radius: ["0%", "70%"],
        center: ["50%", "50%"],
        roseType: "radius",
        emphasis: { disabled: true },
        showEmptyCircle: false,
        label: {
          show: true,
          position: "outside",
          color: "#fff",
          fontSize: 16,
        },
        data: [],
      },
      {
        name: "border",
        type: "pie",
        z: 19,
        radius: ["0%", "71%"],
        center: ["50%", "50%"],
        roseType: "radius",
        showEmptyCircle: false,
        emphasis: { disabled: true },
        label: {
          show: false,
        },
        labelLine: {
          show: false,
        },
        data: [],
      },
    ],

渐变色方案:借鉴了其他文章大佬的内容

let data = [
    { value: 40, name: "其他" },
    { value: 28, name: "其他突发事件" },
    { value: 32, name: "森林火险预警" },
    { value: 30, name: "自然灾害" },
    { value: 38, name: "危险源和风险隐患区" },
  ];
const colorList = [
  ["rgba(22, 127, 136, 1)", "rgba(12, 235, 253, 1)", "rgba(0, 255, 239, 1)"],
  ["rgba(148, 129, 42, 1)", "rgba(201, 221, 68, 1)", "rgba(230, 255, 0, 1)"],
  ["rgba(42, 54, 148, 1)", "rgba(68, 108, 221, 1)", "rgba(155, 177, 255, 1)"],
  ["rgba(193, 141, 31, 1)", "rgba(236, 165, 13, 1)", "rgba(255, 199, 31, 1)"],
  ["rgba(24, 55, 141, 1)", "rgba(0, 52, 199, 1)", "rgba(70, 204, 255, 1)"],
];
/**
 * 生成data方法
 * @data series下的data
 * @colorList 颜色数组
 */
const getLinerColorData = (data, colorList) => {
  const dataTotal = data.reduce((prev, curr) => prev + curr.value, 0);
  data.forEach((item, idx) => {
    item.percent = item.value / dataTotal;
    item.angle = item.percent * Math.PI * 2; // 弧度制的角度
    if (idx == 0) {
      item.startAngle = 0;
      item.endAngle = item.angle;
    } else {
      item.startAngle = data[idx - 1].startAngle + data[idx - 1].angle;
      item.endAngle = item.startAngle + item.angle;
    }
  });
  for (let i = 0; i < data.length; i++) {
    const color = colorList[i];
    const startAngle = data[i].startAngle;
    const endAngle = data[i].endAngle;
    // 这里计算了 线性渐变的起止方向
    // @ts-ignore
    const coordinates = getCoordinates(startAngle, endAngle);
    data[i].itemStyle = {
      color: {
        ...coordinates,
        type: "linear",
        global: false,
        colorStops: [
          {
            offset: 0,
            color: color[1],
          },
          {
            offset: 0.91,
            // offset: 1,
            color: color[0],
          },
        ],
      },
    };
    data[i].labelLine = {
      show: true,
      lineStyle: {
        color: color[2],
      },
    };
  }
  return data;
};
/**
 * 线性渐变起止方向的计算方法
 * @param {*} startArc 开始角度
 * @param {*} endArc 结束角度
 * @returns 四个坐标 x,y,x2,y2
 */
const getCoordinates = (startArc, endArc) => {
  // 这里计算扇形最外层的x,y坐标
  const position = [Math.sin(startArc), -Math.cos(startArc), Math.sin(endArc), -Math.cos(endArc)];
  // 这里求得了最外层两个顶点坐标的差值。
  const dx = position[2] - position[0];
  const dy = position[3] - position[1];
  // 这里在根据两点坐标的差值计算x,y,x2,y2
  return getLocation(dx, dy);
};

const getLocation = (dx, dy) => {
  const tanV = dx / dy;
  // 这里是在计算按照横向渐变还是按照纵向渐变。
  const directSign = Math.abs(tanV) < 1;
  const t = directSign ? tanV : 1 / tanV;

  const sign1 = t > 0 ? 1 : -1;
  const sign2 = dx > 0 ? 1 : -1;
  const sign = directSign ? sign1 * sign2 : sign2;

  // 把整个圆形的坐标映射到了[0-1]之间0.5,0.5即为圆心坐标。
  const group1 = [0.5 - (sign * t) / 2, 0.5 + (sign * t) / 2];
  // 这里给纵向渐变还是横向渐变赋值、即group中的第三项和第四项的值
  const group2 = sign > 0 ? [0, 1] : [1, 0];
  const group = [...group1, ...group2];
  const keys = directSign ? ["x", "x2", "y", "y2"] : ["y", "y2", "x", "x2"];

  const res = {};
  keys.forEach((k, idx) => {
    //@ts-ignore
    res[k] = group[idx];
  });
  return res;
};

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值