You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SkiaSharp中如何为饼图扇形块绑定触摸点击事件以展示对应信息?

SkiaSharp 饼图扇形点击交互实现方案

SkiaSharp 本身没有提供绘制元素的内置事件绑定,你可以通过「存储扇形元数据+坐标碰撞检测」的方式实现需求,具体实现步骤如下:

  • 步骤1:定义扇形数据结构,存储每个扇形的关联参数
    绘制饼图时不要只做渲染逻辑,提前把每个扇形的核心参数、要绑定的业务数据存入自定义结构,方便后续碰撞检测调用:
public class PieSlice
{
    // 扇形基础绘制参数
    public float StartAngle { get; set; } // 起始角度,单位:度
    public float SweepAngle { get; set; } // 扫过角度,单位:度
    public SKPoint Center { get; set; } // 饼图圆心坐标
    public float Radius { get; set; } // 饼图半径
    // 如果是环形饼图可新增 InnerRadius 属性
    public float? InnerRadius { get; set; }

    // 自定义绑定字段,存储扇形对应的关联信息
    public object BindData { get; set; }
}

绘制完成后将所有扇形实例存入全局的 List<PieSlice> 集合中备用。

饼图示例

  • 步骤2:监听SKCanvasView的触摸事件
    给承载绘制内容的SKCanvasView添加触摸事件监听,注意要将触摸点的视图坐标转换为画布实际坐标(如果画布有缩放、平移变换,需要用画布变换矩阵的逆矩阵做坐标转换):
// 注册触摸事件
canvasView.Touch += OnCanvasTouch;

private void OnCanvasTouch(object sender, SKTouchEventArgs e)
{
    // 推荐在抬手时触发点击,减少误触
    if (e.ActionType != SKTouchAction.Released) return;

    SKPoint touchPoint = e.Location;
    // 若画布有缩放/平移,需额外做坐标转换,示例:
    // touchPoint = canvas.TotalMatrix.Invert().MapPoint(touchPoint);

    // 遍历所有扇形做碰撞检测
    foreach (var slice in _pieSlices)
    {
        if (IsPointInSlice(slice, touchPoint))
        {
            // 匹配到点击的扇形,触发自定义回调,传入绑定数据
            OnSliceClicked(slice.BindData);
            e.Handled = true;
            break;
        }
    }
}
  • 步骤3:实现扇形区域碰撞检测逻辑
    通过极坐标转换判断触摸点是否落在扇形范围内:
private bool IsPointInSlice(PieSlice slice, SKPoint point)
{
    // 1. 计算触摸点到圆心的距离,判断是否在半径范围内
    double dx = point.X - slice.Center.X;
    double dy = point.Y - slice.Center.Y;
    double distance = Math.Sqrt(dx * dx + dy * dy);
    
    if (distance > slice.Radius) return false;
    // 环形饼图额外判断内半径
    if (slice.InnerRadius.HasValue && distance < slice.InnerRadius.Value) return false;

    // 2. 计算触摸点相对于圆心的角度,统一转换为0-360度范围
    double radian = Math.Atan2(dy, dx);
    double degree = radian * 180 / Math.PI;
    degree = degree < 0 ? degree + 360 : degree;

    // 3. 判断角度是否落在扇形的角度区间内
    float endAngle = slice.StartAngle + slice.SweepAngle;
    if (endAngle <= 360)
    {
        return degree >= slice.StartAngle && degree <= endAngle;
    }
    else
    {
        // 处理跨360度的扇形边界
        return degree >= slice.StartAngle || degree <= endAngle - 360;
    }
}
  • 步骤4:实现自定义回调逻辑
    在 OnSliceClicked 方法中处理你需要的业务逻辑,比如弹窗展示扇形对应的关联信息即可。

注意事项

如果你的饼图做了高亮、偏移等选中态效果,匹配到扇形后可以给对应扇形加标识,调用Invalidate()方法重绘画布展示选中效果。

内容的提问来源于stack exchange,提问作者Betsq9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 17:15:01