• (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 的代码还是比较粗糙,性能也没有优化,只是实现了大概的交互。

    工程源码下载

  • 相关阅读:
    下雪诗
    华视身份证阅读器100UC HTTP模式二次开发
    C# Action 和 Func 区别
    网站部署——文件系统
    前端-JavaScript DOM和BOM
    IO多路复用
    python-协程
    python-线程
    python-进程
    计算机与操作系统简介
  • 原文地址:https://www.cnblogs.com/hebeiDGL/p/3303647.html
Copyright © 2020-2023  润新知