• 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

  • 相关阅读:
    ksoap2 android 调用WebService
    Android App自动更新解决方案(DownloadManager)
    Android 网络加载通用Loading
    工具类ToastUtil 避免在子线程中使用抛异常 "Can't create handler inside thread that has not called Looper.prepare()"
    Material 风格的搜索框MaterialSearchView的使用
    Android集成极光推送
    第三十天
    第二十九天
    第二十八天
    第二十七天
  • 原文地址:https://www.cnblogs.com/loveFlex/p/2411673.html
Copyright © 2020-2023  润新知