矩阵动画错误。在WPF代码背后

时间:2015-09-02 07:24:32

标签: wpf animation path

我制作动画。

使用ArcSegment绘制路径。

继续前进。

然而,不同于动画的起点和路径的起点。

应该修改什么?

此图片..开始动画后立即。

圆圈位置位于路径的中间。

我想帮助我。拜托......

Here is a sample.

动画部分。源代码

我创建了演示版。 我的源代码用韩文写的。所以创建演示版

如果您继续点击第二个按钮。

路径的起点和起点的不同起点。

如果有其他方法可能。

更改来源时并不重要。

这只是为了成功。我们期待取得好成绩。

你是一个非常好的人。谢谢

XAML

<Window x:Class="WpfApplication7.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="400" Width="830">
<Grid>
    <Button x:Name="num_bt" Content="1.create number" HorizontalAlignment="Left" VerticalAlignment="Top" Width="118" Click="num_bt_Click"/>
    <Button x:Name="start" Content="2.start animation" HorizontalAlignment="Left" Margin="-2,50,0,0" VerticalAlignment="Top" Width="118" Click="draw_bt_Click"/>
    <Label Content="contiue click" HorizontalAlignment="Left" Margin="0,97,0,0" VerticalAlignment="Top" Width="116"/>
    <Label Content="start animation btn" HorizontalAlignment="Left" Margin="0,120,0,0" VerticalAlignment="Top" Width="116"/>
    <Canvas x:Name="canvas" HorizontalAlignment="Left" Height="373" Margin="137,0,0,0" VerticalAlignment="Top" Width="685"/>

</Grid>

背后的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication7
{
/// <summary>
/// MainWindow.xaml에 대한 상호 작용 논리
/// </summary>
public partial class MainWindow : Window
{
    int num_count = 10;  // use data number
    List<int> sampleNumbers;    // Save a number to use for sorting
    int count = 1;  // count
    Ellipse[] Circle;

    List<double> SaveCircleStartPoint;
    struct SaveCircleProperty
    {
        public double Circle_stposX;
        public double Circle_stposY;
        public double radian;
    }

    List<SaveCircleProperty> SaveCircleInfos;

    // save changed sorting info
    struct SortingTraceInfo
    {
        public int Position;    // change position
        public int TargetPosition;  // will change position
        public int[] SortingNumbers;    // sorting numbers
    }

    // save changed sorting info 
    List<SortingTraceInfo> sortingInfos;
    int sortingInfosIndex;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void num_bt_Click(object sender, RoutedEventArgs e)
    {
        Random _random = new Random(); // create number
        int[] num = new int[10];
        sampleNumbers = new List<int>();

        for (int i = 0; i < num_count; i++)
        {
            num[i] = _random.Next(1, 50);
            sampleNumbers.Add(num[i]);   // save number data
        }

        BubbleSort();
        drawCircle(num_count, sampleNumbers);
    }

    private void draw_bt_Click(object sender, RoutedEventArgs e)
    {
        // draw a path and start animation
        SortingTraceInfo traceInfo = this.sortingInfos[this.sortingInfosIndex++];

        draw_path(traceInfo.Position, traceInfo.TargetPosition);
    }

    // draw circle
    private void drawCircle(int num, List<int> size)
    {
        // saving a position to draw a circle
        SaveCircleStartPoint = new List<double>();
        SaveCircleInfos = new List<SaveCircleProperty>();

        // To create the circle by the number of input num
        Circle = new Ellipse[num];
        int location = ((685 / num) - 5); // circle startpoint

        int x = 50; // Width
        int y = 115; // Height

        for (int i = 0; i < num; i++)
        {
            double circlesize = size[i] + 10;
            double radius = circlesize / 2; // radius
            double st_posX = x - radius;    // circular X-axis position
            double st_posY = y - radius;    // circular Y-axis position
            SaveCircleProperty cp = new SaveCircleProperty();

            // define circle property
            Circle[i] = new Ellipse();
            Circle[i].Name = "circle" + i.ToString();
            Circle[i].Stroke = Brushes.Red;
            Circle[i].StrokeThickness = 5;
            Circle[i].Width = circlesize;
            Circle[i].Height = circlesize;

            // position of canvs
            Canvas.SetLeft(Circle[i], st_posX); // startpoint x-axis
            Canvas.SetTop(Circle[i], st_posY); // startpoint Y-axis

            // save circls's property
            SaveCircleStartPoint.Add(st_posX);
            cp.Circle_stposX = st_posX;
            cp.Circle_stposY = st_posY;
            cp.radian = radius;
            SaveCircleInfos.Add(cp);

            // startpoint 
            x += location;

            // add canvas
            canvas.Children.Add(Circle[i]);
            this.RegisterName(Circle[i].Name, Circle[i]);
        }
    }

    private void draw_path(int pos1, int pos2)
    {
        SaveCircleProperty scp = this.SaveCircleInfos[pos1];
        SaveCircleProperty scp2 = this.SaveCircleInfos[pos2];
        create_path(scp.Circle_stposX, scp.Circle_stposY, scp2.Circle_stposX, scp2.Circle_stposY, scp.radian, scp2.radian, pos1, pos2);
    }

    private void create_path(double startPoint, double startPoint2, double endPoint, double endPoint2, double radian1, double radian2, int position, int tartgetPosition)
    {
        // regist name
        NameScope.SetNameScope(this, new NameScope());
        NameScope.SetNameScope(canvas, new NameScope());

        // circls position reset
        Canvas.SetLeft(Circle[position], 0);
        Canvas.SetTop(Circle[position], 0);

        Canvas.SetLeft(Circle[tartgetPosition], 0);
        Canvas.SetTop(Circle[tartgetPosition], 0);

        ///<summary>
        /// Circle left the road going from left to right
        ///</summary>

        PathGeometry pathGeometryLeft = new PathGeometry();
        PathFigure Leftfigure = new PathFigure();
        Leftfigure.StartPoint = new Point(startPoint, startPoint2); // x-axis , y-axis start point

        // point(x-axis, y-axis) 
        Leftfigure.Segments.Add(new ArcSegment(new Point(endPoint, startPoint2), new Size(150, endPoint - startPoint), 90, false, SweepDirection.Clockwise, true));
        pathGeometryLeft.Figures.Add(Leftfigure);
        Path Leftpath = new Path();
        Leftpath.Data = pathGeometryLeft;
        Leftpath.Stroke = Brushes.Green;
        canvas.Children.Add(Leftpath);

        MatrixTransform LeftcircleMatrixTransform = new MatrixTransform();
        Circle[position].RenderTransform = LeftcircleMatrixTransform;

        this.RegisterName("LeftCircleMatrixTransform" + count.ToString(), LeftcircleMatrixTransform);

        pathGeometryLeft.Freeze();

        // Create a MatrixAnimationUsingPath to move the
        // circle along the path by animating
        // its MatrixTransform.
        MatrixAnimationUsingPath Leftmatrixanimation = new MatrixAnimationUsingPath();
        Leftmatrixanimation.PathGeometry = pathGeometryLeft;
        Leftmatrixanimation.Duration = TimeSpan.FromSeconds(5);
        Leftmatrixanimation.DoesRotateWithTangent = true;

        // Set the animation to target the Matrix property
        // of the MatrixTransform named "ButtonMatrixTransform".
        Storyboard.SetTargetName(Leftmatrixanimation, "LeftCircleMatrixTransform" + count.ToString());
        Storyboard.SetTargetProperty(Leftmatrixanimation, new PropertyPath(MatrixTransform.MatrixProperty));

        // Create a Storyboard to contain and apply the animation.
        Storyboard LeftpathAnimationStoryboard = new Storyboard();
        LeftpathAnimationStoryboard.Children.Add(Leftmatrixanimation);

        LeftpathAnimationStoryboard.Begin(this);

        /// <summary>
        /// The road to the right circle from right to left (path)
        /// </summary>

        PathGeometry RightpathGeometry = new PathGeometry();
        PathFigure Rightfigure = new PathFigure();
        Rightfigure.StartPoint = new Point(endPoint, endPoint2 + (radian2 * 2)); // x축 , y축 시작점

        // point(x축 끝, y축 끝점) 
        Rightfigure.Segments.Add(new ArcSegment(new Point(startPoint, endPoint2 + (radian2 * 2)), new Size(150, endPoint - startPoint), 90, false, SweepDirection.Clockwise, true));

        // this.RegisterName("RightmyArcSegment", Rightfigure.Segments);

        RightpathGeometry.Figures.Add(Rightfigure);
        Path Rightpath = new Path();
        Rightpath.Data = RightpathGeometry;
        Rightpath.Stroke = Brushes.Red;
        canvas.Children.Add(Rightpath);

        MatrixTransform RightcircleMatrixTransform = new MatrixTransform();
        Circle[tartgetPosition].RenderTransform = RightcircleMatrixTransform;

        this.RegisterName("RightCircleMatrixTransform" + count.ToString(), RightcircleMatrixTransform);

        RightpathGeometry.Freeze();

        MatrixAnimationUsingPath Rightmatrixanimation = new MatrixAnimationUsingPath();
        Rightmatrixanimation.PathGeometry = RightpathGeometry;
        Rightmatrixanimation.Duration = TimeSpan.FromSeconds(10);

        // Set the animation's DoesRotateWithTangent property
        // to true so that rotates the rectangle in addition
        // to moving it.
        Rightmatrixanimation.DoesRotateWithTangent = true;

        // Set the animation to target the Matrix property
        // of the MatrixTransform named "CircleMatrixTransform".
        Storyboard.SetTargetName(Rightmatrixanimation, "RightCircleMatrixTransform" + count.ToString());
        Storyboard.SetTargetProperty(Rightmatrixanimation, new PropertyPath(MatrixTransform.MatrixProperty));

        // Create a Storyboard to contain and apply the animation.
        Storyboard RightpathAnimationStoryboard = new Storyboard();
        RightpathAnimationStoryboard.Children.Add(Rightmatrixanimation);

        RightpathAnimationStoryboard.Begin(this);

        Ellipse temp = null;
        temp = Circle[position];
        Circle[position] = Circle[tartgetPosition];
        Circle[tartgetPosition] = temp;
        count++;
    }


    // 버블 정렬
    private List<int> BubbleSort()
    {
        sortingInfos = new List<SortingTraceInfo>();
        List<int> sorting = new List<int>(sampleNumbers);

        for (int i = 0; i < sorting.Count - 1; i++)
        {
            for (int j = 0; j < sorting.Count - 1 - i; j++)
            {
                if (sorting[j] > sorting[j + 1])
                {
                    Swap(sorting, j, j + 1);

                    SortingTraceInfo sortInfo = new SortingTraceInfo(); // 
                    sortInfo.Position = j;  // save change position
                    sortInfo.TargetPosition = j + 1;    // save will change position
                    sortInfo.SortingNumbers = sorting.ToArray();   // sorting number saved to array 
                    sortingInfos.Add(sortInfo); // 변경 정보등을 sortingInfos 리스트에 저장
                }
            }
        }
        return sorting;
    }

    private void Swap(List<int> num, int i, int j)
    {
        int temp = num[i];
        num[i] = num[j];
        num[j] = temp;
    }
  }
}

1 个答案:

答案 0 :(得分:1)

    private void draw_path(int pos1, int pos2)
    {
        var circles = canvas.Children.OfType<Ellipse>().OrderBy(q => (double)q.GetValue(Canvas.LeftProperty)).ToList();

        var circle1 = circles[pos1];
        var circle2 = circles[pos2];

        // horizontal animation for circle1
        Storyboard sb1 = new Storyboard();
        double from1 = (double)circle1.GetValue(Canvas.LeftProperty);
        double to1 = (double)circle2.GetValue(Canvas.LeftProperty) + circle2.ActualWidth / 2 - circle1.ActualWidth / 2;
        DoubleAnimation da1 = new DoubleAnimation(from1, to1, new Duration(TimeSpan.FromSeconds(0.6)));

        Storyboard.SetTarget(sb1, circle1);
        Storyboard.SetTargetProperty(sb1, new PropertyPath(Canvas.LeftProperty));

        sb1.Children.Add(da1);

        // horizontal animation for circle2
        Storyboard sb2 = new Storyboard();
        double from2 = (double)circle2.GetValue(Canvas.LeftProperty);
        double to2 = (double)circle1.GetValue(Canvas.LeftProperty) + circle1.ActualWidth / 2 - circle2.ActualWidth / 2;
        DoubleAnimation da2 = new DoubleAnimation(from2, to2, new Duration(TimeSpan.FromSeconds(0.6)));

        Storyboard.SetTarget(sb2, circle2);
        Storyboard.SetTargetProperty(sb2, new PropertyPath(Canvas.LeftProperty));

        sb2.Children.Add(da2);

        // vertical animation for circle1
        Storyboard sb3 = new Storyboard();
        double from3 = (double)circle1.GetValue(Canvas.TopProperty);
        double to3 = (double)circle1.GetValue(Canvas.TopProperty) + circle1.ActualWidth;
        DoubleAnimation da3 = new DoubleAnimation(from3, to3, new Duration(TimeSpan.FromSeconds(0.3)));
        da3.AutoReverse = true;
        da3.AccelerationRatio = 0.1;

        Storyboard.SetTarget(sb3, circle1);
        Storyboard.SetTargetProperty(sb3, new PropertyPath(Canvas.TopProperty));

        sb3.Children.Add(da3);

        // vertical animation for circle2
        Storyboard sb4 = new Storyboard();
        double from4 = (double)circle2.GetValue(Canvas.TopProperty);
        double to4 = (double)circle2.GetValue(Canvas.TopProperty) - circle2.ActualWidth;
        DoubleAnimation da4 = new DoubleAnimation(from4, to4, new Duration(TimeSpan.FromSeconds(0.3)));
        da4.AutoReverse = true;
        da4.AccelerationRatio = 0.1;

        Storyboard.SetTarget(sb4, circle2);
        Storyboard.SetTargetProperty(sb4, new PropertyPath(Canvas.TopProperty));

        sb4.Children.Add(da4);

        sb1.Begin();
        sb2.Begin();
        sb3.Begin();
        sb4.Begin();
    }

希望,这有帮助