《深刻淺出WPF》學習筆記之繪圖和動畫

繪圖

經過WPF繪製的圖形都是矢量圖,能夠經過Design或Blend工具繪製原型圖而後導出XAML再在Visual Studio中調整。繪圖能夠在任意佈局控件中完成,經常使用的爲Canvas和Grid,WPF會自動根據容器的不一樣計算圖形座標。WPF基本圖像都繼承自Shape類。工具

Line,繪製直線,經過設置起始點座標和終止點座標肯定直線的位置,能夠設置直線的樣式,顏色,粗細等。經過設置Stroke屬性設置圖形的顏色,Stroke屬性爲Brush類型,Brush爲抽象類。WPF系統包含豐富的Brush子類,SolidColorBrush,LinearGradientBrush(線性漸變畫刷),RadialGradientBrush(徑向漸變畫刷),ImageBrush(圖像填充),DrawingBrush(使用矢量圖和位圖做爲填充),VisualBrush,使用可視化元素填充,能夠當作可視化元素的截圖。佈局

Rectangle,繪製矩形,能夠設置邊框顏色,邊框大小和填充,填充Fill同Stroke同樣也爲Brush類型。性能

Ellipse,繪製橢圓,使用方法與矩形沒有什麼區別,當width和height相同時即爲正圓。動畫

Path,路徑是WPF繪圖中最強大的工具,它便可以替代其餘幾種圖形,也能夠造成更復雜的圖形。路徑的重要屬性是Data,經過設置Data來肯定具體的圖形。Data的類型爲Geometry,同Brush同樣,Geometry爲抽象類,WPF已經準備了若干繼承類,包括LineGeometry,RectangleGeometry,EllipseGeometry,PathGeometry,StreamGeometry(輕量級PathGeometry),CombinedGeometry,GeometryGroup。Geometry類與Shape類不一樣,Geometry不能做爲單獨元素使用,只能依附在其餘圖形上。PathGeometry能夠繪製複雜的幾何圖形,其Figures能夠容納多個PathFigure對象,而PathFigure的Segments屬性能夠容納多個PathSegment對象,經過PathSegment組合成複雜圖形。一樣的PathSegment爲抽象類,繼承類包括LineSegment,ArcSegment,BezierSegment,QuadraticBezierSegment,PolyBezierSegment,PolyQuadraticBezierSegment。全部這些Segment都沒有起點,起點就是上一個Segment的終點,第一個Segment的起點爲PathFigure的StartPoint。Path的示例代碼:this

        <Path Stroke="Blue">
            <Path.Data>
                <PathGeometry>
                    <PathFigure StartPoint="0,0">
                        <LineSegment Point="0,10"></LineSegment>
                        <LineSegment Point="10,50"></LineSegment>
                        <LineSegment Point="20,40"></LineSegment>
                        <ArcSegment Point="40,80" Size="25,50"></ArcSegment>
                        <BezierSegment Point1="20,20" Point2="30,30" Point3="40,40"></BezierSegment>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>

GeometryGroup也是Geometry的一個繼承類,它最大的特色是能夠將一組Geometry組合到一塊兒。spa

路徑標記語法

Path如此強大,可使咱們爲所欲爲的繪製圖形,但其缺點也不容忽視,就是其標籤語法國語繁瑣,若是圖形過於複雜則會生成大量標籤。經過使用路徑標記語法能夠極大的簡化Path的描述,路徑標記語法實際上就是各類線段的簡記法,好比<LineSegment Point="10,50"></LineSegment>能夠簡記爲L 10,50。使用路徑標記語法通常分三步:移動至起點,繪圖,閉合圖形。路徑標記語法不區分大小寫,使用兩個double表示一個點,中間用逗號或空格分隔,爲避免混淆,常使用逗號分隔。插件

能夠經過設置UIElement的Clip屬性對控件進行裁剪,Clip類型即爲Geometry。code

圖形的效果與濾鏡

UIElement中BitmapEffect和Effect的兩個屬性用來給元素添加效果,BitmapEffect使用CPU計算資源,如今已經被遺棄。Effect屬性使用GPU資源。BitmapEffect簡單易用,它的類型爲BitmapEffect類,是一個抽象類,WPF爲咱們實現了若干子類,經過設置這些子類的屬性來調整效果。示例代碼:orm

        <Button Width="120" Height="30">
            <Button.BitmapEffect>
                <DropShadowBitmapEffect ShadowDepth="5" Opacity="0.7" Direction="-45"></DropShadowBitmapEffect>
            </Button.BitmapEffect>
        </Button>

Effect屬性的類型爲Effect,一樣爲抽象類,WPF爲咱們實現了3個子類,BlurEffect,用來實現模糊效果。DropShadowEffect,用來實現投影效果。ShaderEffect,着色器效果,抽象類,它是留給濾鏡插件開發人員的抽象接口。對象

元素的變形

控制變形的屬性有兩個RenderTransform和LayoutTransform,他們的數據類型都是Transform抽象類。Transform抽象類的派生類有以下一些,MatrixTransform,RotateTransform,ScaleTransform,SkewTransform,TranslateTransform,TransformGroup。呈現變形(RenderTransform)只改變元素的呈現位置,不會對佈局系統形成影響,以減小資源佔用,當使用動畫時必定要使用呈現變形。注意控件呈如今哪裏就在哪裏提供交互。示例代碼:

        <Button Width="120" Height="30" Click="Button_Click">
            <Button.RenderTransform>
                <TranslateTransform X="50" Y="50"></TranslateTransform>
            </Button.RenderTransform>
        </Button>

 

佈局變形(LayoutTransform)會影響窗體的佈局,致使佈局從新計算,這會影響程序性能,所以佈局變形只用在靜態變形上,不會用於動畫。

動畫

能夠用來製做動畫的屬性必定是依賴屬性,動畫的基類爲Timeline。簡單動畫由一個元素就能夠完成,簡單動畫使用AnimationTimeline實現。複雜動畫由多個元素和多個動畫協同完成,複雜動畫使用StoryBoard實現。

經過AnimationTimeline能夠針對一個UI元素實現簡單動畫,AnimationTimeline爲抽象類,WPF動畫系統實現了經常使用數據類型的子類,如DoubleAnimationBase、ByteAnimationBase等。這種數據類型並以Base作後綴的類爲抽象基類,每種數據類型的抽象基類又派生出3種具體動畫,分別爲簡單動畫、關鍵幀動畫、沿路徑運動的動畫。注意並非全部的數據類型都能派生出這3種類型的動畫。DoubleAnimationBase派生出DoubleAnimation(簡單動畫),DoubleAnimationUsingKeyFrames(關鍵幀動畫),DoubleAnimationUsingPath(沿路徑運動動畫)。簡單動畫由變化時間Duration、變化起點From、變化幅度By、變化終點To四要素構成,若是同時設置To和By,By將被忽略。示例代碼:

        <Button x:Name="button" Width="120" Height="30" Click="Button_Click">
            <Button.BitmapEffect>
                <DropShadowBitmapEffect ShadowDepth="5" Opacity="0.7" Direction="-45"></DropShadowBitmapEffect>
            </Button.BitmapEffect>
            <Button.RenderTransform>
                <TranslateTransform X="0" Y="0"></TranslateTransform>
            </Button.RenderTransform>
        </Button>

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation dax = new DoubleAnimation();
            DoubleAnimation day = new DoubleAnimation();
            dax.From = 0;
            day.From = 0;

            dax.By = 100;
            day.By = 100;

            dax.Duration = new Duration(TimeSpan.FromMilliseconds(500));
            day.Duration = new Duration(TimeSpan.FromMilliseconds(500));

            button.RenderTransform.BeginAnimation(TranslateTransform.XProperty, dax);
            button.RenderTransform.BeginAnimation(TranslateTransform.YProperty, day);
        }

經過設置動畫的高級控制屬性能夠是動畫效果更逼真,如設置加速度、減速度、循環模式,漸進式緩衝等。

關鍵幀動畫

 經過定義關鍵幀控制動畫的執行效果,每一個幀都包含幀所在的時間和值,關鍵幀動畫至少包含一個幀做爲動畫的結束位置。關鍵幀動畫包含KeyFrames屬性用來包含關鍵幀,能夠向其中添加不一樣類型的關鍵幀,最簡單的關鍵幀爲LinearDoubleKeyFrame。示例代碼:

        <Button x:Name="button" Width="120" Click="button_Click" HorizontalAlignment="Left">
            <Button.RenderTransform>
                <TranslateTransform X="0" Y="0"></TranslateTransform>
            </Button.RenderTransform>
            Button</Button>


        private void button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimationUsingKeyFrames dakf = new DoubleAnimationUsingKeyFrames();
            dakf.Duration = new Duration(TimeSpan.FromSeconds(1));
            

            LinearDoubleKeyFrame kf1 = new LinearDoubleKeyFrame();
            kf1.KeyTime = KeyTime.FromPercent(0.2);
            kf1.Value = 50;

            LinearDoubleKeyFrame kf2 = new LinearDoubleKeyFrame();
            kf2.KeyTime = KeyTime.FromPercent(0.4);
            kf2.Value = 100;

            LinearDoubleKeyFrame kf3 = new LinearDoubleKeyFrame();
            kf3.KeyTime = KeyTime.FromPercent(0.8);
            kf3.Value = 150;

            dakf.KeyFrames.Add(kf1);
            dakf.KeyFrames.Add(kf2);
            dakf.KeyFrames.Add(kf3);


            button.RenderTransform.BeginAnimation(TranslateTransform.XProperty, dakf);
        }

路徑動畫

控制動畫沿指定路徑移動,路徑動畫的Source屬性用來控制關注路徑的X軸的變化仍是Y軸的變化仍是曲線切線方向變化。示例代碼:

    <Grid x:Name="layoutRoot">
        <Grid.Resources>
            <PathGeometry x:Key="path" Figures="M 0,150 C300,-100 300,400 600,120"></PathGeometry>
        </Grid.Resources>
        <Button x:Name="button" HorizontalAlignment="Left" VerticalAlignment="Top" Height="20" Click="button_Click">
            <Button.RenderTransform>
                <TranslateTransform X="0" Y="0"></TranslateTransform>
            </Button.RenderTransform>
            Button</Button>
    </Grid>


        private void button_Click(object sender, RoutedEventArgs e)
        {
            PathGeometry path = layoutRoot.FindResource("path") as PathGeometry;
            DoubleAnimationUsingPath daupx = new DoubleAnimationUsingPath();
            DoubleAnimationUsingPath daupy = new DoubleAnimationUsingPath();

            daupx.Duration = new Duration(TimeSpan.FromSeconds(1));
            daupx.PathGeometry = path;
            daupx.Source = PathAnimationSource.X;


            daupy.Duration = new Duration(TimeSpan.FromSeconds(1));
            daupy.PathGeometry = path;
            daupy.Source = PathAnimationSource.Y;


            button.RenderTransform.BeginAnimation(TranslateTransform.XProperty, daupx);
            button.RenderTransform.BeginAnimation(TranslateTransform.YProperty, daupy);
        }

場景(Storyboard)

場景就是並行執行的一組動畫,XAML代碼示例:

    <Grid>
        <Button VerticalAlignment="Top" HorizontalAlignment="Left">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="0" Y="0"></TranslateTransform>
            </Button.RenderTransform>
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Loaded">
                    <BeginStoryboard>
                        <Storyboard Duration="0:0:1">
                            <DoubleAnimation Duration="0:0:1" To="200" Storyboard.TargetName="tt" Storyboard.TargetProperty="X"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
            Button</Button>
    </Grid>

C#代碼示例:

    <Grid>
        <Button VerticalAlignment="Top" HorizontalAlignment="Left" Click="Button_Click">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="0" Y="0"></TranslateTransform>
            </Button.RenderTransform>

            Button</Button>
    </Grid>


        private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation da = new DoubleAnimation();
            da.To = 200;
            da.Duration = new Duration(TimeSpan.FromSeconds(1));

            Storyboard sb = new Storyboard();
            sb.Duration = new Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTargetName(da, "tt");
            Storyboard.SetTargetProperty(da, new PropertyPath(TranslateTransform.XProperty));

            sb.Children.Add(da);
            sb.RepeatBehavior = RepeatBehavior.Forever;
            sb.Begin(this);
        }
相關文章
相關標籤/搜索