Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > WPF и Silverlight > VisualBrush as animation frame


Автор: Freak_FB 13.12.2011, 22:08
От нечего делать и в порядке самообразования делаю хитрый стиль для ProgressBar по мотивам http://lurkmore.to/Nyan_Cat.

Пока что застопорился на том, что не могу использовать VisualBrush в качестве фрейма в анимации.
Есть две кисти, определяющие два фоновых рисунка:

Код

<VisualBrush x:Key="NyanWeavingStripesForeground" TileMode="Tile" AlignmentX="Left" ViewportUnits="Absolute">
    <VisualBrush.Viewport>
        <Rect X="0" Y="0" Width="50" Height="50" />
    </VisualBrush.Viewport>
    <VisualBrush.Visual>
        <Canvas Width="2" Height="25">
            <Rectangle Canvas.Left="0" Canvas.Top="0" Width="1" Height="4" Fill="Red" />
            <Rectangle Canvas.Left="0" Canvas.Top="4" Width="1" Height="4" Fill="Orange" />
            <Rectangle Canvas.Left="0" Canvas.Top="8" Width="1" Height="4" Fill="Yellow" />
            <Rectangle Canvas.Left="0" Canvas.Top="12" Width="1" Height="4" Fill="#FF33FF00" />
            <Rectangle Canvas.Left="0" Canvas.Top="16" Width="1" Height="4" Fill="#FF0099FF" />
            <Rectangle Canvas.Left="0" Canvas.Top="20" Width="1" Height="4" Fill="#FF6633FF" />

            <Rectangle Canvas.Left="1" Canvas.Top="1" Width="1" Height="4" Fill="Red" />
            <Rectangle Canvas.Left="1" Canvas.Top="5" Width="1" Height="4" Fill="Orange" />
            <Rectangle Canvas.Left="1" Canvas.Top="9" Width="1" Height="4" Fill="Yellow" />
            <Rectangle Canvas.Left="1" Canvas.Top="13" Width="1" Height="4" Fill="#FF33FF00" />
            <Rectangle Canvas.Left="1" Canvas.Top="17" Width="1" Height="4" Fill="#FF0099FF" />
            <Rectangle Canvas.Left="1" Canvas.Top="21" Width="1" Height="4" Fill="#FF6633FF" />
        </Canvas>
    </VisualBrush.Visual>
</VisualBrush>
<VisualBrush x:Key="NyanWeavingStripesForegroundAlt" TileMode="Tile" AlignmentX="Left" ViewportUnits="Absolute">
    <VisualBrush.Viewport>
        <Rect X="0" Y="0" Width="50" Height="50" />
    </VisualBrush.Viewport>
    <VisualBrush.Visual>
        <Canvas Width="2" Height="25">
            <Rectangle Canvas.Left="1" Canvas.Top="0" Width="1" Height="4" Fill="Red" />
            <Rectangle Canvas.Left="1" Canvas.Top="4" Width="1" Height="4" Fill="Orange" />
            <Rectangle Canvas.Left="1" Canvas.Top="8" Width="1" Height="4" Fill="Yellow" />
            <Rectangle Canvas.Left="1" Canvas.Top="12" Width="1" Height="4" Fill="#FF33FF00" />
            <Rectangle Canvas.Left="1" Canvas.Top="16" Width="1" Height="4" Fill="#FF0099FF" />
            <Rectangle Canvas.Left="1" Canvas.Top="20" Width="1" Height="4" Fill="#FF6633FF" />

            <Rectangle Canvas.Left="0" Canvas.Top="1" Width="1" Height="4" Fill="Red" />
            <Rectangle Canvas.Left="0" Canvas.Top="5" Width="1" Height="4" Fill="Orange" />
            <Rectangle Canvas.Left="0" Canvas.Top="9" Width="1" Height="4" Fill="Yellow" />
            <Rectangle Canvas.Left="0" Canvas.Top="13" Width="1" Height="4" Fill="#FF33FF00" />
            <Rectangle Canvas.Left="0" Canvas.Top="17" Width="1" Height="4" Fill="#FF0099FF" />
            <Rectangle Canvas.Left="0" Canvas.Top="21" Width="1" Height="4" Fill="#FF6633FF" />
        </Canvas>
    </VisualBrush.Visual>
</VisualBrush>


Затем, есть стиль для элемента Rectangle, который по триггеру (фактически - с самого начала) начнет анимировать эти два фоновых рисунка:

Код

<Style x:Key="WeavingStripesStyle" TargetType="Rectangle">
    <Style.Resources>
        <Storyboard x:Key="WeavingStripesAnimation">
            <ObjectAnimationUsingKeyFrames Duration="0:0:0.5" Storyboard.TargetProperty="Fill" RepeatBehavior="Forever">
                <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource NyanWeavingStripesForeground}" />
                <DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{StaticResource NyanWeavingStripesForegroundAlt}" />
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </Style.Resources>
    <Style.Triggers>
        <Trigger Property="IsVisible" Value="True">
            <Trigger.EnterActions>
                <BeginStoryboard x:Name="WeavingStripesStoryboard" Storyboard="{StaticResource WeavingStripesAnimation}" />
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <RemoveStoryboard BeginStoryboardName="WeavingStripesStoryboard" />
            </Trigger.ExitActions>
        </Trigger>
    </Style.Triggers>
</Style>


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

Код

<Rectangle Height="50" SnapsToDevicePixels="True" Style="{StaticResource WeavingStripesStyle}" />


Вылетает Exception где-то на этапе запуска:
Код

"Задание свойства "System.Windows.FrameworkElement.Style" вызвало исключение.": номер строки "237" и позиция в строке "14".
Не удается зафиксировать данное дерево шкалы времени Storyboard для использования в различных потоках.
(Cannot freeze this Storyboard timeline tree for use across threads)


Если использовать вместо VisualBrush SolidColorBrush - всё работает.
В чём может быть проблема?

Поправка 1: Похоже, проблема из за того что c VisualBrush нельзя сделать Freeze(). Может есть идеи как это обойти? Не очень хочется использовать битмапы.

Автор: Gvozdin 13.12.2011, 22:52
Ну тут дело в том что у VisualBrush хотят дернуть Freeze(), а это невозможно по самой сути VisualBrush.

Вот немного об этом:
http://social.msdn.microsoft.com/Forums/en/wpf/thread/0fef4b0f-feba-4412-bf77-d65aa65723bf

Вообще мне кажется что VisualBrush задумывался немного не для этого smile
Типа там отражение сделать для контрола, это вот для него, а рисовать через него таким образом это не то.

Если уж что-то рисуете на XAML, используйте Drawing и DrawingBrush.
Особенно я думаю хорошо будет использовать Expression Design.

Или уж если очень хочется рисовать через Rectangle, то можно в коде делать из них ImageBrush.

Если уж вы занимаетесь этим просто так для себя, вот может быть интересным и полезным smile
http://blogs.msdn.com/b/kaelr/archive/2008/06/18/snapshooter.aspx

Автор: Freak_FB 14.12.2011, 00:07
Да, DrawingBrush из головы вылетел совсем. Переписал с использованием его, двигаюсь дальше.
Спасибо за помощь  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)