WPF 簡易的噴泉效果


這兩天領導讓我做個噴泉的效果,要把一個個UserControl從一個位置噴出,然后,最后落在最終需要在的位置。

噴泉效果說白了,就是兩個步驟:1、放大,從0放大到需要的倍數;2、縮小,平移,從放大的倍數還原到UserControl的原始大小,並且定位到最終的位置。

雖然,只有兩步,但是,作為寫動畫的新手,還是有點費事的,所以,采用了先用Blend設計,然后再轉換為C#代碼的過程。

一、Blend設計單個UserControl的放大和移動效果

1、在Blend里,新建個項目,然后,在Grid下,放個Canvas,在Canvas下放個Image(先拿Image來設計)

2、在Blend左側的時間線,選中image控件,然后點擊上面的+號,會彈出新增動畫資源的彈窗,點擊確定。

3、根據需要,拖拽左側的時間線(黃線)到對應位置,然后,對紅框中的Image控件,進行放大、縮小、位置調整等操作。

4、XAML部分,產生了相應的代碼

<Window.Resources>
        <Storyboard x:Key="StoryboardFountain">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="image">
                <EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:5" Value="5"/>
                <EasingDoubleKeyFrame KeyTime="0:0:10" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="image">
                <EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:5" Value="5"/>
                <EasingDoubleKeyFrame KeyTime="0:0:10" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="image">
                <EasingDoubleKeyFrame KeyTime="0:0:5" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:10" Value="-186.5"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="image">
                <EasingDoubleKeyFrame KeyTime="0:0:5" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:10" Value="-107"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="Storyboard1"/>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard Storyboard="{StaticResource StoryboardFountain}"/>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <Canvas HorizontalAlignment="Center" VerticalAlignment="Center">
            <Image x:Name="image" Source="C:\Users\dell\Pictures\WP_20160112_18_55_33_Raw_LI.jpg" Width="50" Height="50" Canvas.Left="-0.5" Canvas.Top="-0.5" RenderTransformOrigin="0.5,0.5">
                <Image.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Image.RenderTransform>
            </Image>
        </Canvas>
    </Grid>

 

二、把XAML代碼轉換為C#

有了XAML代碼,轉換成C#代碼,就方便多了,只要把對應的部分相關轉換,然后啟動動畫,就OK了

TransformGroup部分轉換為如下的方式

if (uc.RenderTransform as TransformGroup == null)
{
    TransformGroup tg = new TransformGroup();
    uc.RenderTransform = tg;
    tg.Children.Add(new ScaleTransform());
    tg.Children.Add(new TranslateTransform());
}

由於,實際上只用到了ScaleTransform和TranslateTransform,所以,就只寫了兩個

 DoubleAnimationUsingKeyFrames部分轉換為如下的方式

EasingDoubleKeyFrame edf1 = new EasingDoubleKeyFrame(Init, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(i + first_value)));
EasingDoubleKeyFrame edf2 = new EasingDoubleKeyFrame(Mul, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(i + middle_value)));
EasingDoubleKeyFrame edf3 = new EasingDoubleKeyFrame(Org, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(i + end_value)));

DoubleAnimationUsingKeyFrames daukf1 = new DoubleAnimationUsingKeyFrames();
daukf1.KeyFrames.Add(edf1);
daukf1.KeyFrames.Add(edf2);
daukf1.KeyFrames.Add(edf3);
storyboard.Children.Add(daukf1);
Storyboard.SetTarget(daukf1, uc);
Storyboard.SetTargetProperty(daukf1, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));

 對比過XAML代碼和C#代碼以后,就發現,其實XAML轉C#,還是沒有那么困難的,就是把相應的位置進行相關的添加值,可以直接從XAML里復制過來,如(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX),誰能記得住呢,反正我記不住,太笨了。

寫好了一個UserControl的效果以后,多個的實現起來,就容易了,無外乎就是for循環,設置參數而已。

定義一個UCShow的類,里面包含了UC和最后要定位的位置,如下,將需要展示的集合,都添加到一個List里就ok了。

public class UcShow
{
    private UIElement uc;
    private double top;
    private double left;

    public UIElement Uc
    {
        get
        {
            return uc;
        }

        set
        {
            uc = value;
        }
    }

    public double Top
    {
        get
        {
            return top;
        }

        set
        {
            top = value;
        }
    }

    public double Left
    {
        get
        {
            return left;
        }

        set
        {
            left = value;
        }
    }
}

效果如下:

 

噴泉效果的代碼如下:

class Fountain
{
    /// <summary>
    /// 噴泉效果
    /// </summary>
    /// <param name="cav">畫布</param>
    /// <param name="uclist">展示集合</param>
    /// <param name="pL">噴出點左</param>
    /// <param name="pT">噴出點上</param>
    /// <param name="Mul">放大倍數</param>
    /// <param name="middle_value">放大時間點</param>
    /// <param name="end_value">還原時間點</param>
    public void FountainAnimation(Canvas cav,List<UcShow> uclist, double pL = 0, double pT = 0, double Mul = 10, double middle_value = 0.5, double end_value = 1)
    {
        if (uclist.Count <= 0)
        {
            return;
        }
        Storyboard storyboard = new Storyboard();

        double Init = 0;
        double Org = 1;
        double first_value = 0;

        for (int i = 0; i < uclist.Count; i++)
        {
            UIElement uc = uclist[i].Uc;
            double Top = uclist[i].Top;
            double Left = uclist[i].Left;
            Canvas.SetLeft(uc, pL);
            Canvas.SetTop(uc, pT);
            if (uc.RenderTransform as TransformGroup == null)
            {
                uc.RenderTransformOrigin = new Point(0.5, 0.5);
                TransformGroup tg = new TransformGroup();
                uc.RenderTransform = tg;
                tg.Children.Add(new ScaleTransform());
                tg.Children.Add(new TranslateTransform());
            }
            double first = i * 0.05 + first_value;
            double middle = i * 0.05 + middle_value;
            double end = i * 0.05 + end_value;
            EasingDoubleKeyFrame edf0 = new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0)));//所有元素起點都是0
            EasingDoubleKeyFrame edf1 = new EasingDoubleKeyFrame(Init, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(first)));
            EasingDoubleKeyFrame edf2 = new EasingDoubleKeyFrame(Mul, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(middle)));
            EasingDoubleKeyFrame edf3 = new EasingDoubleKeyFrame(Org, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(end)));

            DoubleAnimationUsingKeyFrames daukf1 = new DoubleAnimationUsingKeyFrames();
            daukf1.KeyFrames.Add(edf0);
            daukf1.KeyFrames.Add(edf1);
            daukf1.KeyFrames.Add(edf2);
            daukf1.KeyFrames.Add(edf3);
            storyboard.Children.Add(daukf1);
            Storyboard.SetTarget(daukf1, uc);
            Storyboard.SetTargetProperty(daukf1, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));

            DoubleAnimationUsingKeyFrames daukf2 = new DoubleAnimationUsingKeyFrames();
            daukf2.KeyFrames.Add(edf0);
            daukf2.KeyFrames.Add(edf1);
            daukf2.KeyFrames.Add(edf2);
            daukf2.KeyFrames.Add(edf3);
            storyboard.Children.Add(daukf2);
            Storyboard.SetTarget(daukf2, uc);
            Storyboard.SetTargetProperty(daukf2, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));

            DoubleAnimationUsingKeyFrames daukf3 = new DoubleAnimationUsingKeyFrames();
            EasingDoubleKeyFrame edf31 = new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(middle)));
            EasingDoubleKeyFrame edf32 = new EasingDoubleKeyFrame(Top, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(end)));
            daukf3.KeyFrames.Add(edf31);
            daukf3.KeyFrames.Add(edf32);
            storyboard.Children.Add(daukf3);
            Storyboard.SetTarget(daukf3, uc);
            Storyboard.SetTargetProperty(daukf3, new PropertyPath("(Canvas.Top)"));

            DoubleAnimationUsingKeyFrames daukf4 = new DoubleAnimationUsingKeyFrames();
            EasingDoubleKeyFrame edf41 = new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(middle)));
            EasingDoubleKeyFrame edf42 = new EasingDoubleKeyFrame(Left, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(end)));
            daukf4.KeyFrames.Add(edf41);
            daukf4.KeyFrames.Add(edf42);
            storyboard.Children.Add(daukf4);
            Storyboard.SetTarget(daukf4, uc);
            Storyboard.SetTargetProperty(daukf4, new PropertyPath("(Canvas.Left)"));
       cav.Children.Add(uc); } storyboard.FillBehavior
= FillBehavior.HoldEnd; storyboard.Begin(); } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM