Silverlight中为Margin添加动画

因为在Silverlight中没有ThicknessAnimation,所以为Margin添加动画有点麻烦:

1. 使用ObjectAnimationUsingKeyFrames来做,这个就是通过计算要显示的每一帧内容来设置动画,可能看起来不是那么平滑,如果需要平滑的话,那样就需要写代码来动态生成动画效果,看起来会平滑很多。

使用XAML来进行描述就是这样:

<Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="150"/>
        </Grid.RowDefinitions>
        <Grid.Resources>
            <Storyboard x:Name="sb">
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin"
                                   Storyboard.TargetName="bdTest">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                    <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                        <DiscreteObjectKeyFrame.Value>
                            <Thickness>3,7,5,9</Thickness>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                    <DiscreteObjectKeyFrame KeyTime="0:0:0.6">
                        <DiscreteObjectKeyFrame.Value>
                            <Thickness>4,8,6,10</Thickness>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                    <DiscreteObjectKeyFrame KeyTime="0:0:0.7">
                        <DiscreteObjectKeyFrame.Value>
                            <Thickness>40,80,60,100</Thickness>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </Grid.Resources>
        <Border x:Name="bdTest" Grid.Row="0" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" Background="Red" />
        <Button Content="Button" HorizontalAlignment="Left" Grid.Row="1" VerticalAlignment="Top" Width="75" Click="Button_Click_1" />
        
    </Grid>

2. 另一种方式请参见 Code Project:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ThicknessAnimation
{
	public class ThicknessWrapper : FrameworkElement
	{

		public FrameworkElement Target
		{
			get
			{
				return (FrameworkElement)GetValue(TargetProperty);
			}
			set
			{
				SetValue(TargetProperty, value);
			}
		}

		// Using a DependencyProperty as the backing store for Target.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty TargetProperty =
			DependencyProperty.Register("Target", typeof(FrameworkElement), typeof(ThicknessWrapper), new PropertyMetadata(null, OnTargetChanged));


		static void OnTargetChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
		{
			ThicknessWrapper sender = (ThicknessWrapper)source;
			sender.UpdateMargin();
		}




		public String PropertyName
		{
			get
			{
				return (String)GetValue(PropertyNameProperty);
			}
			set
			{
				SetValue(PropertyNameProperty, value);
			}
		}

		// Using a DependencyProperty as the backing store for PropertyName.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty PropertyNameProperty =
			DependencyProperty.Register("PropertyName", typeof(String), typeof(ThicknessWrapper), new PropertyMetadata("Margin"));



		public Side Side
		{
			get
			{
				return (Side)GetValue(SideProperty);
			}
			set
			{
				SetValue(SideProperty, value);
			}
		}

		// Using a DependencyProperty as the backing store for Side.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty SideProperty =
			DependencyProperty.Register("Side", typeof(Side), typeof(ThicknessWrapper), new PropertyMetadata(Side.Left, OnSideChanged));


		static void OnSideChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
		{
			ThicknessWrapper sender = (ThicknessWrapper)source;
			sender.UpdateMargin();
		}


		public double Value
		{
			get
			{
				return (double)GetValue(ValueProperty);
			}
			set
			{
				SetValue(ValueProperty, value);
			}
		}

		// Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty ValueProperty =
			DependencyProperty.Register("Value", typeof(double), typeof(ThicknessWrapper), new PropertyMetadata(0.0, OnValueChanged));


		static void OnValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
		{
			ThicknessWrapper sender = (ThicknessWrapper)source;
			sender.UpdateMargin();
		}





		static void OnPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
		{
			ThicknessWrapper sender = (ThicknessWrapper)source;
			sender.UpdateMargin();
		}

		private void UpdateMargin()
		{
			if(Target != null)
			{
				var thicknessProperty = Target.GetType().GetProperty(PropertyName);
				var currentThickness = (Thickness)thicknessProperty.GetValue(Target, null);
				var nextThickness = new Thickness(
					CalculateThickness(Side.Left,  currentThickness.Left),
					CalculateThickness(Side.Top,  currentThickness.Top),
					CalculateThickness(Side.Right, currentThickness.Right),
					CalculateThickness(Side.Bottom, currentThickness.Bottom)
					);

				thicknessProperty.SetValue(Target, nextThickness, null);
			}
		}

		private double CalculateThickness(ThicknessAnimation.Side sideToCalculate, double currentValue)
		{
			return (Side & sideToCalculate) == sideToCalculate ? Value : currentValue;
		}


	}

	[Flags]
	public enum Side
	{
		Left = 1,
		Top = 2,
		Right = 4,
		Bottom = 8,
		All = 15
	}
}

<Grid x:Name="LayoutRoot" Background="White">
        <Grid.Resources>
            <Storyboard x:Key="animation">
                <!--<DoubleAnimation Storyboard.TargetName="rectTopMargin" Storyboard.TargetProperty="Value" From="0" To="100" Duration="00:00:1"></DoubleAnimation>-->
                <DoubleAnimation Storyboard.TargetName="rectStrokeThickness" Storyboard.TargetProperty="Value" From="0" To="20" Duration="00:00:1"></DoubleAnimation>
            </Storyboard>
        </Grid.Resources>

        <local:ThicknessWrapper x:Name="rectTopMargin" Target="{Binding ElementName=rect}" Side="Top" PropertyName="Margin"></local:ThicknessWrapper>
        <local:ThicknessWrapper x:Name="rectStrokeThickness" Target="{Binding ElementName=rect}" Side="Left, Right" PropertyName="BorderThickness"></local:ThicknessWrapper>

        <StackPanel>
            <Button Content="Click to animate" Click="Button_Click"></Button>
            <Border x:Name="rect" HorizontalAlignment="Left"  BorderBrush="Black" VerticalAlignment="Top" Background="Green" Height="50" Width="50"></Border>
        </StackPanel>
    </Grid>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值