Binyy Wuhan

i love Flex i come from Wuhan

导航

Flex【原创】惯性定位效果

  最近有一个需求:显示对象从一个点以惯性运动的方式运动到另外一个点。

  感觉就好像定位功能的特效一样,缓动到目标点。

  小弟专门为此封装了这个功能,废话不说,贴代码,给Demo。

  版本Flex4.6

  一共2个类:

 

  1:核心算法类 EaseTween

  1 package 
2 {
3 import flash.display.DisplayObject;
4 import flash.events.Event;
5
6 /**
7 * DisplayObject惯性定位效果
8 *
9 * <br>s = (d-a) + (d-2*a) + (d-3*a) + … + (d-n*a)</br>
10 * <br>d - n*a = 0</br>
11 * <br>===></br>
12 * <br>d = 2*s/(n-1)</br>
13 * <br>a = 2*s/(n*n-n)</br>
14 *
15 * @date 2012.03.20
16 * @version 0.2
17 * @author yaoyf
18 * **/

19 public class EaseTween
20 {
21 /**
22 * @private
23 * */

24 private static var _diso:DisplayObject;
25 private static var _offsetX:Number;
26 private static var _offsetY:Number;
27 private static var _totalDistance:Number;
28 private static var _currentDistance:Number;
29
30 /**
31 * @private
32 * */

33 private static var _accelerationX:Number;
34 private static var _accelerationY:Number;
35 private static var _defualtSpeedX:Number;
36 private static var _defualtSpeedY:Number;
37
38 private static var _times:int = 0;//执行帧数
39 private static var _ratio:int;//距离/执行帧数 = ratio = speed
40

41 /**
42 * 执行缓动效果
43 *
44 * @param diso:diso
45 * @param offsetX:Number diso的x轴偏移量
46 * @param offsetY:Number diso的y轴偏移量
47 * @param speed:Number 定位速度(default = 10)
48 *
49 * @error ErrorX3233:Arguments speed must be greater than 0
50 *
51 * @date 2012.03.20
52 * @version 0.2
53 * @author yaoyf
54 * **/

55 public static function doEaseEffect(diso:DisplayObject,offsetX:Number=0,offsetY:Number = 0,speed:Number=20):void{
56 _diso = diso;
57 if(offsetX == 0 && offsetY == 0){
58 _diso.dispatchEvent(new EaseEffectEvent(EaseEffectEvent.EVT_EASE_DEFAULT));
59 return;
60 }
61 if(speed == 0)return;
62 if(speed < 0){
63 throw new Error("ErrorX3233:Arguments speed must be greater than 0");
64 }
65 _diso.dispatchEvent(new EaseEffectEvent(EaseEffectEvent.EVT_EASE_BEGIN));
66 _offsetX = -offsetX;
67 _offsetY = -offsetY;
68 _currentDistance = 0;
69 _totalDistance = getDistance(_offsetX,_offsetY);
70 _ratio = speed;
71 _times = _totalDistance / _ratio;
72 var dis:Number = 2 * _totalDistance / (_times - 1);
73 var acceleration:Number = 2 * _totalDistance / (_times * (_times - 1));
74 var rio:Number = offsetX / offsetY;
75 _defualtSpeedX = getVector(dis,rio,"x");
76 _defualtSpeedY = getVector(dis,rio,"y");
77 _accelerationX = getVector(acceleration,rio,"x");
78 _accelerationY = getVector(acceleration,rio,"y");
79 diso.addEventListener(Event.ENTER_FRAME, onEaseEnterFrame);
80 }
81
82 //onEnterFrame
83 private static function onEaseEnterFrame(e:Event):void{

84 _defualtSpeedX -= _accelerationX;
85 _defualtSpeedY -= _accelerationY;
86 doPan(_defualtSpeedX,_defualtSpeedY);
87 _currentDistance += getDistance(_defualtSpeedX,_defualtSpeedY);
88 if(_currentDistance >= _totalDistance){
89 _diso.removeEventListener(Event.ENTER_FRAME, onEaseEnterFrame);
90 _diso.dispatchEvent(new EaseEffectEvent(EaseEffectEvent.EVT_EASE_END));
91 }
92 }
93
94 //平移
95 private static function doPan(valueX:Number,valueY:Number):void{

96 if(_offsetX < 0 && _offsetY >= 0){
97 _diso.x += valueX;
98 _diso.y -= valueY;
99 }else if(_offsetY < 0 && _offsetX >= 0){
100 _diso.x -= valueX;
101 _diso.y += valueY;
102 }else if(_offsetY < 0 && _offsetX < 0){
103 _diso.x += valueX;
104 _diso.y += valueY;
105 }else{
106 _diso.x -= valueX;
107 _diso.y -= valueY;
108 }
109 _diso.dispatchEvent(new EaseEffectEvent(EaseEffectEvent.EVT_EASING));
110 }
111
112 //获取x,y轴分向量长度
113 private static function getVector(dis:Number,rio:Number,type:String):Number{

114 switch(type)
115 {
116 case "x" :
117 if(Math.abs(rio) == Infinity){
118 return dis;
119 }else{
120 return Math.abs(rio * Math.sqrt(dis * dis / (rio * rio + 1)));
121 }
122 break;
123 case "y" :
124 if(Math.abs(rio) == Infinity){
125 return 0;
126 }else{
127 return Math.abs(Math.sqrt(dis * dis / (rio * rio + 1)));
128 }
129 break;
130 default :
131 break;
132 }
133 return 0;
134 }
135
136 //勾股函数 获取斜边长度
137 private static function getDistance(deltaX:Number,deltaY:Number):Number{

138 return Math.sqrt(deltaX*deltaX + deltaY*deltaY);
139 }
140
141 }
142 }

 
2:相关事件类
package
{
import flash.events.Event;

/**
* 定位缓动事件类
*
* @date 2012.03.20
* @version 0.2
* @author yaoyf
* *
*/

public class EaseEffectEvent extends Event
{
/**定义 EVT_EASE_DEFAULT事件的type属性,offect为零,不执行缓动**/
public static const EVT_EASE_DEFAULT:String = "easeDefaultEvt";

/**定义 EVT_EASE_BEGIN事件的type属性,缓动开始**/
public static const EVT_EASE_BEGIN:String = "easeBeginEvt";

/**定义 EVT_EASING事件的type属性,缓动中**/
public static const EVT_EASING:String = "easingEvt";

/**定义 EVT_MOUSE_HOLDON_DOWN事件的type属性,缓动结束**/
public static const EVT_EASE_END:String = "easeEndEvt";

/**
* 构造方法
* @param type 事件类型
* @param bubbles 确定 Event 对象是否参与事件流的冒泡阶段。默认值为 false
* @param cancelable 确定是否可以取消 Event 对象。默认值为 false
*/

public function EaseEffectEvent(type:String,bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}

/**
* 克隆
*/

override public function clone():Event
{
return new EaseEffectEvent(type,bubbles,cancelable);
}
/**
* 字符串转换
*/

override public function toString():String
{
return formatToString("EaseEffectEvent","type","bubbles","cancelable","eventPhase");
}

}
}


调用事例:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
initialize="windowedapplication1_initializeHandler(event)">

<fx:Script>
<![CDATA[
import flash.crypto.generateRandomBytes;

import mx.controls.Alert;
import mx.events.FlexEvent;

protected function windowedapplication1_initializeHandler(event:FlexEvent):void
{
this.maximize();
diso.addEventListener(EaseEffectEvent.EVT_EASE_DEFAULT,onEaseDefualt);
diso.addEventListener(EaseEffectEvent.EVT_EASE_BEGIN,onEaseBegin);
diso.addEventListener(EaseEffectEvent.EVT_EASE_END,onEaseEnd);
diso.addEventListener(EaseEffectEvent.EVT_EASING,onEasing);
}

protected function onEaseBegin(event:Event):void
{
trace("onEaseBegin");
}

protected function onEasing(event:Event):void
{
trace("onEasing");
diso.setStyle("backgroundColor",Math.random()*0xEEEEEE);
}

protected function onEaseEnd(event:Event):void
{
trace("onEaseEnd");
}

protected function onEaseDefualt(event:Event):void
{
Alert.show("error !");
}

]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<s:Label id="diso" x="385" y="241" width="45" height="45" backgroundColor="0x123456"/>
<s:HGroup top="10">
<s:Label text="deltaX:" verticalAlign="middle" height="20"/>
<s:TextInput id="txt1"/>
<s:Label text="deltaY:" verticalAlign="middle" height="20"/>
<s:TextInput id="txt2"/>
<s:Label text="speed:" verticalAlign="middle" height="20"/>
<s:TextInput id="txt3"/>
<s:Button x="405" y="10" label="doPan"
click="EaseTween.doEaseEffect(diso,Number(txt1.text),Number(txt2.text),Number(txt3.text))"/>
</s:HGroup>
<s:Label id="lbl" left="10" bottom="10" text="{'( ' + diso.x + ' , ' + diso.y + ' )'}"/>
</s:WindowedApplication>

 
效果图:

 

  

  Demo下载:https://files.cnblogs.com/loveFlex/Sample_fixedPposition.rar

 

posted on 2012-03-22 15:17  Binyy_Wuhan  阅读(684)  评论(0编辑  收藏  举报