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
相关产品推荐
相关产品推荐

