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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4214155/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:20:27  来源:igfitidea点击:

WPF. Easiest way to move Image to (X,Y) programmatically?

wpfanimation

提问by Wolf5

Does anyone know of an easy way to animate a movement from an Image's current location to a new location (X,Y) using WPF animation with no XAML, 100% programmatically? And with no reference to "this" (with RegisterName etc).

有谁知道一种简单的方法,可以使用没有 XAML 的 WPF 动画 100% 以编程方式从图像的当前位置移动到新位置 (X,Y) 的动画?并且没有提到“这个”(使用 RegisterName 等)。

I am trying to make an extension class for Image to do animation stuff on it. It is easy enough to change the width and height properties through animation, but after searching for location animation of an object it suddenly becomes more advanced.

我正在尝试为 Image 制作一个扩展类来在它上面做动画。通过动画更改宽度和高度属性很容易,但是在搜索对象的位置动画后,它突然变得更加高级。

As it is an extension class I will only have a reference to the actual Image object and the X and Y I want to move it to.

因为它是一个扩展类,所以我只会引用实际的 Image 对象,而 X 和 YI 想要将它移动到。

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

Update:

更新:

Thanks. Almost working. It seems The GetTop and GetLeft returns 'NaN' not explicitly set. Found the workaround in this post: Canvas.GetTop() returning NaN

谢谢。快工作了。似乎 GetTop 和 GetLeft 返回未明确设置的“NaN”。在这篇文章中找到了解决方法:Canvas.GetTop() 返回 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);
        }

I had to swap two of the values (FROM) with 0. I assume that must be because in this context the upper left corner of the picture is the origin? But now it works.

我不得不用 0 交换两个值 (FROM)。我认为这一定是因为在这种情况下图片的左上角是原点?但现在它起作用了。

回答by Dean Chalk

Try this:

尝试这个:

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);
}

回答by Developer

Here it is... It changes the size and moves a MediaElementunder the Canvas. Just input your parameters:

这是...它改变了大小并MediaElementCanvas. 只需输入您的参数:

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>

UPDATE:

更新:

Instead of MediaElementuse this line:

而不是MediaElement使用这一行:

 <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}}" />

And don't forget to put the C# code to:

并且不要忘记将 C# 代码放在:

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

You can use MediaElementas well but you have to define a VideoClipto see something ;)

您也可以使用MediaElement,但您必须定义 aVideoClip才能看到某些东西;)

回答by Danny Beckett

This code is based on @DeanChalk's answer.

此代码基于@DeanChalk 的回答。

It moves an Imagecontained within a Canvas(RFID_Token) diagonally from the top-right to the bottom-left, positioned centrally over another Imagewithin a Canvas(RFID_Reader).

它将Imagea Canvas( RFID_Token) 中包含的一个从右上角向左下角移动,位于Imagea Canvas( 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);

回答by laserman

Please find a solution that uses the Left and Top properties of Canvas for the extension method. See the following code:

请找到使用 Canvas 的 Left 和 Top 属性作为扩展方法的解决方案。请参阅以下代码:

    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);

    }

回答by Akli

I kept having NaN or 0 values for my nested elements, here's a modified version of Danny's answer :

我的嵌套元素一直有 NaN 或 0 值,这是丹尼答案的修改版本:

    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);
    }