餅圖(Pie Chart)做爲最多見的統計圖表之一,用於可視化數據中不一樣分類的佔比狀況。使用 G2,在不進行任何定製的狀況下,用戶能夠獲得以下餅圖:除去基本的圖形元素外,還提供了 label 文本標註以及圖例的繪製能力。同時還提供了 tooltip 提示信息、圖例篩選等交互行爲。
git
可是一般,用戶更傾向於如下餅圖的設計及交互:
github
交互層typescript
下面就讓咱們來看下,如何基於默認的餅圖代碼,一步一步快速、簡單得定製吧!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
扇形變圓環,只需一步!設計
咱們可使用 G2 的自定義圖例來實現預期的圖例樣式,在 G2 4.0 的圖例中,咱們開放了 itemName
和 itemName
屬性,用於圖例內容及樣式的配置。
code
具體的定製代碼以下: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
在 G2 V3 版本,自定義圖例的交互須要用戶操做圖形/數據進行實現,而在 G2 4.0 版本,若是無心改變圖形元素的響應樣式,咱們只須要聲明須要的交互便可:
chart.removeInteraction('legend-filter'); // 圖例過濾操做默認內置,如不須要能夠移除 chart.interaction('element-active'); // 添加 element-active 交互:鼠標 hover 激活圖形 active 狀態 複製代碼
chart .interval() .state({ active: { style: element => { const shape = element.shape; return { lineWidth: 10, stroke: shape.attr('fill'), strokeOpacity: shape.attr('fillOpacity'), }; }, // 配置 active 樣式,經過加粗邊框實現放大效果 }, }); 複製代碼
基於以上定製,咱們還能夠做進一步擴展,利用圓環空心部分的面積顯示鼠標擊中圖形元素的詳細信息,以代替 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(); } }], }); 複製代碼
G2 官網: g2.antv.vision/zh/
github:github.com/antvis/g2