转换路径上的命中测试不正确

时间:2013-10-11 17:36:16

标签: wpf xaml

输入命中测试会在RenderTransform属性中具有较大缩放系数的Path元素上产生不正确的结果。

以下XAML定义了一个带有实心圆和Hand光标的路径。

<Canvas Background="LightGray">
    <Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
        <Path.Data>
            <EllipseGeometry RadiusX=".5" RadiusY=".5" Center="1,1"/>
        </Path.Data>
        <Path.RenderTransform>
            <ScaleTransform ScaleX="150" ScaleY="150"/>
        </Path.RenderTransform>
    </Path>
</Canvas>

如下图所示,尽管Hand光标的位置超出了形状,但仍会出现<Canvas Background="LightGray"> <Path StrokeThickness="0" Fill="Blue" Cursor="Hand"> <Path.Data> <EllipseGeometry RadiusX="50" RadiusY="50" Center="100,100"/> </Path.Data> <Path.RenderTransform> <ScaleTransform ScaleX="1.5" ScaleY="1.5"/> </Path.RenderTransform> </Path> </Canvas> 光标。

enter image description here

使用较大的Path和较小的缩放因子,问题消失,Cursor的行为与预期一致。

private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    var canvas = (UIElement)sender;
    var hitElement = canvas.InputHitTest(e.GetPosition(canvas));
    Trace.TraceInformation("hitElement = {0}", hitElement);
}

enter image description here

执行像这样的明确命中测试

Geometry.Transform
在Canvas上的鼠标事件处理程序中的

给出了相同的错误结果。在缩放路径之外清楚地点击鼠标仍然会将Path作为命中元素返回。

值得注意的是,Silverlight中没有出现此问题。


现在的问题是:这种行为的原因是什么,如何避免?请注意,我不能简单地更改Path元素的原始大小,因此像“不使用大比例因子”这样的答案将没有用。

我目前的解决方法不是通过RenderTransform转换Path,而是转换Data(通过将转换应用于<Canvas Background="LightGray"> <Path StrokeThickness="0" Fill="Blue" Cursor="Hand"> <Path.Data> <RectangleGeometry Rect=".5,.5,1,1"/> </Path.Data> <Path.RenderTransform> <TransformGroup> <ScaleTransform ScaleX="150" ScaleY="150"/> <RotateTransform Angle="45" CenterX="150" CenterY="150"/> <TranslateTransform X="100"/> </TransformGroup> </Path.RenderTransform> </Path> </Canvas> 属性)。但由于可能存在复杂的填充(例如使用ImageBrush),我也必须转换填充画笔(这不仅涉及设置变换,还涉及它们的视口)。

此外,实际变换不仅是缩放,而且是一个也可以旋转和翻译的MatrixTransform。


值得注意的是,问题也出现在其他几何形状和其他变换中。例如,带有RectangleGeometry的转换路径显示类似的错误行为。

大比例因子不正确:

<Canvas Background="LightGray">
    <Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
        <Path.Data>
            <RectangleGeometry Rect="50,50,100,100"/>
        </Path.Data>
        <Path.RenderTransform>
            <TransformGroup>
                <ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
                <RotateTransform Angle="45" CenterX="150" CenterY="150"/>
                <TranslateTransform X="100"/>
            </TransformGroup>
        </Path.RenderTransform>
    </Path>
</Canvas>

enter image description here

用小比例因子纠正:

{{1}}

enter image description here

1 个答案:

答案 0 :(得分:4)

更多的评论而不是答案:

这似乎是一种奇怪的行为,我玩了一些Paths,并尝试使用Geometry.GetWidenedPathGeometry对数据本身应用稍微不同的缩放效果,但没有走得太远。 / p>

问题的根本原因似乎是在WPF中选择命中检测容忍度的方式,Brendan Clark对MSDN上的类似问题有两个答案,它似乎从未被修复过。

基本上,使用的命中测试容差似乎是从几何体本身的基本大小派生的绝对值,而不是渲染/转换的大小。因此,虽然这对于大型造型来说很好,但是你要做得更小,或者实际上是小型造型,当你放大时(如你所发现的那样)它会开始变得非常不准确。

即。相对于小形状的尺寸来说,小的击中测试公差很好,但是当形状和公差都扩大时,开始看起来很糟糕。

在一个线程中提出的解决方案是将形状缩放到您需要的最大尺寸,并在您希望它们变小时缩小它们(这对您来说不是解决方案)。 EW。

看起来你可能会陷入一些转变。我会试着看看能不能做得更好。

我正在看的链接:

http://social.msdn.microsoft.com/Forums/vstudio/en-US/8708e340-f734-4cf4-b91d-28b49fee2b72/hittest-is-buggy-not-accurate-for-transformed-scaled-etc-visuals?forum=wpf

http://social.msdn.microsoft.com/Forums/vstudio/en-US/b307676b-d8b2-4af0-9f6f-1e150eed97ba/hittesting-with-a-scaled-path-doesnt-work?forum=wpf