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

ASP.NET Core Blazor中SKGLView触摸事件缺失OffsetX/Y如何处理?

问题解答

为什么TouchEventArgs没有OffsetX/OffsetY?

Blazor的TouchEventArgs映射的是浏览器DOM规范中的Touch对象,而原生DOM的Touch接口本身就没有OffsetX、OffsetY属性——这两个属性是MouseEvent独有的,专门用于直接获取相对于事件触发元素的坐标偏移量。Touch对象只提供了基于屏幕、文档、视口的坐标(ScreenX/PageX/ClientX),需要开发者自行计算相对于目标元素的偏移。

实现触摸坐标与鼠标坐标一致的方法

要让触摸事件得到和鼠标事件OffsetX/OffsetY等价的坐标,需要手动计算触摸点相对于SKGLView元素的位置,步骤如下:

1. 给SKGLView添加ElementReference

修改组件代码,添加引用以便获取元素位置:

<SKGLView @ref="_skglViewRef"
     @ontouchstart="touchstart" @ontouchmove="touchmove" @ontouchend="touchend"
     @onmousedown="mousedown" @onmousemove="mousemove" 
     @onmouseup="mouseup" @onwheel="mousewheel" />

对应的C#字段:

private ElementReference _skglViewRef;

2. 编写JS互操作方法获取元素位置

在wwwroot下的JS文件(比如site.js)中添加获取元素BoundingClientRect的方法:

window.getElementRect = async (element) => {
    const rect = element.getBoundingClientRect();
    return {
        left: rect.left,
        top: rect.top,
        width: rect.width,
        height: rect.height
    };
};

3. 在触摸事件中计算相对坐标

修改触摸事件处理函数,通过JS获取元素位置后计算偏移:

private async void touchstart(TouchEventArgs args)
{
    var rect = await JS.InvokeAsync<ElementRect>(_skglViewRef, "getElementRect");
    for (int i = 0; i < args.TargetTouches.Length; i++)
    {
        var touch = args.TargetTouches[i];
        // 计算相对于SKGLView的偏移,等价于MouseEventArgs.OffsetX/Y
        var offsetX = (touch.ClientX - rect.Left) * m_dpiScale;
        var offsetY = (touch.ClientY - rect.Top) * m_dpiScale;
        TouchLocation pos = new TouchLocation((int)touch.Identifier, offsetX, offsetY, TouchLocationState.Pressed);
    }
}

// 用于接收JS返回的元素矩形结构
public class ElementRect
{
    public double Left { get; set; }
    public double Top { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
}

4. 优化:缓存元素位置(可选)

如果SKGLView元素不会动态改变大小或位置,可以缓存ElementRect的值,避免每次触摸事件都调用JS,提升性能:

private ElementRect? _cachedRect;

private async Task UpdateElementRect()
{
    _cachedRect = await JS.InvokeAsync<ElementRect>(_skglViewRef, "getElementRect");
}

// 在组件初始化或元素尺寸变化时调用UpdateElementRect
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await UpdateElementRect();
    }
}

这样计算出来的offsetX和offsetY就和鼠标事件的OffsetX/OffsetY效果完全一致了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:57:05