.NET MAUI的Android WiFi图传开发(6)——利用SkiaSharp制作一个摇杆
上期我们利用FFImageLoad实现了图片流的显示,之前也有一期简单介绍了一下利用SkiaSharp实现绘图。
本期我们来实现一个摇杆的实现。
public class DrawAble
{
private readonly Rocker view;
public DrawAble(Rocker view)
{
this.view = view;
}
private void Draw_Circle(SKSurface surface, SKRect bounds)
{
float centerX = bounds.MidX;
float centerY = bounds.MidY;
Midx = centerX;
Midy = centerY;
// 计算圆的半径(使用ChargingRingDrawable类中的rad属性)
float radius = CirCleRad;
// 使用SKPaint对象定义圆的样式(颜色、线条宽度等)
using (SKPaint paint = new SKPaint())
{
paint.Color = SKColors.Blue;
paint.Style = SKPaintStyle.Stroke;
paint.StrokeWidth = 20;
// 画圆
surface.Canvas.DrawCircle(centerX, centerY, radius, paint);
}
}
public void Draw(SKSurface surface, SKRect bounds)
{
surface.Canvas.Clear();
Draw_Circle(surface, bounds);//画圆轮廓
}
}
首先定义两个类,一个是画板类,他必须有最基本的Draw函数用来给Sharp实现接口。
其构造函数传入我们的Rocker类,这个类我们在下面定义。
public partial class Rocker : SKCanvasView
{
private readonly DrawAble drawable;
public Rocker()
{
this.EnableTouchEvents = true;//
this.drawable = new ChargingRingDrawable(this);
}
protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
{
this.drawable.Draw(e.Surface, e.Info.Rect);
this.InvalidateSurface();
}
protected override void OnTouch(SKTouchEventArgs e)
{
base.OnTouch(e);
}
}
}
接着定义一个类,命名为Rocker,这个类抽象自SKCanvasView(SkiaSharp的控件)
定义一个画板,构造的时候传入自身。
我们要保留两个处理函数,一个是OnPaintSurface,我们的控件刷新就会调用这个函数,还有一个是OnTouch函数,这个函数用来处理我们的触摸事件。
private void Draw_Circle(SKSurface surface, SKRect bounds)
{
float centerX = bounds.MidX;//获得画板中心
float centerY = bounds.MidY;
Midx = centerX;//用一个参数保存画板中心
Midy = centerY;
// 计算圆的半径(使用ChargingRingDrawable类中的rad属性)
float radius = CirCleRad;
// 使用SKPaint对象定义圆的样式(颜色、线条宽度等)
using (SKPaint paint = new SKPaint())
{
paint.Color = SKColors.Blue;
paint.Style = SKPaintStyle.Stroke;
paint.StrokeWidth = 20;
// 画圆
surface.Canvas.DrawCircle(centerX, centerY, radius, paint);
}
}
在DrawAble类中有这样子一个函数,其作用是画一个基本的圆,我设置的大小是400像素。
private void Draw_InsertCircle(SKCanvas canvas, SKPoint touchLocation, float radius)
{
// 控件的中心点
float centerX = Midx;
float centerY = Midy;
// 计算手的位置与圆的交点
SKPoint intersectionPoint = CalculateIntersectionPoint(centerX, centerY, 300, touchLocation);
// 使用SKPaint对象定义圆的样式(颜色、线条宽度等)
using (SKPaint paint = new SKPaint())
{
paint.Color = SKColors.Red;
paint.Style = SKPaintStyle.Fill;
// 在交点位置绘制圆
canvas.DrawCircle(intersectionPoint.X, intersectionPoint.Y, radius, paint);
LocationPoint = intersectionPoint;
}
}
private SKPoint CalculateIntersectionPoint(float centerX, float centerY, float radius, SKPoint touchLocation)
{
// 计算手的位置与圆的交点
float dx = touchLocation.X - centerX;
float dy = touchLocation.Y - centerY;
float distance = (float)Math.Sqrt(dx * dx + dy * dy);
// 如果距离超出阈值,将交点移动到圆上最近的点
if (distance > radius)
{
float scale = radius / distance;
float intersectionX = centerX + dx * scale;
float intersectionY = centerY + dy * scale;
return new SKPoint(intersectionX, intersectionY);
}
// 如果距离未超出阈值,则返回手的位置作为交点
return touchLocation;
}
接着画内部的摇杆内容,我们计算这个圆和控件中心的位置,设置一个阈值,保证我们画的圆在这个阈值之内,如果超过了阈值,就计算手的位置和圆的交点,再进行画圆。

实现这样子的效果。
接着,我们补全Rocker中触摸事件
protected override void OnTouch(SKTouchEventArgs e)
{
base.OnTouch(e);
switch (e.ActionType)
{
case SKTouchAction.Pressed:
// 处理按下事件
break;
case SKTouchAction.Moved:
// 处理移动事件
SKPoint touchLocation = e.Location;
drawable.InsertCirclePoint = touchLocation;
OnPositionChanged(new SKPoint(drawable.LocationPoint.X-drawable.Midx,drawable.LocationPoint.Y-drawable.Midy));
break;
case SKTouchAction.Released:
SKPoint InsertCirclePoint = new SKPoint(drawable.Midx,drawable.Midy);
drawable.InsertCirclePoint = InsertCirclePoint;
// 使得画布无效,触发重绘
InvalidateSurface();
OnPositionChanged(new SKPoint(0,0));
break;
case SKTouchAction.Cancelled:
// 处理取消事件
break;
}
// 标记事件已处理
e.Handled = true;
}
当移动时,将位置传给DrawAble中,DrawAble会根据手的位置绘制摇杆位置。
并且在放下的时候重新归位。
同时我们定义一个事件,向MainPage中传入位置信息。
private void Rocker_PositionChanged(object sender, SKPoint newPosition)
{
Label.Text = $"Position: ({newPosition.X}, {newPosition.Y})";
}
MainPage中打印我们的位置信息。



登录 或 注册 后才可以进行评论哦!
还没有评论,抢个沙发!