Оптимизация анимации пользовательского элемента управления - PullRequest
0 голосов
/ 16 октября 2010

Хорошо. Итак, я создаю «Приложение Windows Forms» для какого-то парня, использующего C #, и я хочу сделать его интерфейс немного более интересным для него.

Основная форма выглядит как большой циферблат с пользовательскимкнопки расположены на нем.(Я говорю о пользовательских кнопках, поскольку они на самом деле являются простыми пользовательскими элементами управления, которые я создал, которые имеют PictureBox и Метка , которые увеличиваются, когда пользователь указывает на них, а затем уменьшаются, когда мышькурсор перемещается за его пределы. Также имеется свойство Image , которое устанавливает PictureBox 'Изображение и используется в качестве значка так называемой пользовательской кнопки.)

Я использовал два таймера с именами tmrEnlarge и tmrShrink , которые активируются при событиях MouseEnter и MouseLeave соответственно.По сути, это всего лишь пара простых функций для увеличения и уменьшения размера PictureBox , используемого в моем пользовательском элементе управления, и его вид, будто он увеличивается ...

Работает просто отлично, нопроблема в том, что, когда мышь наводит на несколько элементов управления одновременно, анимация замедляет движение дау (что, на мой взгляд, нормально, так как таймеры не лучший способ сделать что-то, как я!), я тоже пытался использовать потоки, нопроблема все еще здесь!: - (

Я хочу знать, каков наилучший способ сделать что-то подобное?

РЕДАКТИРОВАТЬ:

Вот код, который я использовалдля рисования изображения непосредственно на элементе управления без использования PictureBox :

(Это просто быстрая версия, которая оставляет остатков после рисования изображения, что не важнодля меня прямо сейчас)

public partial class DDAnimatingLabel : UserControl
{
    public Image Image { get; set; }

    public DDAnimatingLabel()
    {
        InitializeComponent();
    }

    private void DDAnimatingLabel_MouseEnter(object sender, EventArgs e)
    {
        tmrEnlarge.Enabled = true;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        if (Image != null)
        {
            e.Graphics.DrawImage(this.Image, e.ClipRectangle);
        }
        else
            base.OnPaint(e);
    }

    private void tmrEnlarge_Tick(object sender, EventArgs e)
    {
        if (Size.Width >= MaximumSize.Width)
        {
            tmrEnlarge.Enabled = false;
            return;
        }

        Size s = Size;
        s.Height += 4;
        s.Width += 4;
        Size = s;

        Point p = Location;
        p.X -= 2;
        p.Y -= 2;
        Location = p;
    }

    private void tmrShrink_Tick(object sender, EventArgs e)
    {
        if (tmrEnlarge.Enabled)
            return;

        if (Size.Width == MinimumSize.Width)
        {
            tmrShrink.Enabled = false;
            return;
        }

        Size s = Size;
        s.Height -= 4;
        s.Width -= 4;
        Size = s;

        Point p = Location;
        p.X += 2;
        p.Y += 2;
        Location = p;
    }

    private void DDAnimatingLabel_MouseLeave(object sender, EventArgs e)
    {
        tmrShrink.Enabled = true;
    }
}

1 Ответ

0 голосов
/ 18 октября 2010

Я изначально неправильно понял ваш вопрос.Некоторое время назад я создал систему анимации для такого рода вещей.Здесь вы можете найти этот код: http://pastebin.com/k1XmRapH.

Это старая «версия» моей системы анимации.Это грубо, но относительно мало и легко понять.Ниже показано демонстрационное приложение, которое использует систему анимации.

Ключевые моменты этой системы:

  • Использование одного таймера, который выдает синхронизированный «импульс» для каждой запущенной анимации
  • Импульс использует истекшее время, чтобы вычислить, какое изменение применить

Демонстрационное приложение использует AnimationGroup для изменения свойств как Размер, так и Местоположение.Когда мышь входит в кнопку, мы сначала отменяем любую существующую анимацию, а затем запускаем анимацию, чтобы увеличить кнопку.Когда мышь покидает кнопку, мы снова отменяем любую существующую анимацию и затем запускаем анимацию, чтобы вернуть ее в нормальное состояние.Указание AnimationTerminate.Cancel для AnimationManager.Remove отменяет работающую анимацию без вызова ее метода End (который завершит анимацию).Это оставляет свойства кнопки в состоянии, в котором они находились в момент отмены, и плавно возвращает кнопку к нормальному размеру.

using System;
using System.Drawing;
using System.Windows.Forms;

class Form1 : Form
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    const int PulseInterval = 20;
    const int ButtonAnimateTime = 250;

    AnimationManager animate;
    Point[] buttonLocationsNormal, buttonLocationsHover;
    Size buttonSizeNormal, buttonSizeHover;

    public Form1()
    {
        Text = "Demo";
        ClientSize = new Size(480, 100);

        animate = new AnimationManager { PulseInterval = PulseInterval };

        buttonLocationsNormal = new Point[4];
        buttonLocationsHover = new Point[4];
        buttonSizeNormal = new Size(100, 80);
        buttonSizeHover = new Size(120, 100);

        for (int n = 0, x = 10; n < 4; n++, x += 120)
        {
            Point normalLocation = new Point(x, 10);
            buttonLocationsNormal[n] = normalLocation;
            buttonLocationsHover[n] = new Point(x - 10, 0);
            Button button = new Button { Text = "Text", Location = normalLocation, Size = buttonSizeNormal };
            button.MouseEnter += (s, e) => AnimateButton(s as Button, true);
            button.MouseLeave += (s, e) => AnimateButton(s as Button, false);
            Controls.Add(button);
        }
    }

    private void AnimateButton(Button button, bool hovering)
    {
        int index = Controls.IndexOf(button);
        AnimationGroup group = button.Tag as AnimationGroup;
        if (group != null)
            animate.Remove(group, AnimationTerminate.Cancel);

        Point newLocation;
        Size newSize;
        if (hovering)
        {
            newLocation = buttonLocationsHover[index];
            newSize = buttonSizeHover;
        }
        else
        {
            newLocation = buttonLocationsNormal[index];
            newSize = buttonSizeNormal;
        }
        group = new AnimationGroup(
            new PropertyAnimation("Location", button, newLocation, TimeSpan.FromMilliseconds(ButtonAnimateTime), new PointAnimator())
            , new PropertyAnimation("Size", button, newSize, TimeSpan.FromMilliseconds(ButtonAnimateTime), new SizeAnimator())
        );
        button.Tag = group;
        animate.Add(group);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...