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>
このような明示的なヒット テストを実行する
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var canvas = (UIElement)sender;
var hitElement = canvas.InputHitTest(e.GetPosition(canvas));
Trace.TraceInformation("hitElement = {0}", hitElement);
}
キャンバス上のマウス イベント ハンドラーで、同じ誤った結果が得られます。スケーリングされたパスの外側でマウス クリックを行うと、パスがヒット要素として返されます。
この問題は Silverlight では発生しないことにも注意してください。
ここでの問題は、この動作の原因は何ですか?また、どのように回避できるのでしょうか? Path 要素の元のサイズを単純に変更することはできないため、「大きな倍率を使用しないでください」などの回答は役に立ちません。
私の現在の回避策は、パスを RenderTransform で変換するのではなく、代わりにデータを変換することです (変換をGeometry.Transform
プロパティに適用することによって)。ただし、複雑な塗りつぶし (ImageBrush など) が存在する可能性があるため、塗りつぶしブラシも変換する必要があります (これには、変換だけでなく、ビューポートの設定も含まれます)。
さらに、実際の変換はスケーリングだけでなく、回転と移動も行う MatrixTransform です。
この問題は、他のジオメトリや追加の変換でも発生することに注意してください。たとえば、RectangleGeometry で変換された Path は、同様に正しくない動作を示します。
倍率が大きいと正しくない:
<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>
小さな倍率で修正する:
<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>