主頁 > .NET開發 > 【WPF學習】第五十三章 影片型別回顧

【WPF學習】第五十三章 影片型別回顧

2020-09-10 18:03:06 .NET開發

  創建影片面臨的第一個挑戰是為影片選擇正確的屬性,期望的結果(例如,在視窗中移動元素)與需要使用的屬性(在這種情況下是Canvas.Left和Canvas.Top屬性)之間的關系并不總是很直觀,下面是一些指導原則:

  •   如果希望使用影片來使元素顯示和消失,不要使用Visibility屬性(該屬性只能在完全可見和完全不可見之間進行切換),應改用Opacity屬性淡入或淡出元素,
  •   如果希望動態改變元素的位置,可考慮使用Canvas面板,它提供了最直接的屬性(Canvas.Left及Canvas.Top),而且開銷最小,此外,也可使用影片屬性在其他布局容器中獲得類似效果,例如,可通過使用ThicknessAnimation類動態改變Margin和Padding等屬性,還可動態改變Grid控制元件中的MinWidth或MinHeight屬性、一列或一行,
  •   影片最常用的屬性是渲染變換,可使用變換移動或翻轉元素(TranslateTransform)、旋轉元素(RotateTransform)、縮放或扭曲元素(ScaleTransform)等,通過仔細地使用變換,有時可避免在影片中硬編碼尺寸和位置,它們也繞過了WPF布局系統,比直接作用于元素大小或位置的其他方法速度更快,
  •   動態改變元素表面的較好方法是修改畫刷屬性,可使用ColorAnimation改變顏色或其他影片物件來變換更復雜畫刷的屬性,如漸變中的偏移,

  接下來的示例演示了如何動態改變變換和畫刷,以及如何使用更多的一些影片型別,還將討論如何使用關鍵幀創建多段影片、如何創建基于路徑的影片和基于幀的影片,

一、動態變換

  變換提供了自定義元素的最強大方式之一,當使用變換時,不只是改變元素的邊界,而且會移動、翻轉、扭曲、拉伸、放大、縮小或旋轉元素的整個可視化外觀,例如,可通過ScaleTransform動態改變按鈕的尺寸,這會改變整個按鈕的尺寸,包括按鈕的邊框及其內部的內容,這種效果比動態改變Width和Height屬性或改變文本的Fontsize屬性給人的印象更深刻,

  前面章節了解到,每個元素都能以兩種不同的方式使用變換:RenderTransform屬性和LayoutTransform屬性,RenderTransform效率更高,因為是在布局之后應用變換并且勇于變換最終的渲染輸出,LayoutTransform在布局前應用,從而其他控制元件需要重新排列以適應變換,改變LayoutTransform屬性會引發新的布局操作(除非在Canvas面板上使用元素,在這種情況下,RenderTransform和LayoutTransform的效果相同),

  為在影片中使用變換,第一步是定義變換(影片可改變已經存在的變換,但不能創建新的變換),例如,假設希望使按鈕旋轉,此時需要使用RotateTransform物件:

<Button Content="A Button">
    <RenderTransform>
        <RotateTransform></RotateTransform>
    </RenderTransform>
</Button>

  現在當將滑鼠移動到按鈕上時,下面的事件觸發器就會旋轉按鈕,使用的目標屬性是RenderTransform.Angle——換句話說,讀取按鈕的RenderTransform屬性并修改其中定義的RotateTransform物件的Angle屬性,事實上,RenderTransform屬性可包含各種不同的變換物件,每種變換物件的屬性各不相同,這不會引起問題,只要使用的變換具有Angle屬性,這個觸發器就能作業:

<EventTrigger RoutedEvent="Button.MouseEnter">
    <EventTrigger.Actions>
          <BeginStoryboard Name="rotateStoryboardBegin">
               <Storyboard>
                     <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
                 To="360" Duration="0:0:0.8" RepeatBehavior="Forever"></DoubleAnimation>
                </Storyboard>
           </BeginStoryboard>
     </EventTrigger.Actions>
</EventTrigger>

  按鈕在0.8秒得時間內旋轉一周并且持續旋轉,當按鈕旋轉時仍完全可用——例如,可單擊按鈕并處理Click事件,

  為保證按鈕繞其中心旋轉(而不是繞左上角旋轉),需要按如下方式設定RenderTransformOrigin屬性:

<Button RenderTransformOrigin="0.5,0.5"/>

  請記住,RenderTransformOrigin屬性使用0~1的相對單位,所以0.5表示中點,

  為停止旋轉,可使用第二個觸發器回應MouseLeave事件,這是,可洗掉執行旋轉的故事板,但這會導致按鈕一步調回到它原來的位置,更好的方法是開始第二個影片,用它替代第一個影片,這個影片忽略To和From屬性,這意味著它無縫地再0.2秒得時間內將按鈕旋轉回原始方向:

<EventTrigger RoutedEvent="Button.MouseLeave">
    <EventTrigger.Actions>
         <BeginStoryboard>
              <Storyboard>
                  <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
                   Duration="0:0:0.2"></DoubleAnimation>
               </Storyboard>
          </BeginStoryboard>
    </EventTrigger.Actions>
</EventTrigger>

  為創建旋轉的按鈕,需要為Button.Triggers集合添加這兩個觸發器,或將它們(以及變換)放到一個樣式中,并根據需要為多個按鈕應用這個樣式,例如,下面的視窗標記充滿了下圖中顯示的“能旋轉的”按鈕:

<Window x:Class="Animation.RotateButton"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RotateButton" Height="300" Width="300">
    <Window.Resources>

        <Style TargetType="{x:Type Button}">
            <Setter Property="HorizontalAlignment" Value="Center"></Setter>
            <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
            <Setter Property="Padding" Value="20,15"></Setter>
            <Setter Property="Margin" Value="2"></Setter>
            <Setter Property="RenderTransform">
                <Setter.Value>
                    <RotateTransform></RotateTransform>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="Button.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard Name="rotateStoryboardBegin">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
                 To="360" Duration="0:0:0.8" RepeatBehavior="Forever"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="Button.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
                   Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
        </Style>

    </Window.Resources>
    <StackPanel Margin="5" Button.Click="cmd_Clicked">
        <Button>One</Button>
        <Button>Two</Button>
        <Button>Three</Button>
        <Button>Four</Button>
        <TextBlock Name="lbl" Margin="5"></TextBlock>
    </StackPanel>
</Window>
RotateButton

  在單擊任何按鈕時,都會在TextBlock元素中顯示一條資訊,

  這個示例還未分析渲染變換和布局變換之間的區別提供了絕佳的機會,如果修改代碼可使用LayoutTransform屬性,那么會發現當旋轉其中一個按鈕時,其他按鈕會被推離原來的位置,例如,如果旋轉最上面的按鈕,下面的按鈕會上下跳動以避開頂部的按鈕,

<Window x:Class="Animation.RotateButtonWithLayout"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RotateButtonWithLayout" Height="300" Width="300">
    <Window.Resources>

        <Style TargetType="{x:Type Button}">
            <Setter Property="HorizontalAlignment" Value="Center"></Setter>
            <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
            <Setter Property="Padding" Value="20,15"></Setter>
            <Setter Property="Margin" Value="2"></Setter>
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <RotateTransform></RotateTransform>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="Button.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard Name="rotateStoryboardBegin">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="LayoutTransform.Angle"
                 To="360" Duration="0:0:0.8" RepeatBehavior="Forever"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="Button.MouseLeave">
                    <EventTrigger.Actions>
                        <!-- <RemoveStoryboard BeginStoryboardName="rotateStoryboardBegin"></RemoveStoryboard> -->
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="LayoutTransform.Angle"
                   Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
        </Style>

    </Window.Resources>
    <StackPanel Margin="5" Button.Click="cmd_Clicked">
        <Button>One</Button>
        <Button>Two</Button>
        <Button>Three</Button>
        <Button>Four</Button>
        <TextBlock Name="lbl" Margin="5"></TextBlock>
    </StackPanel>
</Window>
RotateButtonWithLayout

  動態改變多個變換

  可很容易地組合使用變換,實際上這是很容易——只需要使用TransformGroup物件設定LayoutTransform或RenderTransform屬性即可,可根據需要在TransformGroup物件中嵌套任意多個變換,

  下圖顯示了一個使用兩個變換創建的有趣效果,檔案視窗剛開始作為主視窗左上角的小縮略圖,當檔案視窗顯示時,內容旋轉、擴展并快速淡入到試圖中,從概念上講,這與最大化視窗時Windows使用的效果類似,在WPF中,可通過變換為所有的元素應用這種技巧,

  為創建這種效果,在如下TransformGroup物件中定義了兩個變換,并使用TransformGroup物件設定包含所有內容的Board物件的RenderTransform屬性:

<Border.RenderTransform>
     <TransformGroup>
           <ScaleTransform></ScaleTransform>
            <RotateTransform></RotateTransform>
      </TransformGroup>
</Border.RenderTransform>

  通過指定數字偏移值(0用于首先顯示的ScaleTransform物件,1用于接下來顯示的RotateTransform物件),影片可與這兩個變換物件進行互動,例如,下面的影片放大內容:

<DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
                                From="0" To="1" Duration="0:0:2" AccelerationRatio="1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
                                From="0" To="1" Duration="0:0:2" AccelerationRatio="1"></DoubleAnimation>

  下面的影片位于相同的故事板中,用于旋轉內容:

<DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
                                From="70" To="0" Duration="0:0:2" ></DoubleAnimation>

  這個影片中的內容比此處顯示的內容還多,例如,還有一個同事增加Opacity屬性的影片,并且當Borad元素達到最大尺寸時,它短暫地向后"反彈"一下,創建一種更趨自然的效果,為這個影片創建時間線并修改各個影片物件屬性需要耗費時間——理想情況下,可使用諸如Expression Blend的設計工具執行這些任務,而不是通過手動撰寫代碼來完成這些任務,甚至更好的情況下,只要有第三方開發者將這一邏輯分組到自定義影片中,就可以重用并根據需要將其應用到物件上(根據目前的情況,可通過將Storyboard物件存盤為應用程式級的資源,重用這個影片),

  下面是完整的XAML標記:

<Window x:Class="Animation.ExpandElement"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpandElement" Height="423.2" Width="488.8" WindowStartupLocation="CenterScreen">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard SpeedRatio="1.5">
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="Opacity"
                                From="0.2" To="1" Duration="0:0:2.5"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
                                From="70" To="0" Duration="0:0:2" ></DoubleAnimation>

                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
                                From="0" To="1" Duration="0:0:2" AccelerationRatio="1"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
                                From="0" To="1" Duration="0:0:2" AccelerationRatio="1"></DoubleAnimation>

                        <DoubleAnimation Storyboard.TargetName="element"
                                            Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
                                            To="0.98" BeginTime="0:0:2" Duration="0:0:0.05"  DecelerationRatio="1"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
                                To="0.98" BeginTime="0:0:2" Duration="0:0:0.05" DecelerationRatio="1"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                            Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
                                            To="1" BeginTime="0:0:2.05" Duration="0:0:0.2"  AccelerationRatio="1"></DoubleAnimation>
                        <DoubleAnimation Storyboard.TargetName="element"
                                Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
                                To="1" BeginTime="0:0:2.05" Duration="0:0:0.2" AccelerationRatio="1"></DoubleAnimation>

                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Window.Triggers>

    <Grid>
        <!--<Button Name="element">
        <Button.Content>Text</Button.Content>
        <Button.RenderTransform>
          <TransformGroup>
            <ScaleTransform ScaleX="0" ScaleY="0"></ScaleTransform>
            <TranslateTransform></TranslateTransform>
            <RotateTransform Angle="90"></RotateTransform>
          </TransformGroup>
        </Button.RenderTransform>
      </Button>-->
        <Border  Name="element" Margin="3" Background="LightGoldenrodYellow"
               BorderBrush="DarkBlue" BorderThickness="2" CornerRadius="5" >
            <Border.RenderTransform>
                <TransformGroup>
                    <ScaleTransform></ScaleTransform>
                    <RotateTransform></RotateTransform>
                </TransformGroup>
            </Border.RenderTransform>
            <FlowDocumentScrollViewer IsToolBarVisible="True">
                <FlowDocument>

                    <Paragraph xml:space="preserve">The <Italic>foof</Italic> feature is indispensable. You can configure the foof feature using the Foof Options dialog box.</Paragraph>
                    <BlockUIContainer>
                        <Button HorizontalAlignment="Left" Padding="5">Open Foof Options</Button>
                    </BlockUIContainer>


                    <Paragraph FontSize="20pt">Largest Cities in the Year 100</Paragraph>
                    <Table>
                        <Table.Columns>
                            <TableColumn Width="*"></TableColumn>
                            <TableColumn Width="3*"></TableColumn>
                            <TableColumn Width="*"></TableColumn>
                        </Table.Columns>

                        <TableRowGroup  >
                            <TableRow FontWeight="Bold" >
                                <TableCell >
                                    <Paragraph>Rank</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Name</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Population</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>1</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Rome</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>450,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>2</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Luoyang (Honan), China</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>420,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>3</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Seleucia (on the Tigris), Iraq</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>250,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>4</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Alexandria, Egypt</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>250,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>5</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Antioch, Turkey</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>150,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>6</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Anuradhapura, Sri Lanka</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>130,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>7</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Peshawar, Pakistan</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>120,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>8</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Carthage, Tunisia</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>100,000</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>9</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Suzhou, China</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>n/a</Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell>
                                    <Paragraph>10</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>Smyrna, Turkey</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph>90,000</Paragraph>
                                </TableCell>
                            </TableRow>
                        </TableRowGroup>
                    </Table>
                </FlowDocument>
            </FlowDocumentScrollViewer>
        </Border>

    </Grid>

</Window>
ExpandElement

  這種效果非常有用,例如,可使用該效果將注意力吸引到新的內容——例如用戶剛剛打開的檔案,這種效果可能的變化是無窮無盡的,例如,創建產品目錄時,當用戶將滑鼠懸停在相應的產品名稱上時,滑入包含產品細節的面板或將產品影像滾入試圖,

二、動態改變畫刷

  動態改變畫刷是WPF影片中的另一種常用技術,和動態變換同樣容易,同樣,這種技術使用恰當的影片型別,深入到希望改變的特定子屬性,

  下圖顯示了一個修改RadialGradientBrush畫刷的示例,當影片運行時,徑向漸變的中心點沿橢圓漂移,從而實作了一種三維效果,同時,外側的漸變顏色從藍色變成黑色,

  為實作這個效果,需要使用兩種尚未分析過的影片型別,ColorAnimation影片在兩個顏色之間逐漸混合,創建一種微妙的顏色轉移效果,PointAnimation影片可將點從一個位置移到另一個位置(本質上與使用獨立DoubleAnimation,通過線性插值同時修改X坐標和Y坐標是相同的),可使用PointAnimation影片改變使用點構造的圖形,或者就像這個示例中那樣,改變徑向漸變中心點的位置,

  下面是標記定義了橢圓及其畫刷:

<Ellipse Name="ellipse" Margin="5" Grid.Row="1" Stretch="Uniform">
   <Ellipse.Fill>
         <RadialGradientBrush
             RadiusX="1" RadiusY="1" GradientOrigin="0.7,0.3">
                    <GradientStop Color="White" Offset="0" ></GradientStop>
                    <GradientStop Color="Blue" Offset="1" ></GradientStop>
          </RadialGradientBrush>

   </Ellipse.Fill>
</Ellipse>

  下面是移動中心點以及改變第二種顏色的兩個影片:

<PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse" Storyboard.TargetProperty="Fill.GradientOrigin"
                                           RepeatBehavior="Forever">
                        <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:0"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.3,0.7" KeyTime="0:0:5"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.5,0.9" KeyTime="0:0:8"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.9,0.6" KeyTime="0:0:10"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.8,0.2" KeyTime="0:0:12"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:14"></LinearPointKeyFrame>

                        <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:20"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.3,0.7" KeyTime="0:0:25"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.5,0.9" KeyTime="0:0:28"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.9,0.6" KeyTime="0:0:20"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.8,0.2" KeyTime="0:0:22"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:24"></DiscretePointKeyFrame>
                    </PointAnimationUsingKeyFrames>


                    <ColorAnimation Storyboard.TargetName="ellipse" Storyboard.TargetProperty="Fill.GradientStops[1].Color"
              To="Black"  Duration="0:0:10"
              AutoReverse="True" RepeatBehavior="Forever"></ColorAnimation>

  本例網站XAML標記:

<Window x:Class="Animation.AnimateRadialGradient"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="AnimateRadialGradient" Height="300" Width="300" WindowStartupLocation="CenterScreen">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse" Storyboard.TargetProperty="Fill.GradientOrigin"
                                           RepeatBehavior="Forever">
                        <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:0"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.3,0.7" KeyTime="0:0:5"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.5,0.9" KeyTime="0:0:8"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.9,0.6" KeyTime="0:0:10"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.8,0.2" KeyTime="0:0:12"></LinearPointKeyFrame>
                        <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:14"></LinearPointKeyFrame>

                        <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:20"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.3,0.7" KeyTime="0:0:25"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.5,0.9" KeyTime="0:0:28"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.9,0.6" KeyTime="0:0:20"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.8,0.2" KeyTime="0:0:22"></DiscretePointKeyFrame>
                        <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:24"></DiscretePointKeyFrame>
                    </PointAnimationUsingKeyFrames>


                    <ColorAnimation Storyboard.TargetName="ellipse" Storyboard.TargetProperty="Fill.GradientStops[1].Color"
              To="Black"  Duration="0:0:10"
              AutoReverse="True" RepeatBehavior="Forever"></ColorAnimation>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <Ellipse Name="ellipse" Margin="5" Grid.Row="1" Stretch="Uniform">
            <Ellipse.Fill>
                <RadialGradientBrush
             RadiusX="1" RadiusY="1" GradientOrigin="0.7,0.3">
                    <GradientStop Color="White" Offset="0" ></GradientStop>
                    <GradientStop Color="Blue" Offset="1" ></GradientStop>
                </RadialGradientBrush>

            </Ellipse.Fill>
        </Ellipse>
    </Grid>
</Window>
AnimateRadialGradient

  通過修改LinearGradientBrush和RadialGradientBrush畫刷的顏色和偏移值可創建許多精彩效果,如果還不夠,漸變畫刷還有自己的RelativeTransform屬性,可使用該屬性旋轉、縮放、拉伸以及扭曲畫刷,WPF團隊有一個有趣的稱為Gradient Obsession的工具,該工具用于構建基于漸變的影片,

  VisualBrush畫刷

  VisualBrush畫刷可獲取任意元素的外觀,使用該外觀可填充另一個表面,其他表面可以是任何內容,從普遍的矩形到文本框中的字母,

  下圖顯示了一個基本示例,頂部是一個真實的活動按鈕,下面通過VisualBrush畫刷使用按鈕圖片填充一個矩形,并通過各種變換效果拉伸并旋轉按鈕圖片,

  VisualBrush畫刷還為實作一些有趣的影片效果的影片效果提供了可能,例如,不僅可動態顯示活動的真實元素,還可動態顯示具有相同填充內容的簡單矩形,

  為理解這種方法的作業原理,分析這個示例,該例將一個元素放入試圖中,當這個影片運行時,處理具有影片的元素的方法和處理其他任意WPF元素的方式相同,這意味著可單擊它內部的按鈕,或使用鍵盤滾動內容(如果用戶的操作足夠迅速的話),在一些情況下,這可能會令用戶感到困惑,在由寫情況下,這可能導致性能下降,因為需要額外的開銷來變換輸入(如滑鼠單擊),并且和原始元素一起傳遞輸入,

  使用VisualBrush畫刷可輕易地代替這種效果,首先,需要創建另一個元素,使用VisualBrush畫刷填充該元素,VisualBrush畫刷必須根據希望包含影片的元素(在這個示例中,是名為visual的邊框)繪制可視化內容,

<Rectangle Grid.Row="1" Name="rectangle" Width="100" Stretch="Uniform" ClipToBounds="False" RenderTransformOrigin="0.5,0.5">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=visual}">

                </VisualBrush>
            </Rectangle.Fill>
            <Rectangle.RenderTransform>

                <TransformGroup>
                    <SkewTransform CenterX="0.5"></SkewTransform>
                    <RotateTransform CenterX="0.5" CenterY="0.5"></RotateTransform>
                </TransformGroup>

            </Rectangle.RenderTransform>
        </Rectangle>

  示例完整XAML標記:

<Window x:Class="Animation.AnimateVisual"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="AnimateVisual" Height="300" Width="300" Background="LightGoldenrodYellow" WindowStartupLocation="CenterScreen">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Button Name="visual" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button.Content>Test</Button.Content>
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard  RepeatBehavior="Forever">
                            <DoubleAnimation Storyboard.TargetName="rectangle"
                                 Storyboard.TargetProperty="RenderTransform.Children[0].AngleY"
                                 To="180" Duration="0:0:15" AutoReverse="True"></DoubleAnimation>
                            <DoubleAnimation Storyboard.TargetName="rectangle"
                                 Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
                                 To="180" Duration="0:0:20" AutoReverse="True"></DoubleAnimation>
                            <DoubleAnimation Storyboard.TargetName="rectangle"
                                 Storyboard.TargetProperty="Opacity"
                                 To="0.1" Duration="0:0:4" AutoReverse="True"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>

        <Rectangle Grid.Row="1" Name="rectangle" Width="100" Stretch="Uniform" ClipToBounds="False" RenderTransformOrigin="0.5,0.5">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=visual}">

                </VisualBrush>
            </Rectangle.Fill>
            <Rectangle.RenderTransform>

                <TransformGroup>
                    <SkewTransform CenterX="0.5"></SkewTransform>
                    <RotateTransform CenterX="0.5" CenterY="0.5"></RotateTransform>
                </TransformGroup>

            </Rectangle.RenderTransform>
        </Rectangle>
    </Grid>
</Window>
AnimateVisual

  為將矩形放到與原始元素相同的位置,可將它們同時放到Grid面板的同一個單元格中,改變單元格的尺寸,使其適合原始元素(邊框),并拉伸矩形使其相匹配,另一個選擇是在真實實用程式上覆寫Canvas面板(然后可將影片屬性系結到下面真實元素的ActualWidth和ActualHeight屬性,從而確保對齊),

  添加矩形后,只需要調整影片來執行動態變化,最后,當影片完成時隱藏矩形:

private void storyboardCompleted(object sender,EventArgs e)
{
    rectangle.Visibility=Visibility.Collapsed;
}

三、動態改變像素著色器

  通過“【WPF學習】第四十六章 效果 ”的學習,了解了像素著色器(可為任意元素應用位圖風格效果的低級例程,如模糊、輝光以及彎曲效果)的相關內容,就自身而言,像素著色器是一些有趣并且偶爾有用的工具,但通過結合使用影片,他們可變的更通用,可使用它們設計吸引眼球的過渡效果(例如,通過模糊控制元件使其淡出、隱藏,然后模糊另一個控制元件使其淡入),也可使用像素著色器創建給人留下深刻印象的用戶互動效果(例如,當用戶將滑鼠移動到按鈕上時增加按鈕上的輝光),最后為像素著色器的屬性應用影片,就像為其他內容應用影片一樣容易,

  下圖顯示的頁面是基于在前面給出的旋轉按鈕示例構建的,該例包含一系列按鈕,并且當用戶將滑鼠移動到其中某個按鈕上時,關聯并開始影片,區別在于這個示例中的影片不是旋轉按鈕,而將模糊半徑減少至0,結果是移動滑鼠時,最近的按鈕驟然輕快地變得清晰,

  該例的代碼和旋轉按鈕示例中的代碼相同,需要為每個按鈕提供BlurEffect物件而不是RotateTransform物件:

<Setter Property="Effect">
     <Setter.Value>
            <BlurEffect Radius="10"></BlurEffect>
     </Setter.Value>
</Setter>

  還需要相應地修改影片:

 <EventTrigger RoutedEvent="Button.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Effect.Radius"
         To="0" Duration="0:0:0.4"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

                <EventTrigger RoutedEvent="Button.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Effect.Radius" To="10"
        Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

  本實體完整XAML標記:

<Window x:Class="Animation.BlurringButtons"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="BlurringButtons" Height="300" Width="300" WindowStartupLocation="CenterScreen">
    <Window.Resources>

        <Style TargetType="{x:Type Button}">
            <Setter Property="HorizontalAlignment" Value="Center"></Setter>
            <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
            <Setter Property="Padding" Value="20,15"></Setter>
            <Setter Property="Margin" Value="2"></Setter>
            <Setter Property="Effect">
                <Setter.Value>
                    <BlurEffect Radius="10"></BlurEffect>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="Button.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Effect.Radius"
         To="0" Duration="0:0:0.4"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

                <EventTrigger RoutedEvent="Button.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Effect.Radius" To="10"
        Duration="0:0:0.2"></DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>

            </Style.Triggers>
        </Style>

    </Window.Resources>
    <StackPanel Margin="5">
        <Button>One</Button>
        <Button>Two</Button>
        <Button>Three</Button>
        <Button>Four</Button>
        <TextBlock Name="lbl" Margin="5"></TextBlock>
    </StackPanel>
</Window>
BlurringButtons

  為反向使用相同的方法來突出顯示按鈕,例如,可使用應用輝光效果的像素著色器突出顯示滑鼠在其上懸停的按鈕,

  

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/2974.html

標籤:WPF

上一篇:【WPF學習】第五十二章 影片性能

下一篇:WPF的一種動態切語言方法

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more