代码之家  ›  专栏  ›  技术社区  ›  Wolf5

WPF公司。以编程方式将图像移动到(X,Y)的最简单方法?

  •  11
  • Wolf5  · 技术社区  · 14 年前

    有没有人知道一种简单的方法,可以使用WPF动画将一个从图像的当前位置移动到一个新位置(X,Y),而不使用XAML,100%编程?也没有提到“这个”(注册名等)。

    我正在尝试为图像制作一个扩展类,以便对其进行动画处理。通过动画更改宽度和高度属性很容易,但在搜索对象的位置动画后,它突然变得更高级。

    因为它是一个扩展类,所以我只能引用实际的图像对象和要移动到的X和Y。

    public static void MoveTo(this Image targetControl, double X, double Y, double Width, double Height){
     //code here
     ...
    }
    

    更新:

    谢谢。差不多可以了。似乎GetTop和GetLeft返回的“NaN”未显式设置。在这篇文章中找到了解决方法: Canvas.GetTop() returning NaN

    public static void MoveTo(this Image target, double newX, double newY) {
                    Vector offset = VisualTreeHelper.GetOffset(target);
                    var top = offset.Y;
                    var left = offset.X;
                    TranslateTransform trans = new TranslateTransform();
                    target.RenderTransform = trans;
                    DoubleAnimation anim1 = new DoubleAnimation(0, newY - top, TimeSpan.FromSeconds(10));
                    DoubleAnimation anim2 = new DoubleAnimation(0, newX - left, TimeSpan.FromSeconds(10));
                    trans.BeginAnimation(TranslateTransform.YProperty, anim1);
                    trans.BeginAnimation(TranslateTransform.XProperty, anim2);
            }
    

    我不得不用0来交换其中的两个值。我想这一定是因为在这种情况下,图片的左上角是原点?但现在成功了。

    5 回复  |  直到 7 年前
        1
  •  22
  •   Danny Beckett    10 年前

    试试这个:

    public static void MoveTo(this Image target, double newX, double newY)
    {
        var top = Canvas.GetTop(target);
        var left = Canvas.GetLeft(target);
        TranslateTransform trans = new TranslateTransform();
        target.RenderTransform = trans;
        DoubleAnimation anim1 = new DoubleAnimation(top, newY - top, TimeSpan.FromSeconds(10));
        DoubleAnimation anim2 = new DoubleAnimation(left, newX - left, TimeSpan.FromSeconds(10));
        trans.BeginAnimation(TranslateTransform.XProperty,anim1);
        trans.BeginAnimation(TranslateTransform.YProperty,anim2);
    }
    
        2
  •  4
  •   Danny Beckett    10 年前

    在这里。。。它会改变大小并移动 MediaElement Canvas . 只需输入参数:

    Storyboard story = new Storyboard();
    DoubleAnimation dbWidth = new DoubleAnimation();
    dbWidth.From = mediaElement1.Width;
    dbWidth.To = 600;
    dbWidth.Duration = new Duration(TimeSpan.FromSeconds(.25));
    
    DoubleAnimation dbHeight = new DoubleAnimation();
    dbHeight.From = mediaElement1.Height;
    dbHeight.To = 400;
    dbHeight.Duration = dbWidth.Duration;
    
    story.Children.Add(dbWidth);
    Storyboard.SetTargetName(dbWidth, mediaElement1.Name);
    Storyboard.SetTargetProperty(dbWidth, new PropertyPath(MediaElement.WidthProperty));
    
    story.Children.Add(dbHeight);
    Storyboard.SetTargetName(dbHeight, mediaElement1.Name);
    Storyboard.SetTargetProperty(dbHeight, new PropertyPath(MediaElement.HeightProperty));
    
    DoubleAnimation dbCanvasX = new DoubleAnimation();
    dbCanvasX.From = 0;
    dbCanvasX.To = 5;
    dbCanvasX.Duration = new Duration(TimeSpan.FromSeconds(.25));
    
    DoubleAnimation dbCanvasY = new DoubleAnimation();
    dbCanvasY.From = 0;
    dbCanvasY.To = 5;
    dbCanvasY.Duration = dbCanvasX.Duration;
    
    story.Children.Add(dbCanvasX);
    Storyboard.SetTargetName(dbCanvasX, mediaElement1.Name);
    Storyboard.SetTargetProperty(dbCanvasX, new PropertyPath(Canvas.LeftProperty));
    
    story.Children.Add(dbCanvasY);
    Storyboard.SetTargetName(dbCanvasY, mediaElement1.Name);
    Storyboard.SetTargetProperty(dbCanvasY, new PropertyPath(Canvas.TopProperty));
    
    story.Begin(this);
    

    <Viewbox Stretch="Uniform" StretchDirection="Both" SnapsToDevicePixels="True">
            <Grid  Width="640" Height="480" Name="MainLayout" SnapsToDevicePixels="True" Background="Black">
                <Canvas Width="640" Height="480" Name="MainCanvas" SnapsToDevicePixels="True">
                    <MediaElement Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337" LoadedBehavior="Manual" Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" />
                    <Button Canvas.Left="294" Canvas.Top="196" Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
                </Canvas>
            </Grid>
        </Viewbox>
    

    更新:

    而不是 中间元素 使用此行:

     <Rectangle Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337"    Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" Fill="{DynamicResource {x:Static SystemColors.MenuBarBrushKey}}" />
    

    别忘了把C代码放在:

    private void button1_Click(object sender, RoutedEventArgs e) {}
    

    你可以用 中间元素 但是你必须定义 VideoClip 看到一些东西;)

        3
  •  1
  •   Danny Beckett    10 年前

    此代码基于@DeanChalk的答案。

    它移动一个 Image 包含在 Canvas ( RFID_Token )从右上到左下呈对角线,位于另一个 图像 帆布 ( RFID_Reader ).

    <Canvas>
        <Canvas x:Name="RFID_Reader_Canvas">
            <Image x:Name="RFID_Reader" Source="RFID-Reader.png" Height="456" Width="682" Canvas.Left="37" Canvas.Top="524"/>
        </Canvas>
        <Canvas x:Name="RFID_Token_Canvas">
            <Image x:Name="RFID_Token" Source="RFID-Token.png" Height="268" Width="343" Canvas.Left="874" Canvas.Top="70"/>
        </Canvas>
    </Canvas>
    

    var StartX = Canvas.GetLeft(RFID_Token);
    var StartY = Canvas.GetTop(RFID_Token);
    
    var EndX = RFID_Reader.Width / 2 + Canvas.GetLeft(RFID_Reader) - StartX - (RFID_Token.Width / 2);
    var EndY = RFID_Reader.Height / 2 + Canvas.GetTop(RFID_Reader) - StartY - (RFID_Token.Height / 2);
    
    var AnimationX = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(1));
    var AnimationY = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(1));
    
    var Transform = new TranslateTransform();
    RFID_Token_Canvas.RenderTransform = Transform;
    
    Transform.BeginAnimation(TranslateTransform.XProperty, AnimationX);
    Transform.BeginAnimation(TranslateTransform.YProperty, AnimationY);
    
        4
  •  1
  •   Akli    7 年前

    我的嵌套元素一直有NaN或0值,下面是Danny的修改版答案:

        public void MoveTo(Canvas canvas, FrameworkElement target, FrameworkElement destination)
        {
            Point oldPoint = target.TransformToAncestor(canvas).Transform(new Point(0, 0));
            Point newPoint = destination.TransformToAncestor(canvas).Transform(new Point(0, 0));
    
            var EndX = destination.Width / 2 + newPoint.X - oldPoint.X - (target.Width / 2);
            var EndY = destination.Height / 2 + newPoint.Y - oldPoint.Y - (target.Height / 2);
    
            TranslateTransform trans = new TranslateTransform();
            target.RenderTransform = trans;
            DoubleAnimation anim1 = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(0.3));
            DoubleAnimation anim2 = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(0.3));
            trans.BeginAnimation(TranslateTransform.XProperty, anim1);
            trans.BeginAnimation(TranslateTransform.YProperty, anim2);
        }
    
        5
  •  0
  •   laserman    9 年前

    请为扩展方法找到一个使用Canvas的左侧和顶部属性的解决方案。请参见以下代码:

        public static void MoveTo(this Image target, Point newP)
        {
    
            Point oldP = new Point();
            oldP.X = Canvas.GetLeft(target);
            oldP.Y = Canvas.GetTop(target);
    
            DoubleAnimation anim1 = new DoubleAnimation(oldP.X, newP.X, TimeSpan.FromSeconds(0.2));
            DoubleAnimation anim2 = new DoubleAnimation(oldP.Y, newP.Y , TimeSpan.FromSeconds(0.2));
    
            target.BeginAnimation(Canvas.LeftProperty , anim1);
            target.BeginAnimation(Canvas.TopProperty, anim2);
    
        }