Оптимизация анимации Fading Box - PullRequest
3 голосов
/ 01 ноября 2011

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

Я рассчитываю количество необходимых прямоугольников на основе размера виртуального экрана компьютера пользователя (например, у меня 3200x1200). Таким образом, максимизация и минимизация окна покажет больше фона. Как уже говорилось, для моего разрешения мне понадобятся 3220 прямоугольников.

Способ, которым я сейчас это реализовал, состоит в том, что все прямоугольники добавляются на холст со случайно сгенерированными альфа-значениями. Затем я задерживаю-начинаю анимацию с автоматической петлей (см. Ниже). Несомненно, это приводит к тому, что мое приложение очень вялое (справедливо). Могу ли я реализовать этот тип эффекта и получить гораздо лучшую производительность?

<Storyboard x:Key="uiStoryboardTile" AutoReverse="True" RepeatBehavior="Forever">
    <ColorAnimationUsingKeyFrames
        Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
        <EasingColorKeyFrame KeyTime="0:0:2" Value="Transparent"/>
    </ColorAnimationUsingKeyFrames>
</Storyboard>

Fading Boxes

Ответы [ 3 ]

0 голосов
/ 01 ноября 2011

Вот что я хотел бы сделать, чтобы улучшить производительность:

1) Создайте только прямоугольники, видимые на заднем плане.

2) Произвольно связать свойство Fill каждого Rectangle с одним из нескольких StaticResources предопределенных цветов (10-20, вероятно, должно сработать).

3) Создайте раскадровку, которая анимирует эти StaticResources.

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

РЕДАКТИРОВАТЬ - Примеры кодов

Например, добавьте некоторые ресурсы для анимации (это прямоугольники, поскольку вы не можете напрямую анимировать SolidColorBrush):

<Window.Resources>
        <Rectangle x:Key="Color0" Fill="#FFFFCFFF" />
        <Rectangle x:Key="Color1" Fill="#FFFFC2C2" />
        <Rectangle x:Key="Color2" Fill="#FFFFEFD2" />
        ...
</Window.Resources>

Ваш раскадровка будет выглядеть примерно так:

    <Storyboard x:Key="BackgroundAnimation" AutoReverse="True" RepeatBehavior="Forever">
        <ColorAnimationUsingKeyFrames Storyboard.Target="{StaticResource Color0}"
                                      Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                                      BeginTime="0:0:0:0"
                                      AutoReverse="True"
                                      Duration="00:00:03.00">
            <ColorKeyFrameCollection>
                <EasingColorKeyFrame Value="Transparent" />
            </ColorKeyFrameCollection>
        </ColorAnimationUsingKeyFrames>

     <!-- Add keyframes for each color, varying start and duration -->
      ...
</Storyboard>

В вашем коде, где вы генерируете все прямоугольники, вам необходимо привязать ресурсы. Итак, где-то в цикле вам нужно добавить:

 // I'll leave the implementation of GetRandomColorId to you
 resourceId = GetRandomColorId(MAX_COLORS);

 Shape source = (Shape)this.FindResource("Color" + resourceId);
                    Binding binding = new Binding
                                          {
                                              Path = new PropertyPath("Fill"),
                                              Source = source
                                          };

                    rect.SetBinding(Shape.FillProperty, binding);

Наконец, все, что вам нужно сделать, это запустить BackgroundAnimation.

0 голосов
/ 01 ноября 2011

Вы пробовали анимировать их в группах? Хотя у вас может быть более 1000 прямоугольников, возможно, вы можете разбить их на группы и одновременно запустить не более 10 анимаций. Если блоки расположены правильно, они все равно должны выглядеть как случайно анимированные прямоугольники.

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

0 голосов
/ 01 ноября 2011

Есть несколько вариантов:

а. Не используйте так много прямоугольников. Я знаю, что это очевидно, но серьезно, три тысячи предметов для анимации - это ОЧЕНЬ много даже для работоспособного станка.

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

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

// Disclaimer: This code was written in the SO text editor.  Might not be correct.
foreach (MyRect rect in MyRectangles)
{
  if (rect.FadingIn)
  {
    rect.Opacity += 0.1;
    if (rect.Opacity >= 1) { rect.FadingIn = false; }
  }
  else
  {
    rect.Opacity -= 0.1;
    if (rect.Opacity <= 0 ) { rect.FadingIn = true; }
  }
}

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

class MyRect
{
  public Shape Rectangle;
  public bool FadingIn;

  public double Opacity
  {
    get { return Rectangle.Opacity; }
    set { Rectangle.Opacity = value }
  }

  //... etc.
}

Конечно, есть еще некоторый код поддержки, который вам нужно будет разместить на месте, например, доставить свои прямоугольники к их хосту и т. Д., Но похоже, что вы уже проделали это самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...