antvis / G2

📊 The concise and progressive visualization grammar.
https://g2.antv.antgroup.com
MIT License
12.08k stars 1.58k forks source link

饼图怎么让hover 部分放大呢?跟 echarts 一样 #5947

Closed YY88Xu closed 1 week ago

YY88Xu commented 8 months ago

问题描述

image image

重现链接

No response

重现步骤

No response

预期行为

No response

平台

屏幕截图或视频(可选)

No response

补充说明(可选)

No response

pearmini commented 8 months ago

理论上如下是可以的:

/**
 * A recreation of this demo: https://nivo.rocks/pie/
 */
import { Chart } from '@antv/g2';

const chart = new Chart({
  container: 'container',
  width: 500,
  height: 400,
});

chart.coordinate({ type: 'theta', innerRadius: 0.25, outerRadius: 0.8 });

chart
  .interval()
  .data([
    { id: 'c', value: 526 },
    { id: 'sass', value: 220 },
    { id: 'php', value: 325 },
    { id: 'elixir', value: 561 },
    { id: 'rust', value: 54 },
  ])
  .transform({ type: 'stackY' })
  .encode('y', 'value')
  .encode('color', 'id')
  .state('active', { transform: 'scale(1.5, 1.5)'})

chart.interaction("elementHighlight", true)

chart.render();

但目前存在 bug,近期可以修复一下。

YY88Xu commented 8 months ago

大佬,这个修复了吗? 可以用吗

YY88Xu commented 8 months ago

大佬,这个修复了吗? 可以用吗

@pearmini

YY88Xu commented 8 months ago

@pearmini 这个在做了没有呢 大佬

pearmini commented 8 months ago

@YY88Xu @xiaoiver 会来看一下这个问题

xiaoiver commented 8 months ago

应该是 transformOrigin 的问题

YY88Xu commented 8 months ago

应该是 transformOrigin 的问题

所以要怎么写呢?能不能给个例子呢 @xiaoiver

xiaoiver commented 8 months ago

应该是 transformOrigin 的问题

所以要怎么写呢?能不能给个例子呢 @xiaoiver

我们先尝试在 G2 内部修复

YY88Xu commented 8 months ago

应该是 transformOrigin 的问题

所以要怎么写呢?能不能给个例子呢 @xiaoiver

我们先尝试在 G2 内部修复

大概什么时候可以修复好呢?

YY88Xu commented 7 months ago

@xiaoiver 大佬好了吗

YY88Xu commented 7 months ago

@pearmini @xiaoiver 大佬好了吗

ai-qing-hai commented 7 months ago

@YY88Xu
当前的自定义方法,但对 label 还是有点问题。

import { Chart } from '@antv/g2';

const data = [
  { item: '事例一', count: 40, percent: 0.4 },
  { item: '事例二', count: 21, percent: 0.21 },
  { item: '事例三', count: 17, percent: 0.17 },
  { item: '事例四', count: 13, percent: 0.13 },
  { item: '事例五', count: 9, percent: 0.09 },
];

const chart = new Chart({
  container: 'container',
  autoFit: true,
});

chart.coordinate({ type: 'theta', outerRadius: 0.8 });

chart
  .interval()
  .data(data)
  .transform({ type: 'stackY' })
  .encode('y', 'percent')
  .encode('color', 'item')
  .legend('color', { position: 'bottom', layout: { justifyContent: 'center' } })
  .label({
    position: 'outside',
    text: (data) => `${data.item}: ${data.percent * 100}%`,
  })
  .tooltip((data) => ({
    name: data.item,
    value: `${data.percent * 100}%`,
  }));

const scale = 0.05;

chart.render().then((chart) => {
  // Get G Canvas instance
  const { canvas } = chart.getContext();

  const center = chart.getCoordinate().getCenter();
  // Find graphic elements
  const elements = canvas.document.getElementsByClassName(
    G2.ELEMENT_CLASS_NAME,
  );

  // Highlight
  for (const element of elements) {
    const path = element.attributes.path;

    let r = 0;
    let newR = 0;
    const newPath = path.replace(/[a-zA-Z](\d|\.|\,)+/g, (v) => {
      if (v[0] === 'M') {
        const [x, y] = v.replace('M', '').split(',');
        r = Math.sqrt(Math.pow(x - center[0], 2) + Math.pow(y - center[1], 2));
        newR = r * (1 + scale);
        return `M${Number(x) + (x - center[0]) * scale},${Number(y) + (y - center[1]) * scale}`
      }
      if (v[0] === "A") {
        const list = v.split(',');
        const y = list.pop();
        const x = list.pop();
        return `A${newR},${newR},0,0,1,${Number(x) + (x - center[0]) * scale},${Number(y) + (y - center[1]) * scale}`;
      }
      return v;
    });

    element.addEventListener('mouseenter', () => {
      element.attr('path', newPath)
      element.attr('zIndex', 2244)
    });

    element.addEventListener('mouseleave', () => {
      element.attr('path', path)
    });
  }
});
ai-qing-hai commented 7 months ago

@YY88Xu 最新的 看看符不符合你的要求

import { Chart } from '@antv/g2';

const data = [
  { item: '事例一', count: 40, percent: 0.4 },
  { item: '事例二', count: 21, percent: 0.21 },
  { item: '事例三', count: 17, percent: 0.17 },
  { item: '事例四', count: 13, percent: 0.13 },
  { item: '事例五', count: 9, percent: 0.09 },
];

const chart = new Chart({
  container: 'container',
  autoFit: true,
});

chart.coordinate({ type: 'theta', outerRadius: 0.8 });

chart
  .interval()
  .data(data)
  .transform({ type: 'stackY' })
  .encode('y', 'percent')
  .encode('color', 'item')
  .legend('color', { position: 'bottom', layout: { justifyContent: 'center' } })
  .label({
    position: 'outside',
    text: (data) => `${data.item}: ${data.percent * 100}%`,
  })
  .tooltip((data) => ({
    name: data.item,
    value: `${data.percent * 100}%`,
  }));

const scale = 0.05;

chart.render().then((chart) => {
  // Get G Canvas instance
  const { canvas } = chart.getContext();

  const center = chart.getCoordinate().getCenter();
  // Find graphic elements
  const elements = canvas.document.getElementsByClassName(
    G2.ELEMENT_CLASS_NAME,
  );

  // Highlight
  for (const element of elements) {
    const path = element.attributes.path;

    let r = 0;
    let newR = 0;
    const newPath = path.replace(/[a-zA-Z](\d|\.|\,)+/g, (v) => {
      if (v[0] === 'M') {
        const [x, y] = v.replace('M', '').split(',');
        r = Math.sqrt(Math.pow(x - center[0], 2) + Math.pow(y - center[1], 2));
        newR = r * (1 + scale);
        return `M${Number(x) + (x - center[0]) * scale},${Number(y) + (y - center[1]) * scale}`
      }
      if (v[0] === "A") {
        const list = v.split(',');
        const y = list.pop();
        const x = list.pop();
        return `A${newR},${newR},0,0,1,${Number(x) + (x - center[0]) * scale},${Number(y) + (y - center[1]) * scale}`;
      }
      return v;
    });

    element.parentNode.attr('zIndex', 2)
    element.addEventListener('mouseenter', () => {
      element.attr('path', newPath)
    });

    element.addEventListener('mouseleave', () => {
      element.attr('path', path)
    });
  }
});
YY88Xu commented 7 months ago

@ai-qing-hai 是放大了,但是有点卡顿,不知道你能不能感觉到?不知道为啥感觉不够丝滑

YY88Xu commented 7 months ago

@ai-qing-hai 还有一个明显的 bug,就是浏览器窗口变小或变大,在 hover 的时候,会错位

image
ai-qing-hai commented 6 months ago

@YY88Xu import { Chart } from '@antv/g2';

const data = [ { item: '事例一', count: 40, percent: 0.4 }, { item: '事例二', count: 21, percent: 0.21 }, { item: '事例三', count: 17, percent: 0.17 }, { item: '事例四', count: 13, percent: 0.13 }, { item: '事例五', count: 9, percent: 0.09 }, ];

const chart = new Chart({ container: 'container', autoFit: true, });

chart.coordinate({ type: 'theta', outerRadius: 0.8 });

chart .interval() .data(data) .transform({ type: 'stackY' }) .encode('y', 'percent') .encode('color', 'item') .legend('color', { position: 'bottom', layout: { justifyContent: 'center' } }) .label({ position: 'outside', text: (data) => ${data.item}: ${data.percent * 100}%, }) .tooltip((data) => ({ name: data.item, value: ${data.percent * 100}%, }));

const scale = 0.05; let elements; const create = (init) => { // Get G Canvas instance const { canvas } = chart.getContext();

const center = chart.getCoordinate().getCenter();

if (elements) { for (const element of elements) {

  element.removeEventListener('mouseenter', element.mouseenter);
  element.removeEventListener('mouseleave', element.mouseleave);
}

}

// Find graphic elements elements = canvas.document.getElementsByClassName( G2.ELEMENT_CLASS_NAME, );

const initY = elements[0].attributes.path.replace(/A.+/, '').split(',')[1]; const r = init ? -initY : center[1] - initY; // Highlight for (const element of elements) { let { path } = element.attributes; console.log(r) const newR = r * (1 + scale);

if (init) {
  path = path.replace(/[a-zA-Z](\d|\.|\,|\-)+/g, (v) => {
    if (v[0] === 'M') {
      const [x, y] = v.replace('M', '').split(',');
      return `M${Number(x) + center[0]},${Number(y) + center[1]}`;
    }

    if (v[0] === "A") {
      const list = v.split(',');
      const y = list.pop();
      const x = list.pop();

      return list.join(',') + `,${Number(x) + center[0]},${Number(y) + center[1]}`;
    }

    if (v[0] === "L") {
      return `L${center[0]},${center[1]}`
    }
    return v;
  });
}

const newPath = path.replace(/[a-zA-Z](\d|\.|\,|\-)+/g, (v) => {
  if (v[0] === 'M') {
    const [x, y] = v.replace('M', '').split(',');
    return `M${Number(x) + (x - center[0]) * scale},${Number(y) + (y - center[1]) * scale}`
  }

  if (v[0] === "A") {
    const list = v.split(',');
    const y = list.pop();
    const x = list.pop();
    return `A${newR},${newR},0,0,1,${Number(x) + (x - center[0]) * scale},${Number(y) + (y - center[1]) * scale}`;
  }
  return v;
});

element.parentNode.attr('zIndex', 2);
element.mouseenter = () => {
  element.attr('path', newPath);
}
element.mouseleave = () => {
  element.attr('path', path)
}
element.addEventListener('mouseenter', element.mouseenter);

element.addEventListener('mouseleave', element.mouseleave);

} }

chart.render().then(() => { create(); });

chart.on('afterchangesize', () => { create(true); })