动画矩形移动到窗口WPF

时间:2015-11-24 18:58:17

标签: c# wpf canvas wpf-animation doubleanimation

我想要动画一个弯曲的矩形,我必须从它的外部移动INTO实际的Window组件,最好好像它刚刚出现在屏幕上。到目前为止,我已经看到了滚动动画的建议INSIDE一个位于窗口内的画布。我不知道我是否真的可以让Canvas超出实际的窗口。我是不是该?那里有更好的想法吗?

到目前为止,这是我的XAML及其代码隐藏。

UserMenu.xaml:

<Window x:Class="ChatClient.UserMenu"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="UserMenu" Height="350" Width="525" Icon="media/favicon.gif" Background="#FF3C3636" Foreground="{x:Null}">
    <Window.BorderBrush>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="Black" Offset="0"/>
            <GradientStop Color="#FF6F6D95" Offset="1"/>
        </LinearGradientBrush>
    </Window.BorderBrush>
    <Grid x:Name="GridBody">
        <Canvas Name="WindowMainCanvas">
            <Rectangle x:Name="Menu" Fill="#755E5E83" HorizontalAlignment="Left" Height="273" Stroke="Black" VerticalAlignment="Top" Width="446" RadiusY="27.5" RadiusX="27.5" Canvas.Left="545" Canvas.Top="23"/>
            <Button x:Name="ChatClientOnlyButton" Content="Chat (Clients Only)" HorizontalAlignment="Left" Height="80" Margin="132,65,0,0" Style="{DynamicResource OTonButtonStyle1}" VerticalAlignment="Top" Width="259" FontFamily="Impact" FontSize="26.667" Foreground="#FF1C045B" Click="chatClientsOnlyOption" Visibility="Hidden"/>
            <TextBlock x:Name="MenuLabel" HorizontalAlignment="Left" Height="25" Margin="231,35,0,0" TextWrapping="Wrap" Text="Menu" VerticalAlignment="Top" Width="101" FontFamily="Copperplate Gothic Light" FontSize="20" Visibility="Hidden">
                <TextBlock.Foreground>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF0A1D5F" Offset="0.374"/>
                        <GradientStop Color="#FF6E7FB9" Offset="1"/>
                    </LinearGradientBrush>
                </TextBlock.Foreground>
            </TextBlock>
            <Canvas ClipToBounds="True" Name="errorCanvas" Width="446" Height="17" Margin="36,152,35,151">
                <Rectangle x:Name="errorMarquee" Fill="#FF0A0A0C" HorizontalAlignment="Left" Height="17" Stroke="#FF5B1D1D" VerticalAlignment="Top" Width="446" Canvas.Left="-1" Visibility="Hidden"/>
                <TextBlock x:Name="errorText" HorizontalAlignment="Left" Height="16" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="690" FontFamily="Copperplate Gothic Bold" FontSize="16" Foreground="#FF7E0202" Visibility="Hidden"/>
            </Canvas>
        </Canvas>
    </Grid>
</Window>

UserMenu.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace ChatClient
{
    /// <summary>
    /// Interaction logic for UserMenu.xaml
    /// </summary>
    public partial class UserMenu : Window
    {
        public UserMenu()
        {
            InitializeComponent();
            DoubleAnimation menuSlideInAnimation = new DoubleAnimation();
            menuSlideInAnimation.From = Menu.Margin.Left;
            menuSlideInAnimation.To = 35;

            menuSlideInAnimation.Completed += (s, doneEvent) =>
            {
                //consider additional triggers
            };
            menuSlideInAnimation.Duration = new Duration(TimeSpan.FromSeconds(7.0));
            errorText.BeginAnimation(Rectangle.MarginProperty, menuSlideInAnimation, HandoffBehavior.Compose);
        }

        private void chatClientsOnlyOption(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Not available just yet!");
        }
    }
}

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

这样做很复杂,但你可以通过这样做。

  1. 包装要在边框控件中设置动画的矩形,以及 将其内容呈现为图像。

  2. 使用窗口外的边界创建透明弹出窗口

  3. 在弹出窗口中设置矩形图像的动画

  4. 动画完成后关闭弹出窗口。

  5. 这是一个接受动画边框控件的类:

    public class SlideInPopup
    {
        private Popup _popup;
    
        public SlideInPopup()
        {
    
        }
    
        public void SlideIn(Window parent, int heightOffset, Border animateControl, Duration duration)
        {
            if ((animateControl != null) && (parent != null))
            {
                int controlHeight = (int)animateControl.ActualHeight;
                int controlWidth = (int)animateControl.ActualWidth;                
    
                _popup = new Popup();
    
                double height = parent.Height;
                double widthOffset = parent.Width;
                double width = parent.Width * 2;
    
                var fromMargin = new Thickness(animateControl.Margin.Left + widthOffset, 
                                                    animateControl.Margin.Top, 
                                                    animateControl.Margin.Right, 
                                                    animateControl.Margin.Bottom);
    
                var toMargin = animateControl.Margin;
    
    
                Image animateImage = new Image();     
                animateImage.Name = "imgAnimate";
                animateImage.Margin = fromMargin;
                animateImage.Height = controlHeight;
                animateImage.Width = controlWidth;
                animateImage.HorizontalAlignment = HorizontalAlignment.Left;
                animateImage.VerticalAlignment = VerticalAlignment.Top;
                animateImage.Source = CaptureScreen(animateControl, controlWidth, controlHeight);
    
                animateControl.Visibility = Visibility.Collapsed;
                animateControl.Height = 0;
    
                Grid child = new Grid();
                child.Height = height;
                child.Width = width;
                child.Background = Brushes.Transparent;
                child.Children.Add(animateImage);
    
                var storyboard = new Storyboard();
                ThicknessAnimation animation = new ThicknessAnimation(fromMargin, toMargin, duration);
                animation.AccelerationRatio = 0.8;
    
                storyboard.Children.Add(animation);
    
                storyboard.Completed += (s, doneEvent) =>
                {
                    _popup.IsOpen = false;
                    animateControl.Visibility = Visibility.Visible;
                    animateControl.Height = controlHeight;
                };
    
                Storyboard.SetTarget(animation, animateImage);
                Storyboard.SetTargetProperty(animation, new PropertyPath("(Margin)"));
    
                _popup.Height = height;
                _popup.Width = width;
                _popup.HorizontalOffset = parent.Left;
                _popup.VerticalOffset = parent.Top + heightOffset;
                _popup.AllowsTransparency = true;
                _popup.Child = child;
                _popup.IsOpen = true;
    
                child.Resources.Add("sbSlideIn", storyboard);
    
                storyboard.Begin();
            }            
        }
    
        private static BitmapSource CaptureScreen(Visual target, double dpiX, double dpiY)
        {
            if (target == null)
            {
                return null;
            }
            Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
            RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
                                                            (int)(bounds.Height * dpiY / 96.0),
                                                            dpiX,
                                                            dpiY,
                                                            PixelFormats.Pbgra32);
            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext ctx = dv.RenderOpen())
            {
                VisualBrush vb = new VisualBrush(target);
                ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
            }
            rtb.Render(dv);
            return rtb;
        }
    }
    

    然后在你的主窗口xaml中你可以用边框控件包裹你的矩形并删除画布定位属性

    <Border x:Name="borderRect" Margin="35,23,0,0">
        <Rectangle x:Name="Menu" Fill="#755E5E83" HorizontalAlignment="Left" Height="273" Stroke="Black" VerticalAlignment="Top" Width="446" RadiusY="27.5" RadiusX="27.5"/ >
    </Border>
    

    然后您可以使用以下代码启动动画:

    var slideInPopup = new SlideInPopup();
    int heightOffset = (int)this.Height - (int)((FrameworkElement)this.Content).ActualHeight;
    slideInPopup.SlideIn(this, heightOffset, borderRect, new Duration(TimeSpan.FromSeconds(1.0)));