Files
bbq/src/app/routes/datatable/components/operationtable/curve/curve.component.ts
2022-03-29 11:26:55 +08:00

250 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 = `&yen ${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 `&yen ${val.toFixed(2)}`;
}
render(el: ElementRef<HTMLDivElement>): 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;
}
}
}