- 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; } }
效果如下:
这个特效用的好,也能产生一些神奇的效果。
总结
这次是结合拖曳和弹动效果实现的综合案例,效果还是很不错的,之前也没想到原来还可以这样玩,拓展了玩法啊。
代码地址
https://github.com/kesshei/WPFSkiaFiveRingsDemo.git
https://gitee.com/kesshei/WPFSkiaFiveRingsDemo.git
阅
一键三连呦!,感谢大佬的支持,您的支持就是我的动力!
版权
蓝创精英团队(公众号同名,CSDN同名,CNBlogs同名)