如何使用 G2 4.0 快速個性化餅圖?

餅圖(Pie Chart)做爲最多見的統計圖表之一,用於可視化數據中不一樣分類的佔比狀況。使用 G2,在不進行任何定製的狀況下,用戶能夠獲得以下餅圖:除去基本的圖形元素外,還提供了 label 文本標註以及圖例的繪製能力。同時還提供了 tooltip 提示信息、圖例篩選等交互行爲。
git

image.png
2020-03-16 13-29-43.2020-03-16 13_31_59.gif

可是一般,用戶更傾向於如下餅圖的設計及交互:
github

image.png
2020-03-16 13-41-04.2020-03-16 13_41_28.gif

在定製以前,咱們能夠看看這兩種餅圖可視化方式的區別在哪裏:
繪製層

  1. 使用空心環代替實心扇形;
  2. 圖例的個性化定製,將本來 label 的內容同圖例內容合併。

交互層typescript

  1. 圖形元素響應鼠標的狀態發生改變:從默認的描邊變爲圖形的放大突出;
  2. 圖例的點擊篩選變爲點擊突出圖形元素

下面就讓咱們來看下,如何基於默認的餅圖代碼,一步一步快速、簡單得定製吧!markdown

默認餅圖代碼:oop

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,
  height: 500,
});

chart.coordinate('theta', {
  radius: 0.75,
});

chart.data(data);

chart.scale('percent', {
  formatter: (val) => {
    val = val * 100 + '%';
    return val;
  },
});

chart.tooltip({
  showTitle: false,
  showMarkers: false,
});

chart
  .interval()
  .position('percent')
  .color('item')
  .label('percent', {
    content: (data) => {
      return `${data.item}: ${data.percent * 100}%`;
    },
  })
  .adjust('stack');

chart.interaction('element-active');

chart.render();
複製代碼

線上示例連接:g2.antv.vision/zh/examples…spa

定製座標系

扇形變圓環,只需一步!設計

image.png

定製圖例

咱們可使用 G2 的自定義圖例來實現預期的圖例樣式,在 G2 4.0 的圖例中,咱們開放了 itemName 和 itemName 屬性,用於圖例內容及樣式的配置。
code

image.png

圖例屬性對應關係

具體的定製代碼以下:orm

// 聲明須要進行自定義圖例字段: 'item'
chart.legend('item', {
  position: 'right',                                  // 配置圖例顯示位置
  custom: true,                                       // 關鍵字段,告訴 G2,要使用自定義的圖例 
  items: data.map((obj, index) => {
    return {
      name: obj.item,                                 // 對應 itemName
      value: obj.percent,                             // 對應 itemValue
      marker: {
        symbol: 'square',                             // marker 的形狀
        style: {      
          r: 5,                                       // marker 圖形半徑
          fill: chart.getTheme().colors10[index],     // marker 顏色,使用默認顏色,同圖形對應
        },
      },                                              // marker 配置
    };
  }),
  itemValue: {
    style: {
      fill: '#999',
    },                                               // 配置 itemValue 樣式
    formatter: val => `${val * 100}%`                // 格式化 itemValue 內容
  },
});
複製代碼

同時咱們將 label() 方法移除,就獲得了下圖:
ip

image.png

定製交互

在 G2 V3 版本,自定義圖例的交互須要用戶操做圖形/數據進行實現,而在 G2 4.0 版本,若是無心改變圖形元素的響應樣式,咱們只須要聲明須要的交互便可:

chart.removeInteraction('legend-filter');  // 圖例過濾操做默認內置,如不須要能夠移除
chart.interaction('element-active');       // 添加 element-active 交互:鼠標 hover 激活圖形 active 狀態
複製代碼

2020-03-16 15-10-03.2020-03-16 15_10_56.gif

可是咱們須要的是圖形元素方法效果,因此咱們須要配置下圖形元素 active 狀態的樣式:

chart
  .interval()
  .state({
    active: {
      style: element => {
        const shape = element.shape;
        return {
          lineWidth: 10,
          stroke: shape.attr('fill'),
          strokeOpacity: shape.attr('fillOpacity'),
        };
      }, // 配置 active 樣式,經過加粗邊框實現放大效果
    },
  });
複製代碼

2020-03-16 13-41-04.2020-03-16 13_41_28.gif

至此,三個步驟,個性化餅圖的定製就結束了!

擴展

基於以上定製,咱們還能夠做進一步擴展,利用圓環空心部分的面積顯示鼠標擊中圖形元素的詳細信息,以代替 tooltip。固然這也並不麻煩,咱們只須要:

關閉 Tooltip

chart.tooltip(false);
複製代碼

在現有交互行爲的基礎上,添加 **callback**,更新 annotation 內容

// 繪製 annotation
let lastItem;
function updateAnnotation(data) {
  if (data.item !== lastItem) {
    chart.annotation().clear(true);
    chart
      .annotation()
      .text({
        position: ['50%', '50%'],
        content: data.item,
        style: {
          fontSize: 20,
          fill: '#8c8c8c',
          textAlign: 'center',
        },
        offsetY: -20,
      })
      .text({
        position: ['50%', '50%'],
        content: data.count,
        style: {
          fontSize: 28,
          fill: '#8c8c8c',
          textAlign: 'center',
        },
        offsetX: -10,
        offsetY: 20,
      })
      .text({
        position: ['50%', '50%'],
        content: '臺',
        style: {
          fontSize: 20,
          fill: '#8c8c8c',
          textAlign: 'center',
        },
        offsetY: 20,
        offsetX: 20,
      });
    chart.render(true);
    lastItem = data.item;
  }
}

// 清空 annotation
function clearAnnotation() {
  chart.annotation().clear(true);
  chart.render(true);
  lastItem = null;
}

// 在現有 'element-active' 交互行爲的基礎上加上 callback 配置,用於動態更新 Annotation
// 'element-active' 定義:https://github.com/antvis/G2/blob/fdf485ce218f905b5416cb91e0e421b85a1b6925/src/index.ts#L264
chart.interaction('element-active', {
  start: [{
    trigger: 'element:mouseenter',
    action: 'element-active:active',
    callback(context) {
      if (context.event.data) {
        updateAnnotation(context.event.data.data);
      }
    },
  }],
  end: [{
    trigger: 'element:mouseleave',
    action: 'element-active:reset',
    callback() {
      clearAnnotation();
    }
  }],
});

// 在現有 'legend-active' 交互行爲的基礎上加上 callback 配置,用於動態更新 Annotation
// 'legend-active' 定義:https://github.com/antvis/G2/blob/fdf485ce218f905b5416cb91e0e421b85a1b6925/src/index.ts#L293
chart.interaction('legend-active', {
  showEnable: [
    { trigger: 'legend-item:mouseenter', action: 'cursor:pointer' },
    { trigger: 'legend-item:mouseleave', action: 'cursor:default' },
  ],
  start: [{
    trigger: 'legend-item:mouseenter',
    action: ['list-active:active', 'element-active:active'],
    callback(context) {
      const delegateObject = context.event.gEvent.shape.get('delegateObject');
      const targetData = data.filter(obj => obj.item === delegateObject.item.name);
      if (targetData.length) {
        updateAnnotation(targetData[0]);
      }
    }
  }],
  end: [{
    trigger: 'legend-item:mouseleave',
    action: ['list-active:reset', 'element-active:reset'],
    callback(context) {
      clearAnnotation();
    }
  }],
});
複製代碼

2020-03-17 14-15-21.2020-03-17 14_15_51.gif


完整代碼傳送門:  連接

網址

G2 官網: g2.antv.vision/zh/
github:github.com/antvis/g2

相關文章
相關標籤/搜索