当前位置:网站首页>SkiaSharp 之 WPF 自绘 五环弹动球(案例版)
SkiaSharp 之 WPF 自绘 五环弹动球(案例版)
2022-08-03 03:33:00 【dotNET跨平台】
此案例基于拖曳和弹动球两个技术功能实现,如有不懂的可以参考之前的相关文章,属于递进式教程。
五环弹动球
好吧,名字是我起的,其实,你可以任意个球进行联动弹动,效果还是很不错的,有很多前端都是基于这个特效,可以搞出一些很有科技感的效果出来。
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同名)
边栏推荐
- Jincang Database Pro*C Migration Guide ( 5. Program Development Example)
- compose 位移视图
- 瑞鹄转债上市价格预测
- voliate关键字
- 【数据分析】基于MATLAB实现SVDD决策边界可视化
- 基于flowable的upp(统一流程平台)运行性能优化(2)
- Ask next useful SQL server flink - SQL - connector - essentially a CDC - 2
- log4j设置日志的时区
- 数字3d虚拟交互展厅顺应时代发展需求和趋势
- Chinese valentine's day??To the liver is the way!!!!!Auto. Js special position control method
猜你喜欢

Best Practices for Migration from Jincang Database from MySQL to KingbaseES (3. MySQL Database Migration Practice)

在VScode里调试ROS程序

voliate关键字

【剑指offer】——16.数值的整数次方

用 SQL 做数据分析的十大常用功能,附面试原题解答!!

Chapter 8 Character Input Output and Input Validation

【基础数学--埃氏筛】204. 计数质数

Auto.js Pro write the first script hello world

2022-08-02 顾宇佳 学习笔记 多线程

【TA-霜狼_may-《百人计划》】美术2.5 模型常见问题及规范
随机推荐
uniapp运行到手机,基座提示本应用无法独立运行,需要与hbuilderX 搭配使用
详细讲解一下JVM的内存模型与实现?
ROS2自学笔记:机器视觉基础
QT之鼠标和键盘事件重写
七夕??继续肝文章才是正道!!Auto.js 特殊定位控件方法
vscode access denied to unins000.exe
Kotlin multiplication, how do I multiply smaller and smaller?
信号和槽的绑定
PyTorch installation - error when building a virtual environment in conda before installing PyTorch
Senior ClickHouse -
高等代数_笔记_配方法标准化二次型
找不到符号@SuperBuilder,你以为真的是Lombok的问题?
单元测试是什么?怎么写?主要测试什么?
【笔记】混淆矩阵和ROC曲线
mysql8默认密码丢失,如何更改密码详细步骤??
Methods annotated with ‘@Async‘ must be overridable
log4j设置日志的时区
OneNote 教程,如何在 OneNote 中设置笔记格式?
软件测试个人求职简历该怎么写,模板在这里
【obs】启动推流失败 : Output.StartStreamFailed 调用流程