本文章将以如何实现 开始菜单上的tile 为主。
该控件代码经过测试可直接使用。
tile 在我的思路中分为了 3层。
基于ContentControl实现HeaderedContentControl 用于增加Tile种的内容标题
在HeaderedContentControl 的基础上 实现 3d变换 根据触点方向触发不同动画。
实现HubTileBase
在HubTileBase 下我们可以实现多种磁贴
如liveTile(实时反馈) MosaicTile(仿wp8 风格) PulsingTile(脉冲)等等。。
以下将以PulsingTile 代码为主 来介绍
public class HeaderedContentControl : ContentControl
{
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(object), typeof(HeaderedContentControl), new PropertyMetadata(null));
public static readonly DependencyProperty HeaderStyleProperty =
DependencyProperty.Register("HeaderStyle", typeof(Style), typeof(HeaderedContentControl), new PropertyMetadata(null));
public static readonly DependencyProperty HeaderTemplateProperty =
DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate), typeof(HeaderedContentControl), new PropertyMetadata(null));
public static readonly DependencyProperty HeaderTemplateSelectorProperty =
DependencyProperty.Register("HeaderTemplateSelector", typeof(DataTemplateSelector), typeof(HeaderedContentControl), new PropertyMetadata(null));
public HeaderedContentControl()
{
this.DefaultStyleKey = typeof(HeaderedContentControl);
}
public object Header
{
get
{
return base.GetValue(HeaderProperty);
}
set
{
base.SetValue(HeaderProperty, value);
}
}
public Style HeaderStyle
{
get
{
return (Style)base.GetValue(HeaderStyleProperty);
}
set
{
base.SetValue(HeaderStyleProperty, value);
}
}
public DataTemplate HeaderTemplate
{
get
{
return (DataTemplate)base.GetValue(HeaderTemplateProperty);
}
set
{
base.SetValue(HeaderTemplateProperty, value);
}
}
public DataTemplateSelector HeaderTemplateSelector
{
get
{
return (DataTemplateSelector)base.GetValue(HeaderTemplateSelectorProperty);
}
set
{
base.SetValue(HeaderTemplateSelectorProperty, value);
}
}
}
public class HubTileBase : HeaderedContentControl
{
public static readonly DependencyProperty AccentBrushProperty = DependencyProperty.Register("AccentBrush", typeof(Brush), typeof(HubTileBase), new PropertyMetadata(null));
public static readonly DependencyProperty GroupNameProperty = DependencyProperty.Register("GroupName", typeof(string), typeof(HubTileBase), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(Windows.UI.Xaml.Media.ImageSource), typeof(HubTileBase), new PropertyMetadata(null));
public static readonly DependencyProperty IsFrozenProperty = DependencyProperty.Register("IsFrozen", typeof(bool), typeof(HubTileBase), new PropertyMetadata((bool)false, OnIsFrozenChanged));
public static readonly DependencyProperty OverrideDefaultStatesProperty = DependencyProperty.Register("OverrideDefaultStates", typeof(bool), typeof(HubTileBase), new PropertyMetadata((bool)false));
private PointerDirection pointerdirection;
private bool pointerover;
private bool pointerpressed;
public static readonly DependencyProperty RotationDepthProperty = DependencyProperty.Register("RotationDepth", typeof(double), typeof(HubTileBase), new PropertyMetadata((double)20.0));
public static readonly DependencyProperty ScaleDepthProperty = DependencyProperty.Register("ScaleDepth", typeof(double), typeof(HubTileBase), new PropertyMetadata((double)0.9));
private Storyboard storyboard;
public static readonly DependencyProperty TilePressDurationProperty = DependencyProperty.Register("TilePressDuration", typeof(TimeSpan), typeof(HubTileBase), new PropertyMetadata(TimeSpan.FromSeconds((double)0.1)));
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(object), typeof(HubTileBase), new PropertyMetadata(null));
public static readonly DependencyProperty TitleStyleProperty = DependencyProperty.Register("TitleStyle", typeof(Style), typeof(HubTileBase), new PropertyMetadata(null));
private Timeline BuildAnimation(PointerDirection direction)
{
DoubleAnimationUsingKeyFrames frames = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(frames, this);
if (direction != PointerDirection.Center)
{
PlaneProjection projection2 = new PlaneProjection();
projection2.CenterOfRotationZ = 0.0;
PlaneProjection projection = projection2;
EasingDoubleKeyFrame frame3 = new EasingDoubleKeyFrame();
frame3.KeyTime = ((KeyTime)TimeSpan.FromSeconds((double)0.0));
frame3.Value = 0.0;
EasingDoubleKeyFrame frame = frame3;
EasingDoubleKeyFrame frame4 = new EasingDoubleKeyFrame();
frame4.KeyTime = ((KeyTime)this.TilePressDuration);
EasingDoubleKeyFrame frame2 = frame4;
frames.KeyFrames.Add(frame);
frames.KeyFrames.Add(frame2);
if ((direction == PointerDirection.Left) || (direction == PointerDirection.Bottom))
{
frame2.Value = this.RotationDepth;
}
else if ((direction == PointerDirection.Top) || (direction == PointerDirection.Right))
{
frame2.Value = -this.RotationDepth;
}
if ((direction == PointerDirection.Top) || (direction == PointerDirection.Bottom))
{
Storyboard.SetTargetProperty(frames, "(UIElement.Projection).(PlaneProjection.RotationX)");
}
else if ((direction == PointerDirection.Left) || (direction == PointerDirection.Right))
{
Storyboard.SetTargetProperty(frames, "(UIElement.Projection).(PlaneProjection.RotationY)");
}
if (direction == PointerDirection.Bottom)
{
projection.CenterOfRotationX = 0.5;
projection.CenterOfRotationY = 0.0;
}
else if (direction == PointerDirection.Top)
{
projection.CenterOfRotationX = (0.5);
projection.CenterOfRotationY = (1.0);
}
else if (direction == PointerDirection.Left)
{
projection.CenterOfRotationX = (1.0);
projection.CenterOfRotationY = (0.5);
}
else if (direction == PointerDirection.Right)
{
projection.CenterOfRotationX = (0.0);
projection.CenterOfRotationY = (0.5);
}
base.Projection = (projection);
}
return frames;
}
private Timeline BuildScaleXAnimation()
{
DoubleAnimationUsingKeyFrames frames = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(frames, this);
Storyboard.SetTargetProperty(frames, "(UIElement.RenderTransform).(CompositeTransform.ScaleX)");
EasingDoubleKeyFrame frame3 = new EasingDoubleKeyFrame();
frame3.KeyTime = ((KeyTime)TimeSpan.FromSeconds((double)0.0));
frame3.Value = (1.0);
EasingDoubleKeyFrame frame = frame3;
EasingDoubleKeyFrame frame4 = new EasingDoubleKeyFrame();
frame4.KeyTime = ((KeyTime)this.TilePressDuration);
frame4.Value = (this.ScaleDepth);
EasingDoubleKeyFrame frame2 = frame4;
frames.KeyFrames.Add(frame);
frames.KeyFrames.Add(frame2);
CompositeTransform transform = new CompositeTransform();
base.RenderTransformOrigin = (new Point(0.5, 0.5));
base.RenderTransform = (transform);
return frames;
}
private Timeline BuildScaleYAnimation()
{
DoubleAnimationUsingKeyFrames frames = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(frames, this);
Storyboard.SetTargetProperty(frames, "(UIElement.RenderTransform).(CompositeTransform.ScaleY)");
EasingDoubleKeyFrame frame3 = new EasingDoubleKeyFrame();
frame3.KeyTime = ((KeyTime)TimeSpan.FromSeconds((double)0.0));
frame3.Value = (1.0);
EasingDoubleKeyFrame frame = frame3;
EasingDoubleKeyFrame frame4 = new EasingDoubleKeyFrame();
frame4.KeyTime = ((KeyTime)this.TilePressDuration);
frame4.Value = (this.ScaleDepth);
EasingDoubleKeyFrame frame2 = frame4;
frames.KeyFrames.Add(frame);
frames.KeyFrames.Add(frame2);
CompositeTransform transform = new CompositeTransform();
base.RenderTransform = (transform);
base.RenderTransformOrigin = (new Point(0.5, 0.5));
return frames;
}
private void ExecutePointerReleased()
{
if (this.pointerpressed)
{
if (this.OverrideDefaultStates)
{
if (this.pointerover)
{
VisualStateManager.GoToState(this, "PointerOver", true);
}
else
{
VisualStateManager.GoToState(this, "Normal", true);
}
}
else if (this.storyboard != null)
{
if (this.pointerdirection != PointerDirection.Center)
{
DoubleAnimationUsingKeyFrames frames = this.storyboard.Children[0] as DoubleAnimationUsingKeyFrames;
if (frames != null)
{
EasingDoubleKeyFrame frame = frames.KeyFrames[0] as EasingDoubleKeyFrame;
EasingDoubleKeyFrame frame2 = frames.KeyFrames[1] as EasingDoubleKeyFrame;
frame.Value = (frame2.Value);
frame2.Value = (0.0);
}
}
else
{
DoubleAnimationUsingKeyFrames frames2 = this.storyboard.Children[0] as DoubleAnimationUsingKeyFrames;
DoubleAnimationUsingKeyFrames frames3 = this.storyboard.Children[1] as DoubleAnimationUsingKeyFrames;
if (frames2 != null)
{
EasingDoubleKeyFrame frame3 = frames2.KeyFrames[0] as EasingDoubleKeyFrame;
EasingDoubleKeyFrame frame4 = frames2.KeyFrames[1] as EasingDoubleKeyFrame;
frame3.Value = (frame4.Value);
frame4.Value = (1.0);
}
if (frames3 != null)
{
EasingDoubleKeyFrame frame5 = frames3.KeyFrames[0] as EasingDoubleKeyFrame;
EasingDoubleKeyFrame frame6 = frames3.KeyFrames[1] as EasingDoubleKeyFrame;
frame5.Value = (frame6.Value);
frame6.Value = (1.0);
}
}
this.storyboard.Begin();
}
}
this.pointerpressed = false;
}
protected virtual void OnIsFrozenChanged(DependencyPropertyChangedEventArgs e)
{
}
private static void OnIsFrozenChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
HubTileBase base2 = sender as HubTileBase;
if (base2 != null)
{
base2.OnIsFrozenChanged(e);
}
}
protected override void OnPointerEntered(PointerRoutedEventArgs e)
{
this.pointerover = true;
VisualStateManager.GoToState(this, "PointerOver", true);
base.OnPointerEntered(e);
}
protected override void OnPointerExited(PointerRoutedEventArgs e)
{
if (this.pointerpressed)
{
this.ExecutePointerReleased();
}
this.pointerover = false;
VisualStateManager.GoToState(this, "Normal", true);
base.OnPointerExited(e);
}
protected override void OnPointerPressed(PointerRoutedEventArgs e)
{
this.pointerpressed = true;
if (this.OverrideDefaultStates)
{
VisualStateManager.GoToState(this, "PointerPressed", true);
}
else
{
PointerPoint currentpoint = e.GetCurrentPoint(this);
var point = currentpoint.Position;
double num = base.ActualWidth / 3.0;
double num2 = base.ActualHeight / 3.0;
Dictionary<PointerDirection, Rect> pieces = new Dictionary<PointerDirection, Rect>();
pieces.Add(PointerDirection.TopLeft, new Rect(0.0, 0.0, num, num2));
pieces.Add(PointerDirection.Top, new Rect(num, 0.0, num, num2));
pieces.Add(PointerDirection.TopRight, new Rect(num * 2.0, 0.0, num, num2));
pieces.Add(PointerDirection.Left, new Rect(0.0, num2, num, num2));
pieces.Add(PointerDirection.Center, new Rect(num, num2, num, num2));
pieces.Add(PointerDirection.Right, new Rect(num * 2.0, num2, num, num2));
pieces.Add(PointerDirection.BottomLeft, new Rect(0.0, num2 * 2.0, num, num2));
pieces.Add(PointerDirection.Bottom, new Rect(num, num2 * 2.0, num, num2));
pieces.Add(PointerDirection.BottomRight, new Rect(num * 2.0, num2 * 2.0, num, num2));
this.pointerdirection =
(from _direction in pieces.Keys
where pieces[_direction].Contains(point)
select _direction).FirstOrDefault();
this.storyboard = new Storyboard();
if (this.pointerdirection <= PointerDirection.Center)
{
if (this.pointerdirection == PointerDirection.Center)
{
Timeline timeline = this.BuildScaleXAnimation();
Timeline timeline2 = this.BuildScaleYAnimation();
this.storyboard.Children.Add(timeline);
this.storyboard.Children.Add(timeline2);
this.storyboard.Begin();
}
else
{
Timeline timeline3 = this.BuildAnimation(this.pointerdirection);
this.storyboard.Children.Add(timeline3);
this.storyboard.Begin();
}
}
else if (this.pointerdirection == PointerDirection.TopLeft)
{
if (currentpoint.Position.X > currentpoint.Position.Y)
{
Timeline timeline4 = this.BuildAnimation(PointerDirection.Top);
this.storyboard.Children.Add(timeline4);
this.storyboard.Begin();
}
else
{
Timeline timeline5 = this.BuildAnimation(PointerDirection.Left);
this.storyboard.Children.Add(timeline5);
this.storyboard.Begin();
}
}
else if (this.pointerdirection == PointerDirection.TopRight)
{
if (currentpoint.Position.Y > (num2 - (currentpoint.Position.X - (num * 2.0))))
{
Timeline timeline6 = this.BuildAnimation(PointerDirection.Right);
this.storyboard.Children.Add(timeline6);
this.storyboard.Begin();
}
else
{
Timeline timeline7 = this.BuildAnimation(PointerDirection.Top);
this.storyboard.Children.Add(timeline7);
this.storyboard.Begin();
}
}
else if (this.pointerdirection == PointerDirection.BottomLeft)
{
if ((currentpoint.Position.Y - (num2 * 2.0)) > (num2 - currentpoint.Position.X))
{
Timeline timeline8 = this.BuildAnimation(PointerDirection.Bottom);
this.storyboard.Children.Add(timeline8);
this.storyboard.Begin();
}
else
{
Timeline timeline9 = this.BuildAnimation(PointerDirection.Left);
this.storyboard.Children.Add(timeline9);
this.storyboard.Begin();
}
}
else if (currentpoint.Position.X > currentpoint.Position.Y)
{
Timeline timeline10 = this.BuildAnimation(PointerDirection.Right);
this.storyboard.Children.Add(timeline10);
this.storyboard.Begin();
}
else
{
Timeline timeline11 = this.BuildAnimation(PointerDirection.Bottom);
this.storyboard.Children.Add(timeline11);
this.storyboard.Begin();
}
}
base.OnPointerPressed(e);
}
protected override void OnPointerReleased(PointerRoutedEventArgs e)
{
this.ExecutePointerReleased();
base.OnPointerReleased(e);
}
public Brush AccentBrush
{
get
{
return (Brush)base.GetValue(AccentBrushProperty);
}
set
{
base.SetValue(AccentBrushProperty, value);
}
}
public string GroupName
{
get
{
return (string)((string)base.GetValue(GroupNameProperty));
}
set
{
base.SetValue(GroupNameProperty, value);
}
}
public Windows.UI.Xaml.Media.ImageSource ImageSource
{
get
{
return (Windows.UI.Xaml.Media.ImageSource)base.GetValue(ImageSourceProperty);
}
set
{
base.SetValue(ImageSourceProperty, value);
}
}
public bool IsFrozen
{
get
{
return (bool)((bool)base.GetValue(IsFrozenProperty));
}
set
{
base.SetValue(IsFrozenProperty, (bool)value);
}
}
public bool OverrideDefaultStates
{
get
{
return (bool)((bool)base.GetValue(OverrideDefaultStatesProperty));
}
set
{
base.SetValue(OverrideDefaultStatesProperty, (bool)value);
}
}
public double RotationDepth
{
get
{
return (double)((double)base.GetValue(RotationDepthProperty));
}
set
{
base.SetValue(RotationDepthProperty, (double)value);
}
}
public double ScaleDepth
{
get
{
return (double)((double)base.GetValue(ScaleDepthProperty));
}
set
{
base.SetValue(ScaleDepthProperty, (double)value);
}
}
public TimeSpan TilePressDuration
{
get
{
return (TimeSpan)base.GetValue(TilePressDurationProperty);
}
set
{
base.SetValue(TilePressDurationProperty, value);
}
}
public object Title
{
get
{
return base.GetValue(TitleProperty);
}
set
{
base.SetValue(TitleProperty, value);
}
}
public Style TitleStyle
{
get
{
return (Style)base.GetValue(TitleStyleProperty);
}
set
{
base.SetValue(TitleStyleProperty, value);
}
}
}
public static class HubTileService
{
private static List<WeakReference> Tiles = new List<WeakReference>();
internal static void Dequeue(HubTileBase tile)
{
foreach (WeakReference reference in Tiles)
{
if (reference.Target == tile)
{
Tiles.Remove(reference);
break;
}
}
}
internal static void Enqueue(HubTileBase tile)
{
WeakReference reference = new WeakReference(tile, false);
Tiles.Add(reference);
}
public static void Freeze(HubTileBase tile)
{
foreach (WeakReference reference in Tiles)
{
if (reference.Target == tile)
{
HubTileBase base2 = reference.Target as HubTileBase;
base2.IsFrozen = true;
break;
}
}
}
public static void Freeze(string groupname)
{
using (List<WeakReference>.Enumerator enumerator = Tiles.GetEnumerator())
{
while (enumerator.MoveNext())
{
HubTileBase base2 = enumerator.Current.Target as HubTileBase;
if ((base2 != null) && (base2.GroupName == groupname))
{
base2.IsFrozen = false;
}
}
}
}
public static void UnFreeze(HubTileBase tile)
{
foreach (WeakReference reference in Tiles)
{
if (reference.Target == tile)
{
HubTileBase base2 = reference.Target as HubTileBase;
base2.IsFrozen = false;
break;
}
}
}
public static void UnFreeze(string groupname)
{
using (List<WeakReference>.Enumerator enumerator = Tiles.GetEnumerator())
{
while (enumerator.MoveNext())
{
HubTileBase base2 = enumerator.Current.Target as HubTileBase;
if ((base2 != null) && (base2.GroupName == groupname))
{
base2.IsFrozen = false;
}
}
}
}
}
public enum PointerDirection
{
Left,
Top,
Right,
Bottom,
Center,
TopLeft,
TopRight,
BottomLeft,
BottomRight
}
public class PulsingTile : HubTileBase
{
protected ContentPresenter PART_Content;
public static readonly DependencyProperty PulseDurationProperty = DependencyProperty.Register("PulseDuration", typeof(TimeSpan), typeof(PulsingTile), new PropertyMetadata(TimeSpan.FromSeconds((double)4.0), new PropertyChangedCallback(OnValueChanged)));
public static readonly DependencyProperty PulseScaleProperty = DependencyProperty.Register("PulseScale", typeof(double), typeof(PulsingTile), new PropertyMetadata((double)1.0, new PropertyChangedCallback(OnValueChanged)));
private Storyboard pulseStroyboard;
public static readonly DependencyProperty RadiusXProperty = DependencyProperty.Register("RadiusX", typeof(double), typeof(PulsingTile), new PropertyMetadata((double)0.0, new PropertyChangedCallback(OnValueChanged)));
public static readonly DependencyProperty RadiusYProperty = DependencyProperty.Register("RadiusY", typeof(double), typeof(PulsingTile), new PropertyMetadata((double)0.0, new PropertyChangedCallback(OnValueChanged)));
private Storyboard roatationStroyboard;
public static readonly DependencyProperty TranslateDurationProperty = DependencyProperty.Register("TranslateDuration", typeof(TimeSpan), typeof(PulsingTile), new PropertyMetadata(TimeSpan.FromSeconds((double)4.0), new PropertyChangedCallback(OnValueChanged)));
public PulsingTile()
{
base.DefaultStyleKey = (typeof(PulsingTile));
PulsingTile tile = this;
this.Loaded += this.OnLoaded;
}
private void AnimateContent()
{
if (this.PART_Content != null)
{
RectangleGeometry geometry = new RectangleGeometry();
geometry.Rect = (new Rect(0.0, 0.0, base.ActualWidth, base.ActualHeight));
base.Clip = (geometry);
this.PART_Content.RenderTransform = (new CompositeTransform());
this.PART_Content.RenderTransformOrigin = (new Point(0.5, 0.5));
this.PART_Content.Visibility = Windows.UI.Xaml.Visibility.Visible;
DoubleAnimationUsingKeyFrames frames = this.BuildXTimeLine(this.RadiusX, this.RadiusY);
DoubleAnimationUsingKeyFrames frames2 = this.BuildYTimeLine(this.RadiusX, this.RadiusY);
this.roatationStroyboard = new Storyboard();
RepeatBehavior behavior = new RepeatBehavior();
behavior.Type = (RepeatBehaviorType.Forever);
this.roatationStroyboard.RepeatBehavior = (behavior);
this.roatationStroyboard.Children.Add(frames);
this.roatationStroyboard.Children.Add(frames2);
Storyboard.SetTarget(frames, this.PART_Content);
Storyboard.SetTarget(frames2, this.PART_Content);
Storyboard.SetTargetProperty(frames, "(UIElement.RenderTransform).(CompositeTransform.TranslateX)");
Storyboard.SetTargetProperty(frames2, "(UIElement.RenderTransform).(CompositeTransform.TranslateY)");
DoubleAnimationUsingKeyFrames frames3 = this.BuildPulseXTimeLine(this.PulseScale);
DoubleAnimationUsingKeyFrames frames4 = this.BuildPulseYTimeLine(this.PulseScale);
this.pulseStroyboard = new Storyboard();
this.pulseStroyboard.AutoReverse = (true);
this.pulseStroyboard.SpeedRatio = (0.4);
RepeatBehavior behavior2 = new RepeatBehavior();
behavior2.Type = (RepeatBehaviorType.Forever);
this.pulseStroyboard.RepeatBehavior = (behavior2);
this.pulseStroyboard.Children.Add(frames3);
this.pulseStroyboard.Children.Add(frames4);
Storyboard.SetTarget(frames3, this.PART_Content);
Storyboard.SetTarget(frames4, this.PART_Content);
Storyboard.SetTargetProperty(frames3, "(UIElement.RenderTransform).(CompositeTransform.ScaleX)");
Storyboard.SetTargetProperty(frames4, "(UIElement.RenderTransform).(CompositeTransform.ScaleY)");
this.pulseStroyboard.Begin();
this.roatationStroyboard.Begin();
}
}
private DoubleAnimationUsingKeyFrames BuildPulseXTimeLine(double pulseScale)
{
TimeSpan pulseDuration = this.PulseDuration;
SplineDoubleKeyFrame frame = new SplineDoubleKeyFrame();
frame.Value = (1.0);
frame.KeyTime = ((KeyTime)TimeSpan.FromSeconds((double)0.0));
EasingDoubleKeyFrame frame2 = new EasingDoubleKeyFrame();
frame2.Value = (pulseScale);
frame2.KeyTime = (KeyTime.FromTimeSpan(this.PulseDuration));
SineEase ease = new SineEase();
ease.EasingMode = EasingMode.EaseOut;
frame2.EasingFunction = (ease);
DoubleAnimationUsingKeyFrames frames = new DoubleAnimationUsingKeyFrames();
frames.KeyFrames.Add(frame);
frames.KeyFrames.Add(frame2);
return frames;
}
private DoubleAnimationUsingKeyFrames BuildPulseYTimeLine(double pulseScale)
{
TimeSpan pulseDuration = this.PulseDuration;
SplineDoubleKeyFrame frame = new SplineDoubleKeyFrame();
frame.Value = (1.0);
frame.KeyTime = ((KeyTime)TimeSpan.FromSeconds((double)0.0));
EasingDoubleKeyFrame frame2 = new EasingDoubleKeyFrame();
frame2.Value = (pulseScale);
frame2.KeyTime = (KeyTime.FromTimeSpan(this.PulseDuration));
SineEase ease = new SineEase();
ease.EasingMode = EasingMode.EaseOut;
frame2.EasingFunction = (ease);
DoubleAnimationUsingKeyFrames frames = new DoubleAnimationUsingKeyFrames();
frames.KeyFrames.Add(frame);
frames.KeyFrames.Add(frame2);
return frames;
}
private DoubleAnimationUsingKeyFrames BuildXTimeLine(double radiusx, double radiusy)
{
TimeSpan translateDuration = this.TranslateDuration;
DiscreteDoubleKeyFrame frame = new DiscreteDoubleKeyFrame();
frame.Value = (0.0);
frame.KeyTime = ((KeyTime)TimeSpan.FromSeconds((double)0.0));
EasingDoubleKeyFrame frame2 = new EasingDoubleKeyFrame();
frame2.Value = (radiusx);
frame2.KeyTime = (KeyTime.FromTimeSpan(TimeSpan.FromSeconds((double)(translateDuration.TotalSeconds / 4.0))));
SineEase ease = new SineEase();
ease.EasingMode = EasingMode.EaseIn;
frame2.EasingFunction = (ease);
EasingDoubleKeyFrame frame3 = new EasingDoubleKeyFrame();
frame3.Value = (0.0);
frame3.KeyTime = (KeyTime.FromTimeSpan(TimeSpan.FromSeconds((double)(translateDuration.TotalSeconds / 2.0))));
SineEase ease2 = new SineEase();
ease2.EasingMode = EasingMode.EaseInOut;
frame3.EasingFunction = ease2;
EasingDoubleKeyFrame frame4 = new EasingDoubleKeyFrame();
frame4.Value = (-radiusx);
frame4.KeyTime = (KeyTime.FromTimeSpan(TimeSpan.FromSeconds((double)((translateDuration.TotalSeconds * 3.0) / 4.0))));
SineEase ease3 = new SineEase();
ease3.EasingMode = EasingMode.EaseIn;
frame4.EasingFunction = (ease3);
EasingDoubleKeyFrame frame5 = new EasingDoubleKeyFrame();
frame5.Value = (0.0);
frame5.KeyTime = (KeyTime.FromTimeSpan(translateDuration));
SineEase ease4 = new SineEase();
ease4.EasingMode = EasingMode.EaseInOut;
frame5.EasingFunction = (ease4);
DoubleAnimationUsingKeyFrames frames = new DoubleAnimationUsingKeyFrames();
frames.KeyFrames.Add(frame);
frames.KeyFrames.Add(frame2);
frames.KeyFrames.Add(frame3);
frames.KeyFrames.Add(frame4);
frames.KeyFrames.Add(frame5);
return frames;
}
private DoubleAnimationUsingKeyFrames BuildYTimeLine(double radiusx, double radiusy)
{
TimeSpan translateDuration = this.TranslateDuration;
DiscreteDoubleKeyFrame frame = new DiscreteDoubleKeyFrame();
frame.Value = (0.0);
frame.KeyTime = ((KeyTime)TimeSpan.FromSeconds((double)0.0));
EasingDoubleKeyFrame frame2 = new EasingDoubleKeyFrame();
frame2.Value = (this.RadiusY);
frame2.KeyTime = (KeyTime.FromTimeSpan(TimeSpan.FromSeconds((double)(translateDuration.TotalSeconds / 4.0))));
SineEase ease = new SineEase();
ease.EasingMode = EasingMode.EaseIn;
frame2.EasingFunction = (ease);
EasingDoubleKeyFrame frame3 = new EasingDoubleKeyFrame();
frame3.Value = (2.0 * this.RadiusY);
frame3.KeyTime = (KeyTime.FromTimeSpan(TimeSpan.FromSeconds((double)(translateDuration.TotalSeconds / 2.0))));
SineEase ease2 = new SineEase();
ease2.EasingMode = EasingMode.EaseIn;
frame3.EasingFunction = (ease2);
EasingDoubleKeyFrame frame4 = new EasingDoubleKeyFrame();
frame4.Value = (radiusy);
frame4.KeyTime = (KeyTime.FromTimeSpan(TimeSpan.FromSeconds((double)((translateDuration.TotalSeconds * 3.0) / 4.0))));
SineEase ease3 = new SineEase();
ease3.EasingMode = EasingMode.EaseInOut;
frame4.EasingFunction = (ease3);
EasingDoubleKeyFrame frame5 = new EasingDoubleKeyFrame();
frame5.Value = (0.0);
frame5.KeyTime = (KeyTime.FromTimeSpan(translateDuration));
SineEase ease4 = new SineEase();
ease4.EasingMode = EasingMode.EaseIn;
frame5.EasingFunction = (ease4);
DoubleAnimationUsingKeyFrames frames = new DoubleAnimationUsingKeyFrames();
frames.KeyFrames.Add(frame);
frames.KeyFrames.Add(frame2);
frames.KeyFrames.Add(frame3);
frames.KeyFrames.Add(frame4);
frames.KeyFrames.Add(frame5);
return frames;
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.PART_Content = base.GetTemplateChild("PART_Content") as ContentPresenter;
}
protected override void OnIsFrozenChanged(DependencyPropertyChangedEventArgs e)
{
if (base.IsFrozen)
{
if (this.pulseStroyboard != null)
{
this.pulseStroyboard.Stop();
}
if (this.roatationStroyboard != null)
{
this.roatationStroyboard.Stop();
}
}
else
{
if (this.pulseStroyboard != null)
{
this.pulseStroyboard.Begin();
}
if (this.roatationStroyboard != null)
{
this.roatationStroyboard.Begin();
}
}
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
HubTileService.Enqueue(this);
PulsingTile tile = this;
this.Loaded += PulsingTile_Unloaded;
this.StartAnimation();
}
private static void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
PulsingTile tile = sender as PulsingTile;
if (tile != null)
{
tile.StopAnimation();
tile.StartAnimation();
}
}
private void PulsingTile_Unloaded(object sender, RoutedEventArgs e)
{
HubTileService.Dequeue(this);
this.Unloaded -= PulsingTile_Unloaded;
}
private void StartAnimation()
{
this.AnimateContent();
}
private void StopAnimation()
{
if (this.pulseStroyboard != null)
{
this.pulseStroyboard.Stop();
}
if (this.roatationStroyboard != null)
{
this.roatationStroyboard.Stop();
}
}
public TimeSpan PulseDuration
{
get
{
return (TimeSpan)base.GetValue(PulseDurationProperty);
}
set
{
base.SetValue(PulseDurationProperty, value);
}
}
public double PulseScale
{
get
{
return (double)((double)base.GetValue(PulseScaleProperty));
}
set
{
base.SetValue(PulseScaleProperty, (double)value);
}
}
public double RadiusX
{
get
{
return (double)((double)base.GetValue(RadiusXProperty));
}
set
{
base.SetValue(RadiusXProperty, (double)value);
}
}
public double RadiusY
{
get
{
return (double)((double)base.GetValue(RadiusYProperty));
}
set
{
base.SetValue(RadiusYProperty, (double)value);
}
}
public TimeSpan TranslateDuration
{
get
{
return (TimeSpan)base.GetValue(TranslateDurationProperty);
}
set
{
base.SetValue(TranslateDurationProperty, value);
}
}
}
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PulsingTile="using:WinRTXamlToolkit.Controls">
<SolidColorBrush x:Key="AccentBrush" Color="#FF1FAEFF" />
<DataTemplate x:Key="ImageTileContentTemplate">
<Grid>
<Rectangle Fill="{Binding Background}"/>
<Rectangle Fill="White" Opacity="{Binding Opacity}"/>
<Image Source="{Binding Image}" Width="{Binding ImageWidth}" Height="{Binding ImageHeight}"
HorizontalAlignment="{Binding HorizontalImageAlignment}"
VerticalAlignment="{Binding VerticalImageAlignment}" Stretch="UniformToFill"/>
</Grid>
</DataTemplate>
<Style TargetType="ContentControl" x:Key="DefaultHeaderStyle">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="10 5"/>
<Setter Property="FontSize" Value="18"/>
</Style>
<Style TargetType="ContentControl" x:Key="DefaultTitleStyle">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="FontSize" Value="10"/>
</Style>
<Style TargetType="PulsingTile:PulsingTile" >
<Setter Property="Padding" Value="3"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="HeaderStyle" Value="{StaticResource DefaultHeaderStyle}"/>
<Setter Property="TitleStyle" Value="{StaticResource DefaultTitleStyle}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PulsingTile:PulsingTile">
<Grid x:Name="PART_Layout">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Duration="0" To="0.28"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="PointerOveRect"/>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerPressed">
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="PointerOveRect"
Fill="{StaticResource ApplicationForegroundThemeBrush}"
Opacity="0" Margin="-2"/>
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" Margin="{TemplateBinding Padding}"
x:Name="PART_Border">
<Grid Margin="{TemplateBinding Padding}" >
<ContentPresenter
x:Name="PART_Content"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}" />
<ContentControl Content="{TemplateBinding Title}"
Style="{TemplateBinding TitleStyle}"/>
<ContentControl Content="{TemplateBinding Header}"
Style="{TemplateBinding HeaderStyle}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
/>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
以上是主体代码。可以将其复制到项目中编译后可用。
使用方式:
<tools:PulsingTile
HorizontalAlignment="Stretch"
Width="423423"
Height="43423"
d:DesignWidth="200"
d:DesignHeight="200"
Foreground="White"
RadiusX="0"
RadiusY="0"
Title="123123123123"
PulseDuration="0:0:5"
PulseScale="2"
VerticalAlignment="Stretch">
<Image Source="XXXXXXXXXXXXXXXXX"></Image>
</tools:PulsingTile>
最终效果: 该磁贴会根据 时间 放大倍数 等参数 定时脉冲缩放