WPF+SkiaSharp实现自绘拖曳小球
作者:蓝创精英团队 发布时间:2023-03-25 01:31:14
标签:WPF,SkiaSharp,拖曳
拖曳小球
WPF的拖曳效果,基本配置一下,就可以了,但是自绘的话,就得自己控制,按键点击,按键移动和按键松开的事件,与其配合达到目的。
这个效果实现了,其实也变相的实现了WPF里的拖动效果,这个效果用着还是很方便的。
但是代码,确十分的简单。
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;
}
}
});
实现代码
鼠标按下,移动,鼠标松开
先对SkiaSharp对象,增加相关事件
skContainer.MouseDown += SkContainer_MouseDown;
skContainer.MouseUp += SkContainer_MouseUp;
skContainer.MouseMove += SkContainer_MouseMove;
然后增加相关事件处理代码,我这边都统一处理了.
private void SkContainer_MouseDown(object sender, MouseButtonEventArgs e)
{
var cur = e.GetPosition(sender as IInputElement);
drawClock.MouseDown(new SKPoint((float)cur.X, (float)cur.Y), true);
}
private void SkContainer_MouseUp(object sender, MouseEventArgs e)
{
var cur = e.GetPosition(sender as IInputElement);
drawClock.MouseDown(new SKPoint((float)cur.X, (float)cur.Y), false);
}
private void SkContainer_MouseMove(object sender, MouseEventArgs e)
{
var cur = e.GetPosition(sender as IInputElement);
drawClock.MouseMove(new SKPoint((float)cur.X, (float)cur.Y));
}
拖曳核心类
/// <summary>
/// 拖曳
/// </summary>
public class Drag
{
public SKPoint centerPoint;
public int Radius = 0;
private bool Pressed = false;
private bool CirclePressend = false;
private SKPoint sKPoint = SKPoint.Empty;
private SKPoint CirclePoint = SKPoint.Empty;
private SKCanvas canvas;
private float dx = 0;
private float dy = 0;
/// <summary>
/// 渲染
/// </summary>
public void Render(SKCanvas canvas, SKTypeface Font, int Width, int Height)
{
this.canvas = canvas;
centerPoint = new SKPoint(Width / 2, Height / 2);
this.Radius = 40;
canvas.Clear(SKColors.White);
if (CirclePoint.IsEmpty)
{
CirclePoint = new SKPoint(centerPoint.X, centerPoint.Y);
}
if (CirclePressend)
{
CirclePoint = new SKPoint(sKPoint.X - dx, sKPoint.Y - dy);
DrawCircle(this.canvas, CirclePoint);
}
else
{
DrawCircle(this.canvas, CirclePoint);
}
using var paint = new SKPaint
{
Color = SKColors.Black,
IsAntialias = true,
Typeface = Font,
TextSize = 24
};
var msg = $"X:{ sKPoint.X} Y:{sKPoint.Y} Pressed:{Pressed} CirclePressend:{CirclePressend}";
canvas.DrawText(msg, 0, 30, paint);
}
public void MouseMove(SKPoint sKPoint)
{
this.sKPoint = sKPoint;
if (CirclePressend)//按下,就开始拖动
{
CirclePoint = sKPoint;
}
}
public void MouseDown(SKPoint sKPoint, bool Pressed)
{
this.sKPoint = sKPoint;
this.Pressed = Pressed;
if (this.Pressed)
{
this.CirclePressend = CheckPoint(sKPoint, CirclePoint);
if (this.CirclePressend)
{
dx = sKPoint.X - CirclePoint.X;
dy = sKPoint.Y - CirclePoint.Y;
}
}
else
{
this.CirclePressend = false;
}
}
public bool CheckPoint(SKPoint sKPoint, SKPoint CirclePoint)
{
var d = Math.Sqrt(Math.Pow(sKPoint.X - CirclePoint.X, 2) + Math.Pow(sKPoint.Y - CirclePoint.Y, 2));
return this.Radius >= d;
}
/// <summary>
/// 画一个圆
/// </summary>
public void DrawCircle(SKCanvas canvas, SKPoint sKPoint)
{
using var paint = new SKPaint
{
Color = SKColors.Blue,
Style = SKPaintStyle.Fill,
IsAntialias = true,
StrokeWidth = 2
};
canvas.DrawCircle(sKPoint.X, sKPoint.Y, Radius, paint);
}
}
效果如下
我可以点的球的边边哦,这也是一个小技巧,点到球哪里,停止的时候,鼠标还在那个位置,是不是有点像拖动窗体的感觉了。
来源:https://www.cnblogs.com/kesshei/p/16526795.html
0
投稿
猜你喜欢
- SpringBoot多线程进行异步请求的处理近期在协会博客园中,有人发布了博客,系统进行查重的时候由于机器最低配置进行大量计算时需要十秒左右
- 目录微服务微服务架构SpringCould简介环境搭建1. 创建数据库2. 新建一个子模块api3. 新建一个子模块provider作为服务
- OverView今天在复习的时候,突然复习到我们的相机操作,但是对于相机操作,对于我来说比较复杂的是对于权限的操作。所有我们需要对我们的相机
- Synchronized的用法在多线程并发问题中,常用Synchronized锁解决问题。Synchronized锁通常用于同步示例方法,同
- 使用filter设置要排除的URL@WebFilter(urlPatterns = "/*")@Order(value
- 本文实例讲述了C#将指定目录所有文件名转换成小写的方法。分享给大家供大家参考。具体如下:using System;using System.
- @ModelAttribute在父类、子类的执行顺序被 @ModelAttribute 注解的方法会在Controller每个方法执行之前都
- Java获取环境变量Java 获取环境变量的方式很简单: System.getEnv() 得到所有的环境变量Syste
- 第一步。根据卷标,CPU序列号,生成机器码// 取得设备硬盘的卷标号
- 本文实例讲述了Java基于外观模式实现美食天下食谱功能。分享给大家供大家参考,具体如下:一、模式定义外观模式,是软件工程师常用的一种软件设计
- 在Java中,可以通过Runtime类或ProcessBuilder类来实现调用外部程序。Runtime类与ProcessBuilder类使
- 1.栈和队列的共同特点是(只允许在端点处插入和删除元素)4.栈通常采用的两种存储结构是(线性存储结构和链表存储结构)5.下列关于栈的叙述正确
- 本篇将从以下几个方面讲述反射的知识:class 的使用方法的反射构造函数的反射成员变量的反射一、什么是class类在面向对象的世界里,万物皆
- 本文实例讲述了Java对XML文件增删改查操作。分享给大家供大家参考,具体如下:xml文件:<?xml version="1
- 多表联合查询resultType的返回值一般数据按参数类型返回<select id="queryCarIdList"
- 1. 函数式接口的理解根据重构的思想,需要把容易变化的模块进行抽象并封装起来,从这个点来看,Java8新引入的函数式接口就是基于这个思想进行
- 一、目的本篇文章的目的是记录本人使用flutter加载与调用第三方aar包。二、背景本人go后端,业余时间喜欢玩玩flutter。一直有一个
- 背景Java是一种流行的编程语言,验证码是一种常用的网络安全技术。Java发展至今,网上也出现了各种各样的验证码,本人初学Java,下面是我
- 实现跨服务的远程调用(RestTemplate)业务场景:在返回订单信息数据中显示用户信息实现思路:基于RestTemplate发起的htt
- 循环语句就是让计算机根据条件做循环计算,在条件满足时继续循环,条件不满足时退出循环。Java提供了while条件循环。它的基本用法是:whi