import { Component, ElementRef, NgZone, OnInit, ViewChild } from '@angular/core'; import { ModalHelper, _HttpClient } from '@delon/theme'; import { G2MiniAreaClickItem, G2MiniAreaData } from '@delon/chart/mini-area'; import { G2PieClickItem, G2PieComponent, G2PieData } from '@delon/chart/pie'; import { format } from 'date-fns'; import { Chart, registerShape, Util } from '@antv/g2'; import { G2TimelineClickItem, G2TimelineData } from '@delon/chart/timeline'; import { DataService } from '../../../services/data.service'; @Component({ selector: 'app-datatable-curve', templateUrl: './curve.component.html', styleUrls: ['./curve.component.less'] }) export class DatatableDataindexComponent implements OnInit { @ViewChild('pie', { static: false }) pie!: G2PieComponent; chartData: G2TimelineData[] = []; visitData = this.genData(); salesData = this.genData(); salesPieData: G2PieData[] = []; total = ''; constructor(private service: DataService, private ngZone: NgZone) { } ngOnInit(): void { this.refreshPie(); this.initLineData() } initLineData(){ for (let i = 0; i < 20; i += 1) { this.chartData.push({ time: new Date().getTime() + 1000 * 60 * 60 * 24 * i, y1: Math.floor(Math.random() * 100) + 1000, y2: Math.floor(Math.random() * 100) + 10, }); } } private genData(): G2MiniAreaData[] { const beginDay = new Date().getTime(); const res: G2MiniAreaData[] = []; for (let i = 0; i < 20; i += 1) { res.push({ x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'yyyy-MM-dd'), y: Math.floor(Math.random() * 100) + 10, }); } return res; } refresh(): void { this.visitData = this.genData(); } refreshPie(): void { const rv = (min: number = 0, max: number = 5000) => Math.floor(Math.random() * (max - min + 1) + min); this.salesPieData = [ { x: '家用电器', y: rv(), }, { x: '食用酒水', y: rv(), }, { x: '个护健康', y: rv(), }, { x: '服饰箱包', y: rv(), }, { x: '母婴产品', y: rv(), }, ]; if (Math.random() > 0.5) { this.salesPieData.push({ x: '其他', y: rv(), }); } this.total = `¥ ${this.salesPieData.reduce((pre, now) => now.y + pre, 0).toFixed(2)}`; if (this.pie) { // 等待组件渲染 setTimeout(() => { console.log('a') this.pie.changeData() }); } } handleClick(data: G2MiniAreaClickItem): void { this.service.msgSrv.info(`${data.item.x} - ${data.item.y}`); } format(val: number): string { return `¥ ${val.toFixed(2)}`; } render(el: ElementRef): void { this.ngZone.runOutsideAngular(() => this.init(el.nativeElement)); } private init(el: HTMLElement): void { 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: el, autoFit: true, height: 400, }); // 新建一个 view 用来单独渲染Annotation const innerView = chart.createView(); chart.coordinate('theta', { radius: 0.6, innerRadius: 0.7, }); chart.data(data); chart.scale('percent', { formatter: val => { val = val * 100 + '%'; return val; }, }); chart.tooltip(false); // 声明需要进行自定义图例字段: '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: any) => `${val * 100}%` // 格式化 itemValue 内容 }, }); chart .interval() .adjust('stack') .position('percent') .color('item') .style({ fillOpacity: 1, stroke: 'white', lineWidth: 8, }) .state({ active: { style: element => { const shape = element.shape; return { lineWidth: 1, stroke: 'white', strokeOpacity: shape.attr('fillOpacity'), }; }, }, }); // 移除图例点击过滤交互 chart.removeInteraction('legend-filter'); chart.interaction('element-active'); chart.render(); // 监听 element 上状态的变化来动态更新 Annotation 信息 chart.on('element:statechange', (ev: any) => { const { state, stateStatus, element } = ev.gEvent.originalEvent; // 本示例只需要监听 active 的状态变化 if (state === 'active') { const data = element.getData(); if (stateStatus) { // 更新 Annotation updateAnnotation(data); } else { // 隐藏 Annotation clearAnnotation(); } } }); // 绘制 annotation let lastItem: any; function updateAnnotation(data: any) { if (data.item !== lastItem) { innerView.annotation().clear(true); innerView .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, }) innerView.render(true); lastItem = data.item; } } // 清空 annotation function clearAnnotation() { innerView.annotation().clear(true); innerView.render(true); lastItem = null; } } }