用波浪动画填充椭圆

我已经在Windows Phone 8.1 Silverlight App和UWP中创建了一个椭圆,我想用动画波填充它,为此,我正在遵循这个解决方案

但它适用于WPF,所以我无法使用像“Visual Brush”这样的控件。

我想用类似于此的波填充椭圆(在图像中忽略50%) –

在此处输入图像描述

这是我的eliipse

  

视觉刷上的任何替代品? 主要是我想在Windows Phone 8.1 Silverlight中实现它,但是如果它在WP平台上不可用,我将切换到UWP

在给你代码之前,看看下面这个动画gif ,试着理解如何创建这个动画。

在此处输入图像描述

有道理,对吗? 我们需要做的就是创建一个这样的形状,为其偏移X(无限)和Y(水位)设置动画,最后用椭圆剪切它。

首先,您需要使用Adobe Illustrator或类似工具来创建此形状。 在AI中 ,有一个Zig Zag效果(见下面的截图),这是完美的。 你只需要确保起点与结束点的位置相同,所以当你重复动画时,它会觉得它永远不会结束。

在此处输入图像描述

UWP目前缺少的是能够剪切具有非矩形形状的UIElement ,因此我们必须将其导出为png (否则我们将其导出为svg并使用Path来显示它)。

同样出于同样的原因,剪切部分需要大量的工作。 就像Je​​t Chopper的回答一样,只需要大量的代码来获得surfaceBrush ! 更不用说您还需要手动处理设备丢失和应用程序生命周期。

值得庆幸的是,在Creators Update(即15063 )中,有一个名为LoadedImageSurface的新API,它通过带有几行代码的图像uri创建一个CompositionSurfaceBrush 。 在我下面的代码示例中,您将看到我使用它,这意味着,如果您想支持旧版本的Windows 10,则需要将其替换为Jet的答案中的内容。

我们的想法是创建一个名为WaveProgressControl的UserControl,它封装了所有动画逻辑,并公开了一个名为Percent的依赖属性,用于控制水位

WaveProgressControl控件 – XAML

           

WaveProgressControl控件 – 代码隐藏

 private readonly Compositor _compositor; private readonly CompositionPropertySet _percentPropertySet; public WaveProgressControl() { InitializeComponent(); _compositor = Window.Current.Compositor; _percentPropertySet = _compositor.CreatePropertySet(); _percentPropertySet.InsertScalar("Value", 0.0f); Loaded += OnLoaded; } public double Percent { get => (double)GetValue(PercentProperty); set => SetValue(PercentProperty, value); } public static readonly DependencyProperty PercentProperty = DependencyProperty.Register("Percent", typeof(double), typeof(WaveProgressControl), new PropertyMetadata(0.0d, (s, e) => { var self = (WaveProgressControl)s; var propertySet = self._percentPropertySet; propertySet.InsertScalar("Value", Convert.ToSingle(e.NewValue) / 100); })); private void OnLoaded(object sender, RoutedEventArgs e) { CompositionSurfaceBrush imageSurfaceBrush; SetupClippedWaveImage(); SetupEndlessWaveAnimationOnXAxis(); SetupExpressionAnimationOnYAxisBasedOnPercentValue(); void SetupClippedWaveImage() { // Note LoadedImageSurface is only available in 15063 onward. var imageSurface = LoadedImageSurface.StartLoadFromUri(new Uri(BaseUri, "/Assets/wave.png")); imageSurfaceBrush = _compositor.CreateSurfaceBrush(imageSurface); imageSurfaceBrush.Stretch = CompositionStretch.None; imageSurfaceBrush.Offset = new Vector2(120, 248); var maskBrush = _compositor.CreateMaskBrush(); var maskSurfaceBrush = ClippedImageContainer.GetAlphaMask(); // CompositionSurfaceBrush maskBrush.Mask = maskSurfaceBrush; maskBrush.Source = imageSurfaceBrush; var imageVisual = _compositor.CreateSpriteVisual(); imageVisual.RelativeSizeAdjustment = Vector2.One; ElementCompositionPreview.SetElementChildVisual(ClippedImageContainer, imageVisual); imageVisual.Brush = maskBrush; } void SetupEndlessWaveAnimationOnXAxis() { var waveOffsetXAnimation = _compositor.CreateScalarKeyFrameAnimation(); waveOffsetXAnimation.InsertKeyFrame(1.0f, -80.0f, _compositor.CreateLinearEasingFunction()); waveOffsetXAnimation.Duration = TimeSpan.FromSeconds(1); waveOffsetXAnimation.IterationBehavior = AnimationIterationBehavior.Forever; imageSurfaceBrush.StartAnimation("Offset.X", waveOffsetXAnimation); } void SetupExpressionAnimationOnYAxisBasedOnPercentValue() { var waveOffsetYExpressionAnimation = _compositor.CreateExpressionAnimation("Lerp(248.0f, 120.0f, Percent.Value)"); waveOffsetYExpressionAnimation.SetReferenceParameter("Percent", _percentPropertySet); imageSurfaceBrush.StartAnimation("Offset.Y", waveOffsetYExpressionAnimation); } } 

MainPage

         

我已将所有内容都放入此示例项目中 ,下面是一个现场演示。 请享用! 🙂

在此处输入图像描述

这是UWP样本。 您可以根据需要进行调整:

     

和代码背后:

  private async void CreateVisuals() { var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; var bitmap = await CanvasBitmap.LoadAsync(CanvasDevice.GetSharedDevice(), new Uri("ms-appx:///Assets/Wave-PNG-Transparent-Picture.png")); var drawingSurface = CanvasComposition.CreateCompositionGraphicsDevice(compositor, CanvasDevice.GetSharedDevice()) .CreateDrawingSurface(bitmap.Size, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); using (var ds = CanvasComposition.CreateDrawingSession(drawingSurface)) { ds.Clear(Colors.Transparent); ds.DrawImage(bitmap); } var surfaceBrush = compositor.CreateSurfaceBrush(drawingSurface); surfaceBrush.Stretch = CompositionStretch.None; var maskedBrush = compositor.CreateMaskBrush(); maskedBrush.Mask = Ellipse.GetAlphaMask(); maskedBrush.Source = surfaceBrush; var sprite = compositor.CreateSpriteVisual(); sprite.Size = new Vector2((float)Ellipse.Width, (float)Ellipse.Height); sprite.Brush = maskedBrush; sprite.CenterPoint = new Vector3(sprite.Size / 2, 0); sprite.Scale = new Vector3(0.9f); ElementCompositionPreview.SetElementChildVisual(VisualBorder, sprite); var offsetAnimation = compositor.CreateScalarKeyFrameAnimation(); offsetAnimation.InsertKeyFrame(0, 0); offsetAnimation.InsertKeyFrame(1, 256, compositor.CreateLinearEasingFunction()); offsetAnimation.Duration = TimeSpan.FromMilliseconds(1000); offsetAnimation.IterationBehavior = AnimationIterationBehavior.Forever; surfaceBrush.StartAnimation("Offset.X", offsetAnimation); } } 

这是它的样子:

在此处输入图像描述

我用一个简单的解决方案实现了这个目标

Wave2.png是一个扩展(复制粘贴图像并添加到第一个图像的末尾)以使其更长。

该解决方案适用于WP8 / Store apps / UWP / Silverlight

在此处输入图像描述

               

这是动画代码: