AS3 HorizontalScroller---- 水平滚动条控件,细节是魔鬼

水平滚动条的,向右按钮:

package
{
	public class HorizontalScrollerLeftButton extends Button
	{
		public function HorizontalScrollerLeftButton()
		{
			super();
			
			width=10;
			height=10;
		}
		
		protected override function refreshBackground():void
		{
			//super.refreshBackground();
			
			//背景也居中
			this.graphics.clear();
			this.graphics.beginFill(0x55aa00, 0.5);
			this.graphics.drawRect(0,0,10,10);
			this.graphics.endFill();
			
			//边框
			this.graphics.moveTo(0,0);
			this.graphics.lineStyle(1,0,.5);
			this.graphics.lineTo(10,0);
			this.graphics.lineTo(10,10);
			this.graphics.lineTo(0,10);
			this.graphics.lineTo(0,0);
			
			//三角形
			this.graphics.moveTo(2,5);
			this.graphics.lineStyle(1,0,.5);
			this.graphics.lineTo(8,2);
			this.graphics.lineTo(8,8);
			this.graphics.lineTo(2,5);
		}
	}
}

向右按钮:

package
{
	public class HorizontalScrollerRightButton extends Button
	{
		public function HorizontalScrollerRightButton()
		{
			super('');
			
			width=10;
			height=10;
		}
		
		protected override function refreshBackground():void
		{
			//super.refreshBackground();
			
			//背景也居中
			this.graphics.clear();
			this.graphics.beginFill(0x55aa00, 0.5);
			this.graphics.drawRect(0,0,10,10);
			this.graphics.endFill();
			
			//边框
			this.graphics.moveTo(0,0);
			this.graphics.lineStyle(1,0,.5);
			this.graphics.lineTo(10,0);
			this.graphics.lineTo(10,10);
			this.graphics.lineTo(0,10);
			this.graphics.lineTo(0,0);
			
			//三角形
			this.graphics.moveTo(8,5);
			this.graphics.lineStyle(1,0,.5);
			this.graphics.lineTo(2,2);
			this.graphics.lineTo(2,8);
			this.graphics.lineTo(8,5);
		}
	}
}

滚动器按钮:

package
{
	/**
	 * 滚动条的滚动器
	 * @author Jave.Lin
	 */	
	public class ScrollPacker extends Button
	{
		public override function get width():Number
		{
			return super.width;
		}
		
		public override function set width(value:Number):void
		{
			if(super.width!=value)
			{
				super.width=value;
				
				if(super.width==0)visible=false;
				else visible=true;
				
				refreshBackground();
			}
		}
		
		public override function get height():Number
		{
			return super.height;
		}
		
		public override function set height(value:Number):void
		{
			if(super.height!=value)
			{
				super.height=value;
				
				refreshBackground();
			}
		}
		
		public function ScrollPacker()
		{
			super('');
			
			refreshBackground();
		}
		
		protected override function refreshBackground():void
		{
			//背景也居中
			this.graphics.clear();
			this.graphics.beginFill(0x55aa00, 0.5);
			this.graphics.drawRect(0,0,width,height);
			this.graphics.endFill();
			//边框
			this.graphics.moveTo(0,0);
			this.graphics.lineStyle(1,0,.5);
			this.graphics.lineTo(width,0);
			this.graphics.lineTo(width,height);
			this.graphics.lineTo(0,height);
			this.graphics.lineTo(0,0);
		}
	}
}

最后是:整个滚动条组件,做的时间,感觉好多细节都比较难发现。做了才知道。魔鬼啊魔鬼----细节。

package
{
	import controlsEvents.ScrollerEvent;
	
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Point;
	import flash.utils.getTimer;

	/**
	 * 水平滚动条
	 * (纯graphics控件,后期可能要考虑开放更多的一些重绘制接口:方便外部的写重绘制这部分)
	 * @author Jave.Lin
	 */
	public class HorizontalScroller extends Control
	{
		private var _leftBtn:HorizontalScrollerLeftButton;//向左的按钮--减量操作
		private var _rightBtn:HorizontalScrollerRightButton;//向右的按钮--增量操作
		private var _rollPacker:ScrollPacker;//滚动器
		private var _buttonInterval:Number=20;
		private var _curValue:int=0;//当前值
		private var _minValue:int=0;//最小值
		private var _maxValue:int=100;//最大值
		private var _increment:int=5;//每次操作的增/减量
		private var _isAdding:Boolean=false;
		//续持性快速操作的控件参数
		private var _quickCurTime:int=0;
		private var _quickOperateTime:int=0;
		private var _quickOperateTimeMax:int=500;
		private var _maxPos:Number;//滚动器最远的距离
		private var _curVisibleRate:Number=1;//当前可视范围比率,直接影响滚动器的宽度
		
		public function get curVisibleRate():Number
		{
			return _curVisibleRate;
		}
		
		public function set curVisibleRate(value:Number):void
		{
			if(_curVisibleRate!=value)
			{
				_curVisibleRate=value;
				if(_curVisibleRate<=0)_curVisibleRate=0;
				if(_curVisibleRate >=1)_curVisibleRate=1;
				onLayout();
			}
		}
		
		public function get maxValue():int
		{
			return _maxValue;
		}
		
		public function set maxValue(value:int):void
		{
			if(_maxValue!=value)
			{
				if(_minValue>value)throw new Error("HorizontalScroller maxValue less then minValue error! maxValue:"+value+" minValue:"+_minValue);
				_maxValue=value;
				if(curValue>_maxValue)curValue=_maxValue;
			}
		}
		
		public function get minValue():int
		{
			return _minValue;
		}
		
		public function set minValue(value:int):void
		{
			if(_minValue!=value)
			{
				if(value>_maxValue)throw new Error("HorizontalScroller minValue more then maxValue error! minValue:"+value+" maxValue:"+_maxValue);
				_minValue=value;
				if(curValue<_minValue)curValue=_minValue;
			}
		}
		
		public function get curValue():int
		{
			return _curValue;
		}
		
		public function set curValue(value:int):void
		{
			if(_curVisibleRate>=1)return;
			if(_curValue!=value)
			{
				var preValue:int=value;
				if(preValue<_minValue)preValue=_minValue;
				else if(preValue>_maxValue)preValue=_maxValue;
				if(preValue!=_curValue)
				{
					_curValue=preValue;
					if(_minValue==_maxValue)
					{
						_rollPacker.x=fixAndSetRollPackerX(_leftBtn.width);
					}
					else
					{
						_rollPacker.x=fixAndSetRollPackerX(_leftBtn.width+(_buttonInterval-_rollPacker.width)*((_curValue-_minValue)/(_maxValue-_minValue)));
					}
					
					dispatchEvent(new ScrollerEvent(ScrollerEvent.VALUE_CHANGED,_curValue));
				}
			}
		}
		
		public override function get width():Number
		{
			if(isNaN(_w))
			{
				_w=super.width;
			}
			return _w;
		}
		
		public override function set width(value:Number):void
		{
			if(_w!=value)
			{
				var sourceBI:Number=_buttonInterval;
				var sumW:Number=_leftBtn.width+_rightBtn.width;
				_buttonInterval=value-sumW;
				if(_w<value)
				{
					_w=value;
					if(_buttonInterval<10)
					{
						_buttonInterval=10;
						_w=sumW+_buttonInterval;
					}
				}
				else
				{
					_w=value;
				}
				refreshBackground();
				onLayout();
			}
		}
		
		public override function get height():Number
		{
			return super.height;
		}
		
		public function HorizontalScroller()
		{
			super();
		}
		
		private function fixAndSetRollPackerX(prePos:Number):Number
		{
			if(prePos<_leftBtn.width)prePos=_leftBtn.width;
			else if(prePos>_maxPos)prePos=_maxPos;
			return prePos;
		}
		
		private function xTransformToValueAndSetIt(prePos:Number):void
		{
			if(_curVisibleRate>=1)return;
			if(_rollPacker.x==prePos)
			{
				return;
			}
			curValue=(prePos-_leftBtn.width)/(_maxPos-_leftBtn.width)*(_maxValue-_minValue)+_minValue;
		}
		
		protected override function initialize():void
		{
			_leftBtn=new HorizontalScrollerLeftButton();
			addChild(_leftBtn);
			
			_rollPacker=new ScrollPacker();
			addChild(_rollPacker);
			
			_rightBtn=new HorizontalScrollerRightButton();
			addChild(_rightBtn);
			
			if(stage)
			{
				onAddedToStageHandler();
			}
			else
			{
				addEventListener(Event.ADDED_TO_STAGE,onAddedToStageHandler);
			}

			this.width=100;
			this.height=_leftBtn.height;

			onLayout();

			refreshBackground();
		}
		
		private function onLayout():void
		{
			_leftBtn.x=0;
			_leftBtn.y=0;
			
			_rollPacker.x=_leftBtn.width;
			_rollPacker.y=0;
			_rollPacker.height=_leftBtn.height;
			_rollPacker.width=(1-_curVisibleRate)*_buttonInterval;
			
			_rightBtn.x=_leftBtn.x+_leftBtn.width+_buttonInterval;
			_rightBtn.y=0;
			
			_maxPos=_leftBtn.width+_buttonInterval-_rollPacker.width;
		}
		
		private function onAddedToStageHandler(e:Event=null):void
		{
			removeEventListener(Event.ADDED_TO_STAGE,onAddedToStageHandler);
			
			addEventListener(Event.REMOVED_FROM_STAGE,onRemovedFromStageHandler);
			_leftBtn.addEventListener(MouseEvent.CLICK,onLeftBtnMouseClickHandler);
			_leftBtn.addEventListener(MouseEvent.MOUSE_OUT,onLeftBtnMouseOutHandler);
			_leftBtn.addEventListener(MouseEvent.MOUSE_DOWN,onLeftBtnMouseDownHandler);
			_leftBtn.addEventListener(MouseEvent.MOUSE_UP,onLeftBtnMouseUpHandler);
			_rightBtn.addEventListener(MouseEvent.CLICK,onRightBtnMouseClickHandler);
			_rightBtn.addEventListener(MouseEvent.MOUSE_OUT,onRightBtnMouseOutHandler);
			_rightBtn.addEventListener(MouseEvent.MOUSE_DOWN,onRightBtnMouseDownHandler);
			_rightBtn.addEventListener(MouseEvent.MOUSE_UP,onRightBtnMouseUpHandler);
			_rollPacker.addEventListener(MouseEvent.MOUSE_DOWN,onRollPackerMouseDownHandler);
		}
		//鼠标点下滚动器时,滚动器的备份坐标
		private var _mouseDownRollPackerSourceX:Number=0;
		//鼠标点下滚动器时,相对舞台的鼠标x坐标
		private var _mouseDownStageMouseSourceX:Number=0;
		//鼠标点下滚动器时,相对舞台的上一次的鼠标x坐标
		private var _lastStageMouseX:Number=0;
		
		private function onStageEnterFrameHandler(e:Event):void
		{
			if(_lastStageMouseX!=stage.mouseX)
			{
				xTransformToValueAndSetIt(fixAndSetRollPackerX(_mouseDownRollPackerSourceX+(stage.mouseX-_mouseDownStageMouseSourceX)));
				_lastStageMouseX=stage.mouseX;
			}
		}
		
		private function onStageMouseUpHandler(e:MouseEvent):void
		{
			stage.removeEventListener(Event.ENTER_FRAME,onStageEnterFrameHandler);
			_rollPacker.addEventListener(MouseEvent.MOUSE_DOWN,onRollPackerMouseDownHandler);
		}
		
		private function onRollPackerMouseDownHandler(e:MouseEvent):void
		{
			_mouseDownRollPackerSourceX=_rollPacker.x;
			_mouseDownStageMouseSourceX=stage.mouseX;
			_rollPacker.removeEventListener(MouseEvent.MOUSE_DOWN,onRollPackerMouseDownHandler);
			stage.addEventListener(Event.ENTER_FRAME,onStageEnterFrameHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP,onStageMouseUpHandler);
		}
		
		private function onRightBtnMouseClickHandler(e:MouseEvent):void
		{
			if(_curVisibleRate>=1)return;
			curValue+=_increment;
		}
		
		private function onRightBtnMouseUpHandler(e:MouseEvent):void
		{
			removeEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
			_quickOperateTime=0;
		}
		
		private function onRightBtnMouseDownHandler(e:MouseEvent):void
		{
			if(_curVisibleRate>=1)return;
			_quickCurTime=getTimer();
			_isAdding=true;
			addEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
		}
		
		private function onRightBtnMouseOutHandler(e:MouseEvent):void
		{
			removeEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
			_quickOperateTime=0;
		}
		
		private function onLeftBtnMouseUpHandler(e:MouseEvent):void
		{
			removeEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
			_quickOperateTime=0;
		}
		
		private function onLeftBtnMouseDownHandler(e:MouseEvent):void
		{
			if(_curVisibleRate>=1)return;
			_quickCurTime=getTimer();
			_isAdding=false;
			addEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
		}
		
		private function onLeftBtnMouseOutHandler(e:MouseEvent):void
		{
			removeEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
			_quickOperateTime=0;
		}
		
		private function onLeftBtnMouseClickHandler(e:MouseEvent):void
		{
			if(_curVisibleRate>=1)return;
			curValue-=_increment;
		}
		
		private function onEnterFrameHandler(e:Event):void
		{
			_quickOperateTime+=getTimer()-_quickCurTime;
			if(_quickOperateTime>_quickOperateTimeMax)
			{
				if(_isAdding)
				{
					curValue+=_increment;
				}
				else
				{
					curValue-=_increment;
				}
			}
		}
		
		private function onRemovedFromStageHandler(e:Event):void
		{
			removeEventListener(Event.REMOVED_FROM_STAGE,onRemovedFromStageHandler);
			_leftBtn.removeEventListener(MouseEvent.CLICK,onLeftBtnMouseClickHandler);
			_leftBtn.removeEventListener(MouseEvent.MOUSE_OUT,onLeftBtnMouseOutHandler);
			_leftBtn.removeEventListener(MouseEvent.MOUSE_DOWN,onLeftBtnMouseDownHandler);
			_leftBtn.removeEventListener(MouseEvent.MOUSE_UP,onLeftBtnMouseUpHandler);
			_rightBtn.removeEventListener(MouseEvent.CLICK,onRightBtnMouseClickHandler);
			_rightBtn.removeEventListener(MouseEvent.MOUSE_OUT,onRightBtnMouseOutHandler);
			_rightBtn.removeEventListener(MouseEvent.MOUSE_DOWN,onRightBtnMouseDownHandler);
			_rightBtn.removeEventListener(MouseEvent.MOUSE_UP,onRightBtnMouseUpHandler);
			_rollPacker.removeEventListener(MouseEvent.MOUSE_DOWN,onRollPackerMouseDownHandler);
			stage.removeEventListener(Event.ENTER_FRAME,onStageEnterFrameHandler);
			stage.removeEventListener(MouseEvent.MOUSE_UP,onStageMouseUpHandler);
		}
		
		protected override function refreshBackground():void
		{
			this.graphics.clear();
			//背景
			this.graphics.beginFill(0x008800,.5);
			this.graphics.drawRect(0,0,width,height);
			this.graphics.endFill();
		}
	}
}

运行测试图片效果:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值