2017-08-18 81 views
3

我一直在关注this问题做出彩色动画。颜色动画轻松

我可以创建动画,它运行良好,直到动画重新开始。有一段时间感觉动画已经在那里开始/停止了片刻。我希望动画顺利运行,以便它不会在颜色中显示任何重新启动效果。有可能这样做吗?

我使用下面的代码:

 <Storyboard x:Key="GradientAnimation" 
       RepeatBehavior="Forever" 
       Storyboard.TargetName="BackgroundBrush" 
       SpeedRatio="0.3"> 
     <ColorAnimationUsingKeyFrames 
      Storyboard.TargetProperty="(UIElement.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" 
      EnableDependentAnimation="True" 
      BeginTime="-0:0:0.5"> 

      <LinearColorKeyFrame KeyTime="0:0:0" Value="Black"/> 
      <LinearColorKeyFrame KeyTime="0:0:1" Value="Red"/> 
      <LinearColorKeyFrame KeyTime="0:0:2" Value="Black"/> 
      <LinearColorKeyFrame KeyTime="0:0:3" Value="Red"/> 
      <LinearColorKeyFrame KeyTime="0:0:4" Value="Black"/> 
      <LinearColorKeyFrame KeyTime="0:0:5" Value="Red"/> 
      <LinearColorKeyFrame KeyTime="0:0:6" Value="Black"/> 
      <LinearColorKeyFrame KeyTime="0:0:7" Value="Red"/> 

     </ColorAnimationUsingKeyFrames> 
     <ColorAnimationUsingKeyFrames 
      Storyboard.TargetProperty="(UIElement.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" 
      EnableDependentAnimation="True"> 

      <LinearColorKeyFrame KeyTime="0:0:0" Value="Red"/> 
      <LinearColorKeyFrame KeyTime="0:0:1" Value="Black"/> 
      <LinearColorKeyFrame KeyTime="0:0:2" Value="Red"/> 
      <LinearColorKeyFrame KeyTime="0:0:3" Value="Black"/> 
      <LinearColorKeyFrame KeyTime="0:0:4" Value="Red"/> 
      <LinearColorKeyFrame KeyTime="0:0:5" Value="Black"/> 
      <LinearColorKeyFrame KeyTime="0:0:6" Value="Red"/> 
      <LinearColorKeyFrame KeyTime="0:0:7" Value="Black"/> 

     </ColorAnimationUsingKeyFrames> 
    </Storyboard> 

我开始这个动画在后台代码:

((Storyboard)Resources["GradientAnimation"]).Begin(); 

也许有某种“宽松”方式,该拌和开始并停止动画,使其看起来像长时间运行的动画一样平滑。有什么建议么?

+0

我认为,你只需要在你开始相同的状态来完成。所以它可能只是红色 - >黑色 - >红色。它不工作吗? – michauzo

+0

你是什么意思的“重新开始”?它不是永远运行吗?你是否手动停止并重新启动它? –

+0

它一直在运行,是的,但它并没有像需要的那样流畅,因为有一个'缺口'有点儿不对。 – Ahmar

回答

12

您可以尝试EasingColorKeyFrame,但动画永远不会平滑,因为它在UI线程上运行(即EnableDependentAnimation="True")。

这里有一些好消息和坏消息。好处是我们现在在组合图层上有新的渐变画笔API,这意味着它完全具有动画效果并且可以在UI线程上运行。所以性能明智的是它会比目前的Storyboard解决方案好得多。但它仅在Windows 10内幕预览版以上,这意味着它不适用于大多数当前用户,除了内部人员。

但是,我仍然在这里发布这个新的解决方案供将来参考,因为这个主题还没有样本可用。

注意我为动画添加了一些额外的酱以使其更有趣。如果你只想要动画的颜色,随时移动EndPointRotationAngleInDegrees动画(我使用EndPoint动画从应用程序启动时的固体背景颜色变为渐变,RotationAngleInDegrees以永久旋转渐变画笔)。

var compositor = Window.Current.Compositor; 

// Initially, we set the end point to be (0,0) 'cause we want to animate it at start. 
// If you don't want this behavior, simply set it to a different value within (1,1). 
_gradientBrush = compositor.CreateLinearGradientBrush(); 
_gradientBrush.EndPoint = Vector2.Zero; 

// Create gradient initial colors. 
var gradientStop1 = compositor.CreateColorGradientStop(); 
gradientStop1.Offset = 0.0f; 
gradientStop1.Color = GradientStop1StartColor; 
var gradientStop2 = compositor.CreateColorGradientStop(); 
gradientStop2.Offset = 1.0f; 
gradientStop2.Color = GradientStop2StartColor; 
_gradientBrush.ColorStops.Add(gradientStop1); 
_gradientBrush.ColorStops.Add(gradientStop2); 

// Assign the gradient brush to the Root element's Visual. 
_backgroundVisual = compositor.CreateSpriteVisual(); 
_backgroundVisual.Brush = _gradientBrush; 
ElementCompositionPreview.SetElementChildVisual(Root, _backgroundVisual); 

// There are 3 animations going on here. 
// First, we kick off an EndPoint offset animation to create an special entrance scene. 
// Once it's finished, we then kick off TWO other animations simultaneously. 
// These TWO animations include a set of gradient stop color animations and 
// a rotation animation that rotates the gradient brush. 

var linearEase = compositor.CreateLinearEasingFunction(); 
var batch = compositor.CreateScopedBatch(CompositionBatchTypes.Animation); 
batch.Completed += (s, e) => 
{ 
    StartGradientColorAnimations(); 
    StartGradientRotationAnimation(); 
}; 
var endPointOffsetAnimation = compositor.CreateVector2KeyFrameAnimation(); 
endPointOffsetAnimation.Duration = TimeSpan.FromSeconds(3); 
endPointOffsetAnimation.InsertKeyFrame(1.0f, Vector2.One); 
_gradientBrush.StartAnimation(nameof(_gradientBrush.EndPoint), endPointOffsetAnimation); 
batch.End(); 

void StartGradientColorAnimations() 
{ 
    var color1Animation = compositor.CreateColorKeyFrameAnimation(); 
    color1Animation.Duration = TimeSpan.FromSeconds(10); 
    color1Animation.IterationBehavior = AnimationIterationBehavior.Forever; 
    color1Animation.Direction = AnimationDirection.Alternate; 
    color1Animation.InsertKeyFrame(0.0f, GradientStop1StartColor, linearEase); 
    color1Animation.InsertKeyFrame(0.5f, Color.FromArgb(255, 65, 88, 208), linearEase); 
    color1Animation.InsertKeyFrame(1.0f, Color.FromArgb(255, 43, 210, 255), linearEase); 
    gradientStop1.StartAnimation(nameof(gradientStop1.Color), color1Animation); 

    var color2Animation = compositor.CreateColorKeyFrameAnimation(); 
    color2Animation.Duration = TimeSpan.FromSeconds(10); 
    color2Animation.IterationBehavior = AnimationIterationBehavior.Forever; 
    color2Animation.Direction = AnimationDirection.Alternate; 
    color2Animation.InsertKeyFrame(0.0f, GradientStop2StartColor, linearEase); 
    color1Animation.InsertKeyFrame(0.5f, Color.FromArgb(255, 200, 80, 192), linearEase); 
    color2Animation.InsertKeyFrame(1.0f, Color.FromArgb(255, 43, 255, 136), linearEase); 
    gradientStop2.StartAnimation(nameof(gradientStop2.Color), color2Animation); 
} 

void StartGradientRotationAnimation() 
{ 
    var rotationAnimation = compositor.CreateScalarKeyFrameAnimation(); 
    rotationAnimation.Duration = TimeSpan.FromSeconds(15); 
    rotationAnimation.IterationBehavior = AnimationIterationBehavior.Forever; 
    rotationAnimation.InsertKeyFrame(1.0f, 360.0f, linearEase); 
    _gradientBrush.StartAnimation(nameof(_gradientBrush.RotationAngleInDegrees), rotationAnimation); 
} 

下面是工作sample和下面是它的样子。 :)

enter image description here

+0

在我原来的问题中,我只需要从动画中删除'BeginTime',以使其平滑。但我真的很欣赏这种努力。 – Ahmar