199 lines
5.6 KiB
TypeScript
199 lines
5.6 KiB
TypeScript
import { Component, ElementRef, NgZone, OnInit, ViewChild } from '@angular/core';
|
||
import { G2PieComponent, G2PieData } from '@delon/chart/pie';
|
||
import { format } from 'date-fns';
|
||
import { Chart } from '@antv/g2';
|
||
import { DataService } from '../../../services/data.service';
|
||
|
||
@Component({
|
||
selector: 'app-opeationtable-pie',
|
||
templateUrl: './pie.component.html',
|
||
styleUrls: ['./pie.component.less']
|
||
})
|
||
export class OperationtablePieComponent implements OnInit {
|
||
@ViewChild('pie', { static: false }) pie!: G2PieComponent;
|
||
chartData: any = [];
|
||
el: any;
|
||
chart: any;
|
||
enterpriseInfoIdPie = ''
|
||
interManlist: any = []
|
||
innerView: any =[];
|
||
constructor(private service: DataService, private ngZone: NgZone) {
|
||
}
|
||
|
||
ngOnInit(): void {
|
||
this.initData()
|
||
this.initManData()
|
||
}
|
||
initData(){
|
||
this.service.request(this.service.$api_operationalReportWaybillStatusDistribution, {id: this.enterpriseInfoIdPie}).subscribe(res => {
|
||
if (res) {
|
||
this.chartData = res
|
||
// this.ngZone.runOutsideAngular(() => this.init(this.el));
|
||
setTimeout(() => {
|
||
this.chart?.data(this.chartData);
|
||
this.chart?.render();
|
||
}, 1000)
|
||
}
|
||
})
|
||
}
|
||
initManData() {
|
||
this.service.getNetworkFreightForwarder().subscribe(res => {
|
||
this.interManlist = res
|
||
this.enterpriseInfoIdPie = res[0].value
|
||
})
|
||
}
|
||
render(el: ElementRef<HTMLDivElement>): void {
|
||
this.el = el.nativeElement
|
||
setTimeout(() => {
|
||
this.ngZone.runOutsideAngular(() => this.init(this.el));
|
||
}, 500)
|
||
}
|
||
private init(el: HTMLElement): void {
|
||
this.chart = new Chart({
|
||
container: el,
|
||
autoFit: true,
|
||
height: 400,
|
||
});
|
||
// 新建一个 view 用来单独渲染Annotation
|
||
// const innerView = chart.createView();
|
||
|
||
this.innerView = this.chart.createView();
|
||
this.chart.coordinate('theta', {
|
||
radius: 0.6,
|
||
innerRadius: 0.7,
|
||
});
|
||
|
||
// this.chart.data(this.chartData);
|
||
|
||
// chart.scale('percent', {
|
||
// formatter: val => {
|
||
// val = val * 100 + '%';
|
||
// return val;
|
||
// },
|
||
// });
|
||
|
||
this.chart.tooltip(false);
|
||
|
||
// 声明需要进行自定义图例字段: 'item'
|
||
this.chart.legend('item', {
|
||
position: 'right', // 配置图例显示位置
|
||
custom: true, // 关键字段,告诉 G2,要使用自定义的图例
|
||
items: this.chartData.map((obj: any, index: any) => {
|
||
return {
|
||
name: obj.item, // 对应 itemName
|
||
value: obj.percent+ '% ' + obj.count,
|
||
count: obj.count, // 对应 itemValue
|
||
marker: {
|
||
symbol: 'square', // marker 的形状
|
||
style: {
|
||
r: 5, // marker 图形半径
|
||
fill: this.chart.getTheme().colors10[index], // marker 颜色,使用默认颜色,同图形对应
|
||
},
|
||
}, // marker 配置
|
||
};
|
||
}),
|
||
itemValue: {
|
||
style: {
|
||
fill: '#999',
|
||
}, // 配置 itemValue 样式
|
||
formatter: (val: any) => `${val}` // 格式化 itemValue 内容
|
||
},
|
||
});
|
||
|
||
const interval = this.chart
|
||
.interval()
|
||
.adjust('stack')
|
||
.position('percent')
|
||
.color('item')
|
||
.style({
|
||
fillOpacity: 1,
|
||
stroke: 'white',
|
||
lineWidth: 8,
|
||
})
|
||
.state({
|
||
active: {
|
||
style: (element: any) => {
|
||
const shape = element.shape;
|
||
return {
|
||
lineWidth: 1,
|
||
stroke: 'white',
|
||
strokeOpacity: shape.attr('fillOpacity'),
|
||
};
|
||
},
|
||
},
|
||
});
|
||
|
||
// 移除图例点击过滤交互
|
||
this.chart.removeInteraction('legend-filter');
|
||
this.chart.interaction('element-active');
|
||
|
||
this.chart.render(true);
|
||
// 默认选择
|
||
interval.elements[0].setState('selected', true);
|
||
const ele = interval.elements[0].getData();
|
||
|
||
|
||
// 监听 element 上状态的变化来动态更新 Annotation 信息
|
||
this.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;
|
||
const updateAnnotation = (data: any) => {
|
||
if (data.item !== lastItem) {
|
||
this.innerView.annotation().clear(true);
|
||
this.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,
|
||
})
|
||
this.innerView.render(true);
|
||
|
||
|
||
lastItem = data.item;
|
||
}
|
||
}
|
||
|
||
// 清空 annotation
|
||
function clearAnnotation(this: any) {
|
||
this.innerView?.annotation()?.clear(true);
|
||
this.innerView.render(true);
|
||
lastItem = null;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|