(3)FluidMoveBehavior 之模仿 Windows Phone 開始菜單的 Tile 長按后排序


 

   這個工程和上一篇 (2)中介紹的排序大同小異,只是比上一篇交換復雜一點,不是通過單擊進行交換,

而是拖動一個 Tile 到另一個 Tile 上時,判斷兩個 Tile 的中心距離是否符合條件來判斷是否進行交換兩個 Tile。

歸根結底還是利用 FluidMoveBehavior 行為來使 Silverlight 的元素在重新定位時,產生動畫效果。畢竟在

實際開發中,用戶體驗還是很重要的,生動的交互比生硬的交互會更讓用戶感到親切。

   當然項目中也用到了視覺狀態管理相關的技術,因為不是重點,這里不會過多的介紹。

 

   效果交互圖:

 第一步:首先定義一個 UserControl 類,作為一個 Tile 控件,並且在 CodeBehind 頁面中注冊一個

  依賴屬性 TileBackgroundProperty,用來設置 Tile 不同的背景,效果:

 

 

    給該 Tile 控件添加 3 種不同的視覺狀態:NormalVisualState、CheckedVisualState、FloatVisualState,即

當長按選中時,為 CheckedVisualState 狀態,並顯示右上角的圖片 “圖釘”;其它 tile 狀態為 FloatVisualState,

為了讓不同的 tile 漂浮的方向和方式不同,提供 4 個 FloatVisualState 。

相應的 xaml :

    <Grid x:Name="LayoutRoot" Margin="10" Width="150" Height="150">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="VisualStateGroup">
                <VisualState x:Name="NormalVisualState"/>
                <VisualState x:Name="CheckedVisualState">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Assets_thumb_png">
                            <DiscreteObjectKeyFrame KeyTime="0">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Visible</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames></Storyboard>
                </VisualState>    
                <VisualState x:Name="FloatVisualState1">
                    <Storyboard RepeatBehavior="Forever" AutoReverse="True">
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="0.9"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="0.9"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="-5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.6"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="FloatVisualState2">
                    <Storyboard RepeatBehavior="Forever" AutoReverse="True">
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="0.9"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="0.9"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.6"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="FloatVisualState3">
                    <Storyboard RepeatBehavior="Forever" AutoReverse="True">
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="0.9"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="0.9"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="-5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="-5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.6"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="FloatVisualState4">
                    <Storyboard RepeatBehavior="Forever" AutoReverse="True">
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="0.9"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.9"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="0.9"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="-5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="-5"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:6" Value="5"/>
                        </DoubleAnimationUsingKeyFrames>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="grid">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.6"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:4.5" Value="0.6"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>     
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Grid x:Name="grid" Background="{StaticResource PhoneAccentBrush}" RenderTransformOrigin="0.5,0.5">
            <Grid.RenderTransform>
                <CompositeTransform/>
            </Grid.RenderTransform>
            <Image Source="{Binding TileBackground}" Stretch="Fill"/>
            <Image x:Name="Assets_thumb_png" Visibility="Collapsed" Margin="124,-16,-15,124" Source="Assets/thumb.png" Stretch="Fill"/>
        </Grid>        
    </Grid>
View Code


該自定義控件相應的 C#:

    public partial class TileControl : UserControl
    {
        public TileControl()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        #region TileBackground (依賴屬性)        
        /// <summary>
        /// Tile 的背景圖片
        /// </summary>
        public string TileBackground
        {
            get 
            {
                return (string)GetValue(TileBackgroundProperty); 
            }
            set 
            { 
                SetValue(TileBackgroundProperty, value); 
            }
        }
        public static readonly DependencyProperty TileBackgroundProperty =
            DependencyProperty.Register("TileBackground", typeof(string), typeof(TileControl),
              new PropertyMetadata("/Assets/Tiles/FlipCycleTileMedium.png"));

        #endregion                

        // 漂浮
        static Random rand = new Random();
        public void Float()
        {
            // 使 tile 進入不同的漂浮狀態
            switch (rand.Next(5))
            {
                case 1:
                    VisualStateManager.GoToState(this, "FloatVisualState1", false);
                    break;
                case 2:
                    VisualStateManager.GoToState(this, "FloatVisualState2", false);
                    break;
                case 3:
                    VisualStateManager.GoToState(this, "FloatVisualState3", false);
                    break;
                case 4:
                    VisualStateManager.GoToState(this, "FloatVisualState4", false);
                    break;
                default: VisualStateManager.GoToState(this, "FloatVisualState3", false);
                    break;
            }
        }

        // 選中
        public void Checked()
        {
            VisualStateManager.GoToState(this, "CheckedVisualState", false);
        }

        // 恢復
        public void Reset()
        {
            VisualStateManager.GoToState(this, "NormalVisualState", false);
        }
    }
View Code

 

第二步:定義不同的 Tile 在重疊時,判斷中心點的距離,是否小於 40px,如果是,則交換兩個 Tile。

     如果 Tile 控件的 寬和 高設置為 150px,則各個控件的坐標為:

 

 

當拖動一個 Tile 到其它 Tile 上時,判斷兩個 Tile 的中心點坐標的距離:

 

 

第三步:在 MainPage 頁面中,添加一個 Grid,分別放置各個自定義控件,並且每個自定義控件放在一個 Boder 里面,

    並且分別注冊 Border 的長按事件 Hold 統一為 Border_Hold:

       <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Grid.Resources>
                <Style TargetType="Border">
                    <Setter Property="Background" Value="Transparent"/>
                </Style>
            </Grid.Resources>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <i:Interaction.Behaviors>
                <el:FluidMoveBehavior x:Name="fluidBehavior" AppliesTo="Children" Duration="00:00:01">
                    <el:FluidMoveBehavior.EaseY>
                        <QuinticEase EasingMode="EaseOut"/>
                    </el:FluidMoveBehavior.EaseY>
                    <el:FluidMoveBehavior.EaseX>
                        <QuinticEase EasingMode="EaseOut"/>
                    </el:FluidMoveBehavior.EaseX>
                </el:FluidMoveBehavior>
            </i:Interaction.Behaviors>
            <Border Hold="Border_Hold">
                <local:TileControl TileBackground="/Assets/Tiles/01.png"/>
            </Border>
            <Border Grid.Column="1" Hold="Border_Hold">
                <local:TileControl TileBackground="/Assets/Tiles/02.png"/>
            </Border>
            <Border  Grid.Row="1"  Hold="Border_Hold">
                <local:TileControl TileBackground="/Assets/Tiles/03.png"/>
            </Border>
            <Border Grid.Row="1" Grid.Column="1"  Hold="Border_Hold">
                <local:TileControl TileBackground="/Assets/Tiles/04.png"/>
            </Border>
            <Border Grid.Row="2"  Hold="Border_Hold">
                <local:TileControl TileBackground="/Assets/Tiles/05.png"/>
            </Border>
            <Border  Grid.Row="2" Grid.Column="1" Hold="Border_Hold">
                <local:TileControl TileBackground="/Assets/Tiles/06.png"/>
            </Border>
        </Grid>

 

第四步:在 MainPage 頁面的 CodeBehind 中,定義一個類型為  Dictionary<Point, Border> 的泛型字典 dic,

     當頁面加載完成時,初始化該字典:

       public MainPage()
        {
            InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            InitDic();
        }

        // Size : 資源素距離父元素左上角的距離
        Dictionary<Point, Border> dic = new Dictionary<Point, Border>();
        int childWidth;

        // 初始化一個字典集合,Key:border 元素的中心點坐標,value:border 自己
        void InitDic()
        {
            dic.Clear();

            foreach (var item in ContentPanel.Children)
            {
                childWidth = (int)item.DesiredSize.Width;

                Border border = item as Border;
                int row = Grid.GetRow(border);
                int col = Grid.GetColumn(border);
                Point position = new Point(col * childWidth + childWidth / 2, row * childWidth + childWidth / 2);
                border.Tag = position;

                dic.Add(position, border);

                Debug.WriteLine("point-  x:" + (col * childWidth + childWidth / 2) + "  y:" + (row * childWidth + childWidth / 2));
            }
        }

 

在 Border 的 Border_Hold 方法中,添加邏輯,用來處理各個 Tile 的視圖狀態,並且注冊 ManipulationDelta 和 MouseLeftButtonUp 事件:

       Border borderTemp;
        CompositeTransform transformTemp;
        private void Border_Hold(object sender, System.Windows.Input.GestureEventArgs e)
        {
            e.Handled = true;

            borderTemp = sender as Border;

            // 注冊 tile 右上角“圖釘”圖片的單擊事件
            (borderTemp.Child as TileControl).Assets_thumb_png.Tap += Assets_thumb_png_Tap;

            transformTemp = new CompositeTransform();

            transformTemp.TranslateX = x;
            transformTemp.TranslateY = y;

            borderTemp.RenderTransform = transformTemp;

            // 拖動 border 時,改變它的坐標
            borderTemp.ManipulationDelta += borderTemp_ManipulationDelta;

            // 當手指離開 border 時,判斷各個 tile 中心點的距離
            borderTemp.MouseLeftButtonUp += borderTemp_MouseLeftButtonUp;

            if (borderTemp.Child != null)
            {
                foreach (var item in ContentPanel.Children)
                {
                    Border border = item as Border;
                    if (border.Child != null)
                    {
                        TileControl tile = border.Child as TileControl;
                        // 被選中的 tile 進入 CheckedVisualState 視圖狀態,其余的進入 FloatVisualState 視圖狀態
                        if (tile == (borderTemp.Child as TileControl))
                        {
                            tile.Checked();                            
                            border.IsHitTestVisible = true;
                        }
                        else
                        {
                            tile.Float();
                            // 當處於漂浮狀態時,不再接收“單擊”等屏幕事件
                            border.IsHitTestVisible = false;
                        }
                    }
                }
            }
        }

 

 

當手指離開選擇的 Tile 時,判斷各個 Tile 的中心點的距離,從而判斷是否具備交換兩個 Tile 的條件:

        void borderTemp_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            e.Handled = true;

            DateTime timeStart = DateTime.Now;

            Debug.WriteLine("Translation.X: " + transformTemp.TranslateX);
            Debug.WriteLine("Translation.Y: " + transformTemp.TranslateY);

            Point pointSource = (Point)borderTemp.Tag;

            Point point = new Point(transformTemp.TranslateX + pointSource.X, transformTemp.TranslateY + pointSource.Y);

            bool IsSwaped = false;

            // 當手指離開屏幕時,判斷選中的 tile 的中心點和其它中心點的直線距離,
            // 如果距離小於 40px,則兩個 tile 互換 //換
            foreach (Point position in dic.Keys)
            {
                Border border2 = dic[position];
                if (borderTemp != border2)
                {
                    x = (int)(point.X - position.X);
                    y = (int)(point.Y - position.Y);

                   // 計算兩個 Tile 中心點的直線距離                  
int distance = (int)Math.Sqrt(x * x + y * y); if (distance < 40) { // 交換兩個 tile 的位置 SwapBorder(borderTemp, border2); IsSwaped = true; break; } } } Debug.WriteLine(DateTime.Now - timeStart); if (!IsSwaped) { transformTemp.TranslateX = 0; transformTemp.TranslateY = 0; } }

 

 

   重要代碼粘貼到上面了,具體代碼可以下載工程。至此有關 FluidMoveBehavior 行為的三篇文章暫時寫完了。

   這個demo 運行的交互很簡單,但是算法上還是頗費周折,想了幾種實現方式,最終采用了上面的方式,重點時間

都花費在了數學計算上了。不過 demo 的代碼還是比較粗糙,性能也沒有優化,只是實現了大概的交互。

 

工程源碼下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM