WPF анимация движения

Все исходники / Язык программирования C# / OS Windows / Desktop / WPF программирование / WPF анимация движения
Оглавление:
  1. Анимация движения кнопок
  2. Выбор контейнера
  3. Построение каркаса класса
  4. Разработка кода
  5. Анимация движения червяка
  6. Код главного окна
  7. Исходник анимации движения элементов

Анимация движения кнопок

WPF, Анимация движения кнопокЗадача. Построить метод для передвижения кнопки в указанные координаты. Передвижение кнопки должно осуществляться анимацией, т.е. плавно от исходной позиции в конечную. Построить анимацию для группы кнопок, запускаемую по щелчку в окне приложения. Скорость движения элементов должна быть постоянной, независимо от расстояния перемещения.

Выбор контейнера

Для перемещения кнопки (или любого другого элемента) по плоской форме достаточно двух координат Left по горизонтали и Top по вертикали. В силу философии компоновки WPF позиционированием своих детей ведают контейнеры и поэтому элементы не имеют свойств Left и Top. Класс Button, соответственно, также не имеет свойств абсолютного позиционирования.

Чтобы кнопки перемещались точно в указанные координаты, в качестве контейнера, выберем панель Canvas. Canvas автоматически не позиционирует свои дочерние элементы, но позволяет указывать для них абсолютные места размещения. Статический методы Canvas.SetLeft(элемент, координата-X), Canvas.SetTop(элемент, координата-Y) перемещают элементы в любую позицию в пределах канвы.

Построение каркаса класса

Метод анимационного перемещения кнопки создадим в отдельном классе. Таким образом, используя принцип инкапсуляции, значительно уменьшим количество кода в файле главного окна приложения.

Построим скелет класса, назовём его Moving: Листинг скелета класса:
static class Moving
{
    public static void MoveTo(FrameworkElement fe, double x, double y)
    {
	    ...
    }
}

Поскольку в составе класса только один метод и нет ни одного поля, рациональней объявить его статическим. Метод движения элемента в качестве параметров принимает сам элемент и координаты пункта назначения. Хотя речь идет об анимации кнопок, в качестве первого параметра можно использовать элемент любого типа.

Разработка кода

По условию нет необходимости создавать длительную анимацию, поэтому код упростим применением метода UIElement.BeginAnimation(…), который наследует класс Button. Один метод с параметрами для Left координаты, аналогичный метод для Top координаты. BeginAnimation(...) работает в отдельном потоке, не прерывая основной. Два метода запустятся почти одновременно и управляемый элемент поедет по прямой до точки с координатами x и y.

Чтобы скорость была постоянной, длительность анимации должна быть пропорциональна расстоянию перемещения. Перед началом движения необходимо вычислять длину гипотенузы (катеты – Left->Left1 и Top->Top1) и делить её на значение скорости. Так мы получаем время движения в пути, обеспечивая константную скорость на любые дистанции.

Вот что у нас получилось, полный листинг класса Moving:
static class Moving
{
    public static void MoveTo(FrameworkElement fe, double x, double y)
    {
        // Значение скорость условные единицы в секунду.
        double speed = 300;
  
        // Получение начальных координат
        double leftInit = Canvas.GetLeft(fe);
        double topInit = Canvas.GetTop(fe);
 
        // Вычисление катетов. Нас интересует только расстояние,
        // поэтому используем модули значений катетов.
        double X = Math.Abs(x - leftInit);
        double Y = Math.Abs(y - topInit);
        double quart = Math.Sqrt(X * X + Y * Y);

        // Время для данного расстояния с указанной скоростью.
        double time = quart / speed;

        var left = new DoubleAnimation
        {
            From = leftInit,
            To = x,
            Duration = new Duration(TimeSpan.FromSeconds(time))
        };

        var top = new DoubleAnimation
        {
            From = topInit,
            To = y,
            Duration = new Duration(TimeSpan.FromSeconds(time))
        };

        fe.BeginAnimation(Canvas.LeftProperty, left);
        fe.BeginAnimation(Canvas.TopProperty, top);
    }
}

Анимация движения червяка

WPF, Анимация движения червякаЗадача. Создать анимацию элемента напоминающего движение червяка. В качестве контейнера для элемента нельзя использовать панель Canvas. Движение построить на изменениях относительных величин. Обеспечить настройку частоты кадров анимации.

Разработка алгоритма движения элемента

Код главного окна

Благодаря тому, что все задачи выполнены в отдельных классах, программный код главного окна приложения получился небольшим и понятным.

Стоит отдельно описать создание группы кнопок. Множество элементов не рационально определять в XAML файле. Гораздо быстрее создать массив элементов класса Button с необходимыми настройками свойств и координатами размещения. Инициализация группы кнопок и объекта класса движения червяка происходят в конструкторе.

Код инициализации приложения:
private readonly WormAnimation wormAnimation;
readonly Button[] buttons = new Button[9];

public MainWindow()
{
    InitializeComponent();

    for(int i = 0; i < buttons.Length; i++)
    {
        buttons[i] = new Button();
        buttons[i].Width = buttons[i].Height = 24;
        buttons[i].Content = i + 1;

        // Автоматический расчёт координат размещения.
        Canvas.SetLeft(buttons[i], 0);
        Canvas.SetTop(buttons[i], 24 * i);
        // Каждая кнопка будет на поле Canvas.
        fieldMoving.Children.Add(buttons[i]);
    }

    // Контейнер - Grid. Червяка представит Border.
    // Скорость анимации 60 кадров в секунду обеспечит плавные движения.
    wormAnimation = new WormAnimation(gridAquarium, earthworm, 60);
}
Код запуска анимаций группы кнопок и имитации движения червяка:
bool horizontal = true;
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    for (int i = 0; i < buttons.Length; i++)
    {
        double temp = (buttons[i].Width + 1) * i;
        // Смена направления движения при каждом щелчке мыши.
        if (horizontal == true) Moving.MoveTo(buttons[i], temp, 0);
        else Moving.MoveTo(buttons[i], 0, temp);
    }
    // Флаг направления изменяем на противоположный.
    horizontal = !horizontal;
}

private void gridAquarium_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    wormAnimation.LetsGo();
}

Исходник анимации движения элементов

Исходный код написан в MS Visual Studio 2019. Два вида анимаций размещены в закладках контейнера TabControl. Исходник приложения комбинирует инициализацию элементов в XAML и в программном коде. Для работы с исходным кодом рекомендуется изучить данную статью.

Скачать исходник

Тема: «WPF анимация движения» Язык программирования C# WpfButtonAnimation-vs16.zip Размер:120 КбайтЗагрузки:424