88

WPF 简易的喷泉效果 - 衆尋

 6 years ago
source link: http://www.cnblogs.com/ZXdeveloper/p/7837682.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

WPF 简易的喷泉效果

这两天领导让我做个喷泉的效果,要把一个个UserControl从一个位置喷出,然后,最后落在最终需要在的位置。

喷泉效果说白了,就是两个步骤:1、放大,从0放大到需要的倍数;2、缩小,平移,从放大的倍数还原到UserControl的原始大小,并且定位到最终的位置。

虽然,只有两步,但是,作为写动画的新手,还是有点费事的,所以,采用了先用Blend设计,然后再转换为C#代码的过程。

一、Blend设计单个UserControl的放大和移动效果

1、在Blend里,新建个项目,然后,在Grid下,放个Canvas,在Canvas下放个Image(先拿Image来设计)

609679-20171115100843671-783675400.png

2、在Blend左侧的时间线,选中image控件,然后点击上面的+号,会弹出新增动画资源的弹窗,点击确定。

609679-20171115101052562-792680062.png

3、根据需要,拖拽左侧的时间线(黄线)到对应位置,然后,对红框中的Image控件,进行放大、缩小、位置调整等操作。

609679-20171115102419671-1265150400.png

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>

 

609679-20171115103509109-2099047592.gif

二、把XAML代码转换为C#

有了XAML代码,转换成C#代码,就方便多了,只要把对应的部分相关转换,然后启动动画,就OK了

609679-20171115104220906-1983841644.png

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,所以,就只写了两个

609679-20171115111537515-1671294797.png

 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;
        }
    }
}

效果如下:

609679-20171115124317452-1267103497.gif

喷泉效果的代码如下:

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(); } }

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK