2013-10-11 9 views
11

Il test di input hit produce risultati non corretti su un elemento Path con fattori di ridimensionamento elevati nella sua proprietà RenderTransform.Test hit errato sul percorso trasformato

Il seguente XAML definisce un percorso con un cerchio pieno e un cursore 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> 

Come si può vedere nell'immagine sottostante, il cursore Hand appare anche se la sua posizione è senso all'esterno della forma.

enter image description here

con un percorso di grandi e piccoli fattori di scala il problema scompare e il cursore si comporta come previsto.

<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

Esecuzione di un hit test esplicito come questo

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

in un gestore di eventi del mouse sulla tela dà gli stessi risultati non corretti. Un clic del mouse chiaramente fuori dal percorso in scala restituisce comunque il percorso come elemento colpito.

Vale anche la pena notare che il problema non viene visualizzato in Silverlight.


Ora la domanda è: qual è la causa di questo comportamento e come può essere evitato? Nota che non posso semplicemente cambiare le dimensioni originali dei miei elementi Path, quindi una risposta del tipo "non utilizzare fattori su larga scala" non sarà utile.

La mia soluzione corrente non è quella di trasformare il percorso da un RenderTransform, ma trasformare i Dati invece (applicando la trasformazione alla proprietà Geometry.Transform). Ma poiché potrebbero esserci riempimenti complessi (ad esempio con ImageBrush), devo anche trasformare i pennelli di riempimento (il che implica non solo l'impostazione della loro trasformazione, ma anche il loro punto di vista).

Inoltre, la trasformazione effettiva non è solo ridimensionamento, ma un MatrixTransform che ruota e converte anche.


Potrebbe anche valere la pena notare che il problema emerge anche con altre geometrie e trasformazioni aggiuntive. Ad esempio, un tracciato trasformato con RectangleGeometry mostra un comportamento simile errato.

non corretti con fattori di grandi dimensioni:

<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> 

enter image description here

corrette con i fattori di piccola scala:

<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

+0

Soluzione: * Non utilizzare fattori di scala di grandi dimensioni *. Nah, sto scherzando. Si verifica se si cambia 'RenderTranform' in' LayoutTransform'? –

+0

Già provato, sebbene LayoutTransform non sia un'opzione. Ad ogni modo, si comporta allo stesso modo con LayoutTransform. – Clemens

+0

Hai considerato l'utilizzo di 'RectangleGeometry.Transform' invece di' Path. [Render | Layout] Transform'? Dal momento che hai accesso alla geometria stessa, puoi fare in modo che Shape esegua il rendering di una geometria già trasformata, quindi i test di hit dovrebbero essere più naturali. – heltonbiker

risposta

3

Più di un commento esteso che una risposta:

012.

Sembra un comportamento strano, ho giocato con alcuni Paths e ho provato a utilizzare Geometry.GetWidenedPathGeometry per applicare un effetto di ridimensionamento leggermente diverso sui dati stessi, ma non ho ottenuto molto lontano.

La causa principale del problema sembra essere il modo in cui viene scelta la tolleranza di rilevamento del colpo in WPF, ci sono due risposte a domande simili su MSDN di Brendan Clark, sembra qualcosa che non è mai stato risolto.

In sostanza, la tolleranza di test hit utilizzata sembra essere un valore assoluto derivato dalla dimensione base della geometria stessa, piuttosto che dalla dimensione renderizzata/trasformata. Quindi, mentre per le forme grandi va bene che stai realizzando forme più piccole, o addirittura piccole, che manterrai piccole, comincerà a diventare abbastanza impreciso quando le forme piccole vengono ridimensionate (come hai trovato).

I.e. Una piccola tolleranza di prova rispetto alle dimensioni di una piccola figura va bene, ma quando la forma e la tolleranza vengono entrambe scalate, inizia a sembrare orribile.

La soluzione proposta in un thread era di ridimensionare le forme fino alla dimensione massima richiesta e ridurle quando le vuoi più piccole (che non è una soluzione per te). Ew.

Sembra che tu possa essere bloccato con qualche trasformazione. Proverò a vedere se riesco a trovare qualcosa di meglio.

Link stavo guardando:

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

+0

Grazie per aver fornito questa spiegazione e i collegamenti. Questo è quello che stavo cercando. – Clemens

+1

Felice che sia stato utile = D – Chris

Problemi correlati