此案例基于拖曳和彈動球兩個技術功能實現,如有不懂的可以參考之前的相關文章,屬于遞進式教程。
五環彈動球
好吧,名字是我起的,其實,你可以任意個球進行聯動彈動,效果還是很不錯的,有很多前端都是基于這個特效,可以搞出一些很有科技感的效果出來。
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同名)