web-dev-qa-db-ja.com

WPF。プログラムで画像を(X、Y)に移動する最も簡単な方法は?

XAMLを使用せず、プログラムで100%WPFアニメーションを使用して、画像の現在の場所から新しい場所(X、Y)への動きを簡単にアニメーション化する方法を知っている人はいますか?そして、「これ」への参照なしで(RegisterNameなどで)。

Imageの拡張クラスを作成して、アニメーションを実行しようとしています。アニメーションで幅と高さのプロパティを変更するのは簡単ですが、オブジェクトの位置アニメーションを検索すると、突然高度になります。

これは拡張クラスなので、実際のImageオブジェクトへの参照と、移動先のXとYのみを持ちます。

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

更新:

ありがとう。ほとんど動作しています。 GetTopとGetLeftは、明示的に設定されていない「NaN」を返すようです。この投稿で回避策を見つけました: Canvas.GetTop()returns 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);
        }

2つの値(FROM)を0と交換する必要がありました。このコンテキストでは、画像の左上隅が原点であるためだと思いますか?しかし、今はうまくいきます。

11
Wolf5

これを試して:

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);
}
23
Dean Chalk

ここにあります...サイズを変更し、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>

更新:

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

そして、C#コードを次の場所に配置することを忘れないでください。

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

MediaElementも使用できますが、何かを表示するにはVideoClipを定義する必要があります;)

4
Developer

ネストされた要素に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);
    }
1
Akli

このコードは@DeanChalkの回答に基づいています。

ImageRFID_Token)内のCanvasを右上から左下に斜めに移動し、ImageRFID_Reader)内の別のCanvasの中央に配置します。

<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);
1
Danny Beckett

拡張メソッドに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);

    }
0
laserman