Flex实现仪表盘控件

最近,应公司项目要求,研发一套图谱控件。涵盖折线图、棒图、饼图、仪表盘等多种类型图谱。现将仪表控件实现方式与大家分享,本文中不足之处欢迎大家指出,互相学习、共同进步微笑

先来看一下最终效果:


仪表控件结构上可以分为容器、表盘、指针、标注标签四部组成,之所以这么分是因为我希望表盘、标注、标注标签能够单独的变化,这样就可以通过开发不同样式的表盘、指针、标注标签等,让它们自由组合,实现仪表控件的灵活配置。


源码下载


这里的容器指的就是我们的仪表组件名称,其实现代码如下:

protected override function createChildren():void
		{
			super.createChildren();
			
			// 创建表盘
			this._meterBoard = MeterBoardBase.newInstance();
			this.addChild(this._meterBoard);
			
			// 创建刻度
			this._scaleLabels = ScaleLabelsBase.newInstance();
			this._scaleLabels.minValue = this._minValue;
			this._scaleLabels.maxValue = this._maxValue;
			this.addChild(this._scaleLabels);
			
			// 创建指针
			this._indicator = IndicatorBase.newInstance();
			this.addChild(this._indicator);
			
			// 初始化动画器
			this._animate = new Animate();
			this._animate.duration = 1000;
			this._animate.addEventListener(EffectEvent.EFFECT_UPDATE, this.onIndicatorUpdate);
		}
		
		protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			
			if (null != this._meterBoard)
			{
				this._meterBoard.setActualSize(unscaledWidth, unscaledHeight);
				this._meterBoard.x = this._meterBoard.y = 0;
			}
			
			if (null != this._indicator)
			{
				this._indicator.setActualSize(unscaledWidth, unscaledHeight);
				this._indicator.x = this._indicator.y = 0;
			}
			
			if (null != this._scaleLabels)
			{
				this._scaleLabels.setActualSize(unscaledWidth, unscaledHeight);
				this._scaleLabels.x = this._scaleLabels.y = 0;
			}
		}
其中我们使用_animate实现仪表盘指针转动的动画效果,确保无论指针的值的跳变量为多少,指针均能在正确的时间旋转到正确的刻度,这里我们设置的是1000毫秒。

接着来我们实现表盘的绘制,这里我们的表盘采用的半圆的形式,指针的旋转角度为0-180度。具体实现代码如下:

protected override function draw(unscaledWidth:Number, unscaledHeight:Number):void
		{
			this.graphics.clear();
			
			var radius:Number = this.getRadius(unscaledWidth, unscaledHeight);
			var ptCenter:Point = this.getCenterPoint(unscaledWidth, unscaledHeight);
			
			// 绘制表盘边框
			GeomUtil.drawSector(this.graphics, 0xf7f7f7, ptCenter.x, ptCenter.y, 0, radius * 0.8, -182, 1);
			GeomUtil.drawSector(this.graphics, 0x000000, ptCenter.x, ptCenter.y, radius * 0.78, radius * 0.8, -182, 1);
			GeomUtil.drawSector(this.graphics, 0x808080, ptCenter.x, ptCenter.y, radius * 0.76, radius * 0.78, -182, 1);
			
			// 绘制表盘样式
			var boardStyles:Array = DataParseUtil.parseMeterBoardData(this._boardDatas);
			if (DataObjectUtil.arrayValid(boardStyles))
			{
				for each (var pieData:PieData in boardStyles)
				{
					GeomUtil.drawSector(this.graphics, pieData.color, ptCenter.x, ptCenter.y, radius * 0.6, radius * 0.7, pieData.angle, pieData.start);
				}
			}
		}

GeomUtil是我定义的一个几乎工具类,用于实现几何图形的画法。GeomUtil中的drawSector方法用于绘制扇形,drawSector(graphics:Graphics, color:uint, x:Number, y:Number, r:Number, R:Number, angle:Number, startA:Number),参数graphics为绘图对象,color表示扇形区域的颜色,x,y为扇形所在圆的圆心坐标,r为扇形内径,R为扇形外径,angle表示扇形跨越的角度,startA是扇形的起始角度。

接着我们实现指针类,其绘制方法如下:

protected override function draw(unscaledWidth:Number, unscaledHeight:Number):void
		{
			this.graphics.clear();
			
			// 计算指针轴半径及中心点
			var radius:Number = unscaledHeight / 12;
			var ptCenter:Point = new Point(unscaledWidth / 2, unscaledHeight * 9 / 10);
			
			// 绘制指针
			var matrix:Matrix = new Matrix();
			
			// 获得指针的三个顶点坐标
			var ptEnd1:Point = Point.polar(radius, GeomUtil.convertToRadians(180 - this._degree - 30));
			var ptEnd2:Point = Point.polar(radius, GeomUtil.convertToRadians(180 - this._degree + 30));
			var ptEnd3:Point = Point.polar(radius + Math.min(ptCenter.x, ptCenter.y) * 0.68, GeomUtil.convertToRadians(180 - this._degree));
			ptEnd1.y = 0 - ptEnd1.y;
			ptEnd2.y = 0 - ptEnd2.y;
			ptEnd3.y = 0 - ptEnd3.y;
			ptEnd1.offset(ptCenter.x, ptCenter.y);
			ptEnd2.offset(ptCenter.x, ptCenter.y);
			ptEnd3.offset(ptCenter.x, ptCenter.y);
			
			// 绘制指针
			this.graphics.lineStyle(1, 0x0698c8, 0.9);
			this.graphics.beginFill(0x0698c8, 0.7);
			this.graphics.moveTo(ptEnd1.x, ptEnd1.y);
			this.graphics.lineTo(ptEnd3.x, ptEnd3.y);
			this.graphics.lineTo(ptEnd2.x, ptEnd2.y);
			this.graphics.lineTo(ptEnd1.x, ptEnd1.y);
			this.graphics.endFill();
			
			var degree:Number = 180 - this._degree;
			var offsetHor:Number = Math.cos(GeomUtil.convertToRadians(degree)) * radius / 5;
			var offsetVer:Number = Math.sin(GeomUtil.convertToRadians(degree)) * radius / 5;
			
			// 绘制指针轴
			matrix = new Matrix();
			matrix.createGradientBox(radius * 2, radius * 2, 0, offsetHor, 0 - offsetVer);
			matrix.translate(ptCenter.x - radius, ptCenter.y - radius);
			this.graphics.lineStyle(1, 0x585858, 0.8);
			this.graphics.beginGradientFill(GradientType.RADIAL, [0xfbfbfb, 0x7b7b7b], [1, 1], [0x00, 0xFF], matrix);
			this.graphics.drawCircle(ptCenter.x, ptCenter.y, radius);
			this.graphics.endFill();
		}

好了,我们的仪表控件关于绘制方面的内容就介绍完了。标注标签的实现等就不再一一给出代码了,稍后会给出整个控件的源代码,有兴趣的朋友下载后自己看吧。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值