要求:用户将数据作为参数传进来,通过类型决定渲染何种类型的图标。
demo:
html:
<ngo-chart [inputParams]="options"></ngo-chart>
ts:
options = { type: 'line', //图表类型 xAxis: { //X轴的数据 data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { //X轴的数据 data: [120, 220, 150, 111, -150, 55, 60], }, width: 600, //宽 height: 500, //高 dataPadding: 8 //条形图之间的距离 };
效果:
源代码:
import { Input, OnInit, ViewChild, Component, ViewEncapsulation, ElementRef, AfterViewInit, ChangeDetectorRef, } from '@angular/core'; import { NgoChartSvgParams, Scale, Axis, Chart } from './chart-svg-params'; @Component({ selector: 'ngo-chart-svg', templateUrl: './chart-svg.html', styleUrls: ['./chart-svg.scss'], encapsulation: ViewEncapsulation.Native }) export class NgoChartSvg implements OnInit, AfterViewInit { @Input() inputParams: NgoChartSvgParams; @ViewChild('svg') svg: ElementRef; @ViewChild('polyline') polyline: ElementRef; params: NgoChartSvgParams; AxisY: Axis; // Y轴 AxisX: Axis; // X轴 valueToPxRatio: number; // 值转px的比率 Y0: number; // 坐标轴 (0,0)的Y轴 Yscale: Array<Scale> = []; // Y轴刻度值 Xscale: Array<Scale> = []; // X轴刻度值 XgapWidth: number; // X轴刻度之间的间隙宽度 data: Array<Chart> = []; color: string; type: string; polyLinePoints: string; polyLineLength: number; constructor( private ele: ElementRef, private cd: ChangeDetectorRef ) { } ... ngOnInit() { this.initParams(); const svg = this.svg.nativeElement; const _width = this.params.width; const _height = this.params.height; svg.setAttribute('width', _width); svg.setAttribute('height', _height); // 绘制 y轴 this.drawAxisY(); this.drawScaleY(); // 绘制 x轴 this.drawAxisX(); this.drawScaleX(); this.drawRect(); if (this.params.type === 'line') { this.drawLine(); } } ngAfterViewInit() { if (this.polyline) { this.polyLineLength = this.polyline.nativeElement.getTotalLength(); this.cd.detectChanges(); } } }
html
<svg #svg> <!-- Y轴 --> <g> <line [attr.x1]="AxisY.x1" [attr.y1]="AxisY.y1+15" [attr.x2]="AxisY.x2" [attr.y2]="AxisY.y2" [attr.stroke]="color" [attr.fill]="color" /> <polygon [attr.points]="AxisY.arrow" /> <ng-container *ngFor="let scale of Yscale"> <line [attr.x1]="scale.x1" [attr.x2]="scale.x2" [attr.y1]="scale.y1" [attr.y2]="scale.y2" stroke="rgba(0,0,0,0.3)" /> <text [attr.x]="scale.x1-5" [attr.y]="scale.y1" [attr.fill]="color" [attr.fill]="color">{{scale.label}}</text> </ng-container> </g> <!-- X轴 --> <g> <line [attr.x1]="AxisX.x1-15" [attr.x2]="AxisX.x2" [attr.y1]="AxisX.y1" [attr.y2]="AxisX.y2" [attr.stroke]="color" [attr.fill]="color" /> <polygon [attr.points]="AxisX.arrow" /> <ng-container *ngFor="let scale of Xscale"> <line [attr.x1]="scale.x1" [attr.x2]="scale.x2" [attr.y1]="scale.y1" [attr.y2]="scale.y2" [attr.stroke]="color" [attr.fill]="color" /> <text [attr.x]="scale.x1-XgapWidth/2" [attr.y]="AxisY.y1+15" [attr.fill]="color">{{scale.label}}</text> </ng-container> </g> <!-- 矩形 --> <ng-container *ngIf="type==='bar'"> <text x="10" y="20" fill="red">bar</text> <g> <ng-container *ngFor="let item of data"> <ng-container *ngIf="item.value<=0"> <rect [attr.x]="item.x" [attr.y]="item.y" [attr.width]="item.w" [attr.height]="item.h" fill="color"> <animate attributeName="height" [attr.from]="item.h*0.6" [attr.to]="item.h" begin="0s" dur="1.1s" /> </rect> <text [attr.x]="item.x+item.w/2" [attr.y]="item.y+item.h-5" fill="white">{{item.value}}</text> </ng-container> <ng-container *ngIf="item.value>0"> <rect [attr.x]="item.x" [attr.y]="item.y" [attr.width]="item.w" [attr.height]="item.h" fill="color"> <animate attributeName="y" [attr.from]="item.y+item.h*0.4" [attr.to]="item.y" begin="0s" dur="1.1s" /> <animate attributeName="height" [attr.from]="item.h*0.6" [attr.to]="item.h" begin="0s" dur="1.1s" /> </rect> <text [attr.x]="item.x+item.w/2" [attr.y]="item.y+18" fill="white">{{item.value}} <animate attributeName="opacity" from="0" to="1" begin="0s" dur="1.1s" /> </text> </ng-container> </ng-container> </g> </ng-container> <!--折线 --> <ng-container *ngIf="type==='line'"> <text x="10" y="20" fill="red">line</text> <g> <polyline #polyline [attr.points]="polyLinePoints" fill="none" [attr.stroke]='color' [attr.stroke-dasharray]="polyLineLength" [attr.stroke-dashoffset]="polyLineLength" /> <ng-container *ngFor="let item of data"> <circle [attr.cx]="item.x+item.w/2" [attr.cy]="item.y" r="2" [attr.fill]="color" [attr.stroke]='color' /> <text [attr.x]="item.x+item.w/2" [attr.y]="item.y+20" fill="white">{{item.value}} <animate attributeName="opacity" from="0" to="1" begin="0s" dur="1.1s" /> </text> </ng-container> </g> </ng-container> </svg>
css