SkiaSharp 之 WPF 自绘 五环弹动球(案例版)

  • SkiaSharp 之 WPF 自绘 五环弹动球(案例版)已关闭评论
  • 157 次浏览
  • A+
所属分类:.NET技术
摘要

此案例基于拖曳和弹动球两个技术功能实现,如有不懂的可以参考之前的相关文章,属于递进式教程。


此案例基于拖曳和弹动球两个技术功能实现,如有不懂的可以参考之前的相关文章,属于递进式教程。

五环弹动球

好吧,名字是我起的,其实,你可以任意个球进行联动弹动,效果还是很不错的,有很多前端都是基于这个特效,可以搞出一些很有科技感的效果出来。

Wpf 和 SkiaSharp

新建一个WPF项目,然后,Nuget包即可
要添加Nuget包

Install-Package SkiaSharp.Views.WPF -Version 2.88.0 

其中核心逻辑是这部分,会以我设置的60FPS来刷新当前的画板。

skContainer.PaintSurface += SkContainer_PaintSurface; _ = Task.Run(() => {     while (true)     {         try         {             Dispatcher.Invoke(() =>             {                 skContainer.InvalidateVisual();             });             _ = SpinWait.SpinUntil(() => false, 1000 / 60);//每秒60帧         }         catch         {             break;         }     } }); 

弹球实体代码 (Ball.cs)

public class Ball {     public double X { get; set; }     public double Y { get; set; }     public double VX { get; set; }     public double VY { get; set; }     public int Radius { get; set; }     public bool Dragged { get; set; } = false;     public SKColor sKColor { get; set; } = SKColors.Blue;     public bool CheckPoint(SKPoint sKPoint)     {         var d = Math.Sqrt(Math.Pow(sKPoint.X - X, 2) + Math.Pow(sKPoint.Y - Y, 2));         return this.Radius >= d;     } } 

五环弹动核心类 (FiveRings.cs)

/// <summary> /// 五环弹球 /// </summary> public class FiveRings {     public SKPoint centerPoint;     public int Radius = 0;     public int BallLength = 8;      public double TargetX;     public double Spring = 0.03;     public double SpringLength = 200;     public double Friction = 0.95;     public List<Ball>? Balls;     public Ball? draggedBall;     public void init(SKCanvas canvas, SKTypeface Font, int Width, int Height)     {         if (Balls == null)         {             Balls = new List<Ball>();             for (int i = 0; i < BallLength; i++)             {                 Random random = new Random((int)DateTime.Now.Ticks);                 Balls.Add(new Ball()                 {                     X = random.Next(50, Width - 50),                     Y = random.Next(50, Height - 50),                     Radius = this.Radius                 });             }         }     }     /// <summary>     /// 渲染     /// </summary>     public void Render(SKCanvas canvas, SKTypeface Font, int Width, int Height)     {         centerPoint = new SKPoint(Width / 2, Height / 2);         this.Radius = 20;         this.TargetX = Width / 2;         init(canvas, Font, Width, Height);         canvas.Clear(SKColors.White);           //划线         using var LinePaint = new SKPaint         {             Color = SKColors.Green,             Style = SKPaintStyle.Fill,             StrokeWidth = 3,             IsStroke = true,             StrokeCap = SKStrokeCap.Round,             IsAntialias = true         };         SKPath path = null;         foreach (var item in Balls)         {             if (path == null)             {                 path = new SKPath();                 path.MoveTo((float)item.X, (float)item.Y);             }             else             {                 path.LineTo((float)item.X, (float)item.Y);             }         }         path.Close();         canvas.DrawPath(path, LinePaint);           foreach (var item in Balls)         {             if (!item.Dragged)             {                 foreach (var ball in Balls.Where(t => t != item).ToList())                 {                     SpringTo(item, ball);                 }             }             DrawCircle(canvas, item);         }          using var paint = new SKPaint         {             Color = SKColors.Blue,             IsAntialias = true,             Typeface = Font,             TextSize = 24         };         string by = $"by 蓝创精英团队";         canvas.DrawText(by, 600, 400, paint);      }     /// <summary>     /// 画一个圆     /// </summary>     public void DrawCircle(SKCanvas canvas, Ball ball)     {         using var paint = new SKPaint         {             Color = SKColors.Blue,             Style = SKPaintStyle.Fill,             IsAntialias = true,             StrokeWidth = 2         };         canvas.DrawCircle((float)ball.X, (float)ball.Y, ball.Radius, paint);     }     public void MouseMove(SKPoint sKPoint)     {         if (draggedBall != null)         {             draggedBall.X = sKPoint.X;             draggedBall.Y = sKPoint.Y;         }     }     public void MouseDown(SKPoint sKPoint)     {         foreach (var item in Balls)         {             if (item.CheckPoint(sKPoint))             {                 item.Dragged = true;                 draggedBall = item;             }             else             {                 item.Dragged = false;             }         }     }     public void MouseUp(SKPoint sKPoint)     {         draggedBall = null;         foreach (var item in Balls)         {             item.Dragged = false;         }     }     public void SpringTo(Ball b1, Ball b2)     {         var dx = b2.X - b1.X;         var dy = b2.Y - b1.Y;         var angle = Math.Atan2(dy, dx);         var targetX = b2.X - SpringLength * Math.Cos(angle);         var targetY = b2.Y - SpringLength * Math.Sin(angle);          b1.VX += (targetX - b1.X) * Spring;         b1.VY += (targetY - b1.Y) * Spring;          b1.VX *= Friction;         b1.VY *= Friction;          b1.X += b1.VX;         b1.Y += b1.VY;     } } 

效果如下:

SkiaSharp 之 WPF 自绘 五环弹动球(案例版)

这个特效用的好,也能产生一些神奇的效果。

总结

这次是结合拖曳和弹动效果实现的综合案例,效果还是很不错的,之前也没想到原来还可以这样玩,拓展了玩法啊。

代码地址

https://github.com/kesshei/WPFSkiaFiveRingsDemo.git

https://gitee.com/kesshei/WPFSkiaFiveRingsDemo.git

一键三连呦!,感谢大佬的支持,您的支持就是我的动力!

版权

蓝创精英团队(公众号同名,CSDN同名,CNBlogs同名)