antvis/G2

在极坐标系下,使用 custom shape,默认动画会复写 style.d 导致 custom 渲染错误 #6564

BQXBQX posted onGitHub

问题描述

当使用 custom shape path 时,默认动画会重新根据 options 创建 path.d, 复写了自定义的 path。

<img width="1278" alt="image" src="https://github.com/user-attachments/assets/b25dfe9f-0fbd-4cdb-befa-9d5f8db54291" />

import * as G2 from '@antv/g2';

export function issue6563(context) {
  const { container, canvas } = context;
  const data = [
    { type: '分类一', value: 27 },
    { type: '分类二', value: 25 },
    { type: '分类三', value: 18 },
    { type: '分类四', value: 15 },
    { type: '分类五', value: 10 },
    { type: 'Other', value: 5 },
  ];

  const max = Math.max(...data.map((obj) => obj.value ?? 0), 0);
  function ShapeSlice(style, context) {
    const { document } = context;
    return (P, value, defaults) => {
      const { color: defaultColor } = defaults;
      const [p0, p1, p2, p3] = P;
      const pm = [(p0[0] + p1[0]) / 2, p0[1]];
      const { color = defaultColor } = value;

      const percentValue = value.items[0].value;
      const percent =
        typeof percentValue === 'string'
          ? Number.parseFloat(percentValue.replace('%', '')) / max
          : Number(percentValue) / max;

      const transformPoints = scalePoints(p1, p0, p3, percent);

      const svg = pathArrayToString(createArcPath(...transformPoints));

      return document.createElement('path', {
        style: {
          fill: color,
          d: svg,
          ...style,
        },
      });
    };
  }

  G2.register('shape.interval.slice', ShapeSlice);

  const chart = new G2.Chart({
    container: container,
    autoFit: true,
    canvas,
  });

  chart
    .coordinate({ type: 'theta', outerRadius: 0.8 })
    .interval()
    .data(data)
    .transform({ type: 'stackY' })
    .encode('y', 'value')
    .encode('color', 'type')
    .legend('color', {
      position: 'bottom',
      layout: { justifyContent: 'center' },
    })
    .label({
      position: 'outside',
      text: (data) => ` ${data.value}%`,
    })
    .tooltip((data) => ({
      name: data.type,
      value: `${data.value}%`,
    }))
    .encode('shape', 'slice');

  const finished = chart.render();

  return {
    chart,
    finished,
  };
}

function scalePoints(
  center: [number, number],
  p1: [number, number],
  p2: [number, number],
  factor: number,
): [[number, number], [number, number], [number, number]] {
  const dx1 = p1[0] - center[0];
  const dy1 = p1[1] - center[1];

  const dx2 = p2[0] - center[0];
  const dy2 = p2[1] - center[1];

  const scaledP1: [number, number] = [
    center[0] + dx1 * factor,
    center[1] + dy1 * factor,
  ];
  const scaledP2: [number, number] = [
    center[0] + dx2 * factor,
    center[1] + dy2 * factor,
  ];

  return [center, scaledP1, scaledP2];
}

function pathArrayToString(pathArray) {
  return pathArray
    .map((item) => {
      if (Array.isArray(item)) {
        return item.join(' '); // 将数组元素连接成字符串
      }
      return item; // 对于 "Z" 直接返回
    })
    .join(' '); // 用空格连接整个路径
}
function createArcPath(center: number[], point1: number[], point2: number[]) {
  // 计算两个点到中心点的距离(半径)
  const radius1 = Math.sqrt(
    Math.pow(point1[0] - center[0], 2) + Math.pow(point1[1] - center[1], 2),
  );
  const radius2 = Math.sqrt(
    Math.pow(point2[0] - center[0], 2) + Math.pow(point2[1] - center[1], 2),
  );

  // 确保半径相等,以便形成一个闭合的弧
  const radius = Math.min(radius1, radius2);

  // 计算角度(单位:弧度)
  const angle1 = Math.atan2(point1[1] - center[1], point1[0] - center[0]);
  const angle2 = Math.atan2(point2[1] - center[1], point2[0] - center[0]);

  // 计算弧的路径(从angle1到angle2)
  const largeArcFlag = angle2 - angle1 > Math.PI ? 1 : 0;

  // 生成路径
  return [
    ['M', center[0], center[1]], // 移动到圆心
    ['L', point1[0], point1[1]], // 画一条直线到第一个点
    ['A', radius, radius, 0, 0, 0, point2[0], point2[1]], // 绘制弧
    'Z', // 闭合路径
  ];
}

重现链接

No response

重现步骤

首次渲染时渲染错误,autofit 后渲染正确,点击 legend 后也会出现渲染错误。

预期行为

首次渲染和 legend 点击后渲染正确。

平台

  • 操作系统: [macOS, Windows, Linux, React Native ...]
  • 网页浏览器: [Google Chrome, Safari, Firefox]

屏幕截图或视频(可选)

https://github.com/user-attachments/assets/998b62b1-797e-4dda-8429-c1f7cfda8182

补充说明(可选)

具体发现过程和问题描述可详见:https://github.com/antvis/G2/issues/6563


能帮忙修复吗?🥲

posted by hustcc 4 months ago

能帮忙修复吗?🥲

我尝试修复一下,尽量避免 break change。如果出现了 break change 我们再交流🥺?

posted by BQXBQX 4 months ago

Fund this Issue

$0.00
Funded

Pull requests