Kim Sang Hoon
Kim Sang Hoon

Reputation: 51

Matrix animation error. in WPF in code behind

I making animation.

Draw a path with use a ArcSegment.

And moves along to the path.

However, different from startingpoint of animation and startingpoint of path.

What should modify?

this image .. Immediately after the starting the animation.

Circle location is in the middle of the Path.

I Want to help me. please...

enter image description here

animation part. source code

i create demo version. my source code written in korean. so create demo version

If you continue to click the second button.

Different starting point of the path and starting point Of a circle.

If there are other methods that may be.

It does not matter all when you change the source.

This is just to succeed. We look forward to good results.

You are a really good person. thank you

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>

code behind

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

Upvotes: 0

Views: 241

Answers (1)

keymusicman
keymusicman

Reputation: 1291

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

Hope, it helps

Upvotes: 1

Related Questions