如何在Angular2中使用SVG自定义图表

如何在Angular2中使用SVG自定义图表?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

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//条形图之间的距离
};

效果:

如何在Angular2中使用SVG自定义图表

源代码:

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
})
exportclassNgoChartSvgimplementsOnInit,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(
privateele:ElementRef,
privatecd:ChangeDetectorRef
){}
...
ngOnInit(){
this.initParams();
constsvg=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="letscaleofYscale">
<lineclass="dash"[attr.x1]="scale.x1"[attr.x2]="scale.x2"[attr.y1]="scale.y1"[attr.y2]="scale.y2"stroke="rgba(0,0,0,0.3)"
/>
<textclass="_label"[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="letscaleofXscale">
<line[attr.x1]="scale.x1"[attr.x2]="scale.x2"[attr.y1]="scale.y1"[attr.y2]="scale.y2"[attr.stroke]="color"[attr.fill]="color"
/>
<textclass="_label"[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'">
<textx="10"y="20"fill="red">bar</text>
<g>
<ng-container*ngFor="letitemofdata">
<ng-container*ngIf="item.value<=0">
<rectclass="_rect"[attr.x]="item.x"[attr.y]="item.y"[attr.width]="item.w"[attr.height]="item.h"fill="color">
<animateattributeName="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">
<animateattributeName="y"[attr.from]="item.y+item.h*0.4"[attr.to]="item.y"begin="0s"dur="1.1s"/>
<animateattributeName="height"[attr.from]="item.h*0.6"[attr.to]="item.h"begin="0s"dur="1.1s"/>
</rect>
<textclass="_label"[attr.x]="item.x+item.w/2"[attr.y]="item.y+18"fill="white">{{item.value}}
<animateattributeName="opacity"from="0"to="1"begin="0s"dur="1.1s"/>
</text>
</ng-container>
</ng-container>
</g>
</ng-container>
<!--折线-->
<ng-container*ngIf="type==='line'">
<textx="10"y="20"fill="red">line</text>
<g>
<polyline#polylineclass="_polyline"[attr.points]="polyLinePoints"fill="none"[attr.stroke]='color'[attr.stroke-dasharray]="polyLineLength"
[attr.stroke-dashoffset]="polyLineLength"/>
<ng-container*ngFor="letitemofdata">
<circle[attr.cx]="item.x+item.w/2"[attr.cy]="item.y"r="2"[attr.fill]="color"[attr.stroke]='color'/>
<textclass="_label"[attr.x]="item.x+item.w/2"[attr.y]="item.y+20"fill="white">{{item.value}}
<animateattributeName="opacity"from="0"to="1"begin="0s"dur="1.1s"/>
</text>
</ng-container>
</g>
</ng-container>
</svg>

css

svg{
background:rgba(0,0,0,0.2);
border:1pxsolidblack;
}
svg*{
position:static;
font-size:16px;
}
._polyline{
fill:none;
animation:lineMove1.5sease-in-outforwards;
}
@keyframeslineMove{
to{
stroke-dashoffset:0;
}
}

一、初始化参数

//首先获取传入的参数
@Input()inputParams;
//初始化
const_params:NgoChartSvgParams={
xAxis:this.inputParams.xAxis,
yAxis:this.inputParams.yAxis,
type:this.inputParams.type?this.inputParams.type:'bar',
width:this.inputParams.width?this.inputParams.width:700,
height:this.inputParams.height?this.inputParams.height:500,
dataPadding:this.inputParams.dataPadding!==undefined?this.inputParams.dataPadding:8,
YscaleNo:this.inputParams.YscaleNo>=3?this.inputParams.YscaleNo:6,
};
this.color='black';
this.type=_params.type;
this.params=_params;

二:绘制坐标轴Y轴

const_height=this.params.height;
const_pad=this.params.padding;
const_arrow=_pad+','+(_pad-5)+''+(_pad-6)+','+(_pad+12)+''+(_pad+6)+','+(_pad+12);
this.AxisY={
x1:_pad,
y1:_height-_pad,
x2:_pad,
y2:_pad,
arrow:_arrow
};

三、绘制Y轴的刻度

const_height=this.params.height;
const_width=this.params.width;
//显示label的边距
const_padding=this.params.padding;
const_Ydata=this.params.yAxis.data;
//显示的刻度数
const_YscaleNo=this.params.YscaleNo;
const_dataMax=this.getMinAndMaxData(_Ydata).dataMax;
const_dataMin=this.getMinAndMaxData(_Ydata).dataMin;
let_YminValue;
let_YgapValue;
if(_dataMin<0){
_YgapValue=Math.ceil((_dataMax-_dataMin)/(_YscaleNo)/10)*10;
_YminValue=Math.floor(_dataMin/_YgapValue)*_YgapValue;
}else{
_YgapValue=Math.ceil((_dataMax)/(_YscaleNo)/10)*10;
_YminValue=0;
}
//Y轴坐标点
const_y2=this.AxisY.y2;
const_y1=this.AxisY.y1;
const_x1=this.AxisY.x1;
//Y轴刻度的间隙宽度
const_YgapWidth=(_y1-_y2)/(this.params.YscaleNo);
this.valueToPxRatio=_YgapValue/_YgapWidth;
//坐标轴(0,0)的Y轴坐标
const_Y0=_y1-Math.abs(_YminValue/this.valueToPxRatio);
this.Y0=_Y0;
for(leti=0;i<this.params.YscaleNo;i++){
const_obj:Scale={x1:0,x2:0,y1:0,y2:0,label:'',value:0};
_obj.x1=_x1;
_obj.y1=_y1-_YgapWidth*i;
_obj.x2=_x1+_width-2*_padding;
_obj.y2=_y1-_YgapWidth*i;
_obj.label=_YminValue+_YgapValue*i;
this.Yscale.push(_obj);
}

四、绘制X坐标轴

const_width=this.params.width;
//显示label的边距
const_pad=this.params.padding;
const_x2=_width-_pad;
const_y2=this.Y0;
const_arrow=(_x2+5)+','+_y2+''+(_x2-10)+','+(_y2-6)+''+(_x2-10)+','+(_y2+6);
this.AxisX={
x1:_pad,
y1:_y2,
x2:_x2,
y2:_y2,
arrow:_arrow
};

五、绘制X轴刻度

const_width=this.params.width;
const_Xdata=this.params.xAxis.data;
const_Ydata=this.params.yAxis.data;
constY0=this.Y0;
const_x1=this.AxisX.x1;
const_x2=this.AxisX.x2;
constXgapWidth=((_x2-_x1)/(this.params.xAxis.data.length+1));
this.XgapWidth=XgapWidth;
for(leti=0;i<_Xdata.length;i++){
const_obj:Scale={x1:0,x2:0,y1:0,y2:0,value:0,label:''};
_obj.y1=Y0;
_obj.y2=Y0+5;
_obj.label=_Xdata[i];
_obj.value=_Ydata[i];
_obj.x1=_x1+XgapWidth*(i+1);
_obj.x2=_x1+XgapWidth*(i+1);
this.Xscale.push(_obj);

六、绘制矩形

const_value=this.params.yAxis.data;
const_dataPadding=this.params.dataPadding;
const_XgapWidth=this.XgapWidth;
for(leti=0;i<_value.length;i++){
constelement=_value[i];
const_obj:Chart={x:0,y:0,w:0,h:0,value:0};
_obj.w=_XgapWidth-2*_dataPadding;
_obj.x=this.Xscale[i].x1-_obj.w-_dataPadding;
_obj.h=Math.abs(this.Xscale[i].value/this.valueToPxRatio);
_obj.value=this.Xscale[i].value;
if(this.Xscale[i].value>=0){
_obj.y=this.Y0-(this.Xscale[i].value)/this.valueToPxRatio;
}else{
_obj.y=this.Y0;
}
this.data.push(_obj);
}
}

七、绘制折线

const_data=this.data;
let_str='';
_data.forEach(ele=>{
if(ele.value<0){
ele.y=ele.y+ele.h;
}
_str+=(ele.x+ele.w/2)+','+ele.y+'';
});
this.polyLinePoints=_str;

关于如何在Angular2中使用SVG自定义图表问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注恰卡编程网行业资讯频道了解更多相关知识。

发布于 2021-04-15 01:56:13
收藏
分享
海报
0 条评论
157
上一篇:使用C#怎么比较类型 下一篇:使用Node.js怎么实现一个HTTP服务器
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码