Dieser Artikel wurde maschinell übersetzt.

Touch and Go

Eine Fingereingabenschnittstelle für eine ausgerichtete Karte

Charles Petzold

Charles PetzoldWann immer ich ein bisschen in ein Einkaufszentrum oder ein Museum verloren bin, ich Suche für eine Karte, aber gleichzeitig fühle ich oft einige Angst vor was ich finde. Mir ich bin ziemlich sicher, die Karte wird einen Pfeil mit der Bezeichnung Funktion, "Bist du hier", aber wie wird die Karte ausgerichtet sein? Wenn die Karte senkrecht montiert ist, entsprechen der rechten Seite der Karte tatsächlich zu meiner rechten und entsprechen unteren was hinter mir ist? Oder braucht die Karte im Weltraum zu Line-up mit dem eigentlichen Layout verdreht und geistig aus seiner Halterung entfernt werden?

Karten, die auf einen Winkel oder Parallel zum Boden montiert sind, sind viel besser — angegeben, das heißt, sie sind richtig von Anfang an orientiert. Unabhängig von der geistigen Agilität mit räumlichen Beziehungen sind die Karten leichter zu lesen, wenn sie parallel zur Erde sind, oder können mit der Erde ausrichten nach vorn geschwenkt werden. Vor Jahren GPS war es üblich, die Auseinandersetzung mit Papier Straßenkarten durch das Wild drehen sie nach rechts, Links und auf den Kopf gestellt auf der Suche nach der richtigen Orientierung zu sehen.

Karten, die in der Software auf Handys und andere mobile Geräte implementiert werden haben das Potenzial, sich basierend auf einen Kompass lesen orientieren. Dies ist die treibende Kraft hinter meinem Bestreben, zeigt eine Karte auf einem Windows Phone Gerät, der bezogen auf das Telefon dreht. Eine solchen Karte sollten selbst mit der umliegenden Landschaft ausrichten und möglicherweise hilfreicher den verlorenen unter uns sein können.

Ausrichten der Karte

Mein ursprüngliche Ziel war ein wenig ehrgeiziger als ein rotierender Karte. Das Programm, das ich vorgestellt würde tatsächlich eine Karte in einem dreidimensionalen Raum schweben, so wäre es immer parallel zur Oberfläche der Erde, als auch mit dem Kompass ausgerichtet wird.

Ein wenig experimentieren hat mich überzeugt, dass dieser Ansatz etwas extravaganter war als ich brauchte. Obwohl die geneigte Karte mit Perspektive für GPS im Auto zeigt feine ist, ich denke, das ist, weil die Karte ist immer den gleichen Grad geneigt, und es etwas imitiert, was Sie aus der Windschutzscheibe sehen. Mit einer Karte auf einem mobilen Gerät wirkt das Kippen der Karte Grafiken komprimieren, ohne irgendwelche zusätzlichen Informationen. Eine einfache zweidimensionale Rotation schien ausreichend sein.

In meinem Artikel vom November ich diskutiert, wie man die Bing Maps SOAP-Dienste herunterzuladen und montieren von 256 Pixel Digitalfotos in einer Karte verwenden ("Assembling Bing-Kartenkacheln auf Windows Phone," msdn.microsoft.com/magazine/jj721603). Die Fliesen aus diesem Webdienst verfügbar sind in Zoomstufen, organisiert jede höhere Ebene verdoppeln die Auflösung der vorherigen Ebene, was bedeutet hat, dass jede Kachel auf der gleichen Fläche wie vier Fliesen in der nächsten höheren deckt.

Das Programm im vergangenen Monat Spalte enthaltenen Anwendungen Bar Buttons beschriftet mit Plus und minus Zeichen erhöhen oder verringern die Zoomstufe in diskrete Sprünge. Dieser Typ der Schnittstelle ist ausreichend für eine Karte auf einer Website, aber für ein Handy, ist die einzige Beschreibung, die angemessen "völlig lahm."

Dies bedeutet, dass es jetzt Zeit, um einen echten Touch-Interface implementieren, mit der die Karte, um kontinuierlich vergrößert werden können.

Sobald ich begann dieses Touch-Interface hinzufügen — eine einzelne Finger schwenken, zwei Finger zu vergrößern und verkleinern — ich erwarb einen tiefen und dauerhaften Respekt für die Maps-Anwendung auf Windows Phone und für das Anzeigen der Silverlight-Steuerelement. Diese Karten implementieren natürlich eine viel komplexere Touch-Interface als was ich in der Lage schon zu verwalten.

Ich glaube z.B. nicht, dass ich je gesehen habe, ein schwarzes Loch in den Karten app eröffnen, da ein Stein fehlt. Es ist meine Erfahrung, dass der Bildschirm immer vollständig abgedeckt ist — obwohl offensichtlich manchmal mit einem Ziegel, die über den Punkt der Anerkennung hinaus gestreckt wurde. Fliesen werden mit Fliesen der bessere Auflösung mit einem Fade-Animation ersetzt. Trägheit wird auf sehr natürliche Weise implementiert, und die Benutzeroberfläche wird nie nervös, während Fliesen heruntergeladen werden.

Mein OrientingMap-Programm (die Sie herunterladen können) kommt nirgendwo an die reale Maps-Anwendung zu schließen. Schwenken und Ausbau ist oft nervös, gibt es keine Trägheit und häufig weiße Flecken auftauchen, wenn Fliesen sind nicht schnell genug heruntergeladen.

Trotz dieser Mängel ist mein Programm erfolgreich bei der Erhaltung der Karte mit der Welt, die es schildert einer Orientierung.

Die grundlegende Frage

Die Bing Maps SOAP-Dienste bieten einen Programmzugriff auf 256 Pixel quadratisch Kartenkacheln aus denen zusammengesetzte Karten größere konstruiert werden kann. Für Straße und Luftaufnahmen macht Bing Maps verfügbare 21 Stufen des Zooms, wobei Stufe 1 die Erde mit vier Fliesen, Stufe 2 mit 16 Steine, Stufe 3 mit 64, usw. umfasst. Jede Stufe bietet Doppelzimmer die horizontale Auflösung und verdoppeln die vertikale Auflösung der nächstniedrigeren Ebene.

Fliesen haben eine Parent-Child-Beziehung: Außer Fliesen in Stufe 21 hat jede Kachel vier Kinder in die nächste höhere Ebene, die zusammen den gleichen Bereich wie selbst jedoch doppelte Auflösung abdecken.

Wenn ein Programm hält sich an integral Zoomstufen — ebenso wie das Programm dargestellt in Artikel des letzten Monats — die einzelnen Kacheln können in ihrer tatsächlichen Pixelgrößen angezeigt werden. Des letzten Monats Programm zeigt immer 25 Fliesen in einem 5 × 5-Array auf eine Gesamtgröße von 1.280 Pixel im Quadrat. Das Programm positioniert immer dieses Array von Fliesen so, dass die Mitte des Bildschirms des Telefons Lage auf der Karte entspricht, die ein Ort irgendwo in der Mitte Fliese ist. Die Mathematik zu tun, und Sie werden feststellen, dass selbst wenn eine Ecke der Fliese Mitte in der Mitte des Bildschirms sitzt, diese quadratische 1.280 Pixel-Größe ausreichend für die 480 × 800 Bildschirmgröße des Handys, egal wie es gedreht wird.

Weil des letzten Monats Programm nur diskrete Zoomstufen unterstützt und immer die Fliesen des Telefons Standortabhängig zentriert, implementiert es eine extrem vereinfachte Logik durch diese 25 Steine vollständig ersetzen, wenn eine Änderung eintritt. Glücklicherweise macht der Downloadcache dabei ziemlich schnell, wenn die zuvor heruntergeladene Kacheln Fliesen ersetzt werden.

Mit einem Touch-Interface ist dieser Ansatz einfache nicht mehr akzeptabel.

Das schwierige Teil ist definitiv die Skalierung: Z. B. genommen Sie an, das Programm beginnt mit dem Anzeigen von Kartenkacheln Level 12 in ihrer Pixelgrößen. Jetzt wird der Benutzer legt zwei Finger auf dem Bildschirm und bewegt die Finger auseinander, um den Bildschirm zu erweitern. Das Programm muss reagieren durch die Fliesen darüber hinaus ihre 256-Pixel-Größe skalieren. Sie können dies tun, mit ScaleTransform auf den Fliesen selbst oder mit ScaleTransform auf eine Leinwand, auf dem die Fliesen zusammengesetzt werden, angewendet.

Aber nicht diese Steine unbegrenzt skalieren möchten! Sie möchten zu einem bestimmten Zeitpunkt jede Kachel mit vier Kind Fliesen aus der nächsten höheren und die Hälfte der Skalierungsfaktor ersetzen. Dieser Austauschprozess wäre ziemlich trivial, wenn die Kind Fliesen sofort verfügbar waren, aber sie natürlich nicht sind. Sie müssen heruntergeladen werden, was bedeutet, dass das Kind Fliesen müssen visuell auf das übergeordnete Element positioniert werden, und nur wenn alle vier Kind Kacheln heruntergeladen wurden das übergeordnete Element werden auf der Canvas entfernt kann.

Der umgekehrte Prozess muss in einem Zoom heraus auftreten. Wie der Benutzer zwei Finger zusammen drückt, kann das gesamte Array von Fliesen nach unten skaliert werden, aber irgendwann sollte jede Gruppe von vier Fliesen mit dem übergeordneten Dachziegel visuell unter den vier Fliesen ersetzt werden. Nur wenn diese übergeordneten Kachel heruntergeladen wurde, können die vier Kinder entfernt werden.

Zusätzliche Klassen

Wie ich im Artikel des letzten Monats erläutert, verwendet Bing Maps ein Nummerierungssystem genannt ein "Quadkey" zur eindeutigen Identifizierung von Kartenkacheln. Eine Quadkey ist eine Base-4-Zahl: Die Anzahl der Ziffern in der Quadkey gibt die Zoom-Stufe und die Ziffern selbst Codieren eine überlappende Längen- und Breitengrad.

Das OrientingMap-Programm hilft bei der Arbeit mit Quadkeys, umfasst das Projekt eine QuadKey-Klasse, die Eigenschaften zum Abrufen von übergeordneten und untergeordneten Quadkeys definiert.

Das OrientingMap-Projekt hat auch eine neue MapTile-Klasse, die von UserControl abgeleitet wird. Die XAML-Datei für dieses Steuerelement zeigt sich an Abbildung 1. Es hat ein Bildelement mit der Source-Eigenschaft auf ein BitmapImage-Objekt zum Anzeigen der Kachel Bitmap sowie ScaleTransform für die Skalierung des gesamten Ziegel nach oben oder unten festgelegt. (In der Praxis sind einzelne Fliesen nur um positive und negative ganzzahlige Potenzen von 2 skaliert.) Für das Debuggen, ich habe einen TextBlock in der XAML-Datei, die die Quadkey anzeigt, und ich habe Links, die in: Ändern Sie einfach das Attribut Visibility Visible zu sehen.

Abbildung 1 die MapTile.xaml-Datei aus OrientingMap

<UserControl x:Class="OrientingMap.MapTile" ... >
  <Grid>
    <Image Stretch="None">
      <Image.Source>
        <BitmapImage x:Name="bitmapImage"
                     ImageOpened="OnBitmapImageOpened" />
      </Image.Source>       
    </Image>
    <!-- Display quadkey for debugging purposes -->
    <TextBlock Name="txtblk"
               Visibility="Collapsed"
               Foreground="Red" />
  </Grid>
  <UserControl.RenderTransform>
    <ScaleTransform x:Name="scale" />
  </UserControl.RenderTransform>
</UserControl>

Die Codebehind-Datei für MapTile werden mehrere praktische Eigenschaften definiert: Die QuadKey-Eigenschaft ermöglicht MapTile Klasse selbst auf den URI für den Zugriff auf die Karte-Fliese zu erhalten; Eigenschaft "Skalierung" ermöglicht externen Code den Skalierungsfaktor eingestellt; eine IsImageOpened-Eigenschaft gibt an, wann die Bitmap heruntergeladen wurde; und eine ImageOpened-Eigenschaft ermöglicht den externen Zugriff auf das ImageOpened-Ereignis des Objekts BitmapImage. Diese beiden letzten Eigenschaften helfen das Programm bestimmen, wann ein Bild geladen wurde damit das Programm alle Fliesen entfernen kann, die das Bild ersetzt wird.

Bei der Entwicklung dieses Programms, verfolgte ich zunächst ein System wo jeder MapTile Objekt die Eigenschaft "Skalierung" benutzen um zu bestimmen, wann sie mit einer Gruppe von vier untergeordnete MapTile Objekte oder ein Elternteil MapTile ersetzt werden sollte. Das MapTile selbst würde behandeln die Erstellung und Positionierung von diesen neuen Objekten, Festlegen der Handler für das ImageOpened, und wäre auch zu entfernen sich von der Leinwand.

Aber ich konnte nicht diese Regelung sehr gut zu funktionieren. Sollten Sie ein Array von 25 Kartenkacheln, die der Benutzer durch die Touch-Oberfläche erweitert. Diese 25 Fliesen werden ersetzt mit 100 Fliesen und dann die 100 Kacheln mit 400 Fliesen ersetzt. Ist dies verständlich? Nein, tut es nicht, weil die Skalierung hat effektiv bewegt viele dieser potentiellen neuen Kacheln zu weit weg ist den Bildschirm sichtbar sein. Die meisten von ihnen sollte nicht erstellt oder gar heruntergeladen werden!

Stattdessen verschob ich diese Logik zu der Hauptseite. Diese Klasse verwaltet ein CurrentMapTiles Feld vom Typ Dictionary < QuadKey, MapTile >. Dies speichert alle MapTile Objekte derzeit auf dem Display, auch wenn sie noch dabei heruntergeladen werden. Eine Methode namens RefreshDisplay verwendet die aktuelle Position der Karte und einem Skalierungsfaktor ein ValidQuadKeys Feld vom Typ List <QuadKey> zusammenzubauen. Wenn ein QuadKey-Objekt in ValidQuadKeys aber nicht in CurrentMapTiles vorhanden ist, ist eine neue MapTile erstellt und auf die Leinwand und CurrentMapTiles hinzugefügt.

RefreshDisplay entfernt keine MapTile Objekte, die nicht mehr benötigt werden, entweder weil sie außerhalb des Bildschirms geschwenkt oder mit Eltern oder Kindern ersetzt worden habe. Das ist die Verantwortung für eine zweite wichtige Methode mit dem Namen Cleanup. Diese Methode vergleicht die ValidQuadKeys-Auflistung mit CurrentMapTiles. Wenn sie ein Element in CurrentMapTiles, die nicht in ValidQuadKeys ist findet, entfernt nur das MapTile wenn ValidQuadKeys keine Kinder hat, die Kinder in ValidQuadKeys alle heruntergeladen wurden, oder wenn ValidQuadKeys ein Elternteil, dass MapTile enthält und übergeordneten heruntergeladen wurde.

Die Methoden RefreshDisplay und Bereinigung effizienter zu gestalten – und sie weniger häufig aufrufen — ist ein Ansatz zur Verbesserung der Leistungsfähigkeit des OrientingMap.

Geschachtelte Leinwände

Die Benutzeroberfläche für das OrientingMap-Programm erfordert zwei Arten von Grafiktransformationen: Übersetzung für Einzel-Finger schwenken und Skalierung für zwei-Finger-Prise Operationen. Darüber hinaus erfordert die Ausrichtung der Karte mit der Richtung des Nordens eine Drehungstransformation. Um diese mit effizienten Silverlight Transformationen zu implementieren, enthält die Datei MainPage.XAML drei Ebenen von Canvas Panels, siehe Abbildung 2.

Abbildung 2 ein Großteil der MainPage.xaml Datei für OrientingMap

<phone:PhoneApplicationPage x:Class="OrientingMap.MainPage" ... >
  <Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12">
      <TextBlock Name="errorTextBlock"
                 HorizontalAlignment="Center"
                 VerticalAlignment="Top"
                 TextWrapping="Wrap" />
      <!-- Rotating Canvas with origin in center of screen -->
      <Canvas HorizontalAlignment="Center"
              VerticalAlignment="Center">
        <!-- Translating Canvas for panning -->
        <Canvas>
          <!-- Scaled Canvas for images -->
          <Canvas Name="imageCanvas"
                  HorizontalAlignment="Center"
                  VerticalAlignment="Center">
              <Canvas.RenderTransform>
                <ScaleTransform x:Name="imageCanvasScale" />
              </Canvas.RenderTransform>
          </Canvas>
          <!-- Circle to show location -->
          <Ellipse Name="locationDisplay"
                   Width="24"
                   Height="24"
                   Stroke="Red"
                   StrokeThickness="3"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"
                   Visibility="Collapsed">
            <Ellipse.RenderTransform>
              <TranslateTransform x:Name="locationTranslate" />
            </Ellipse.RenderTransform>
          </Ellipse>
          <Canvas.RenderTransform>
            <TranslateTransform x:Name="imageCanvasTranslate" />
          </Canvas.RenderTransform>
        </Canvas>
        <Canvas.RenderTransform>
          <RotateTransform x:Name="imageCanvasRotate" />
        </Canvas.RenderTransform>
      </Canvas>
      <!-- Arrow to show north -->
      <Border HorizontalAlignment="Left"
              VerticalAlignment="Top"
              Background="Black"
              Width="36"
              Height="36"
              CornerRadius="18">
        <Path Stroke="White"
              StrokeThickness="3"
              Data="M 18 4 L 18 24 M 12 12 L 18 4 24 12">
          <Path.RenderTransform>
            <RotateTransform x:Name="northArrowRotate"
                             CenterX="18"
                             CenterY="18" />
          </Path.RenderTransform>
        </Path>
      </Border>
      <!-- "powered by bing" display -->
      <Border Background="Black"
              HorizontalAlignment="Center"
              VerticalAlignment="Bottom"
              CornerRadius="12"
              Padding="3">
        <StackPanel Name="poweredByDisplay"
                    Orientation="Horizontal"
                    Visibility="Collapsed">
          <TextBlock Text=" powered by "
                     Foreground="White"
                     VerticalAlignment="Center" />
          <Image Stretch="None">
            <Image.Source>
              <BitmapImage x:Name="poweredByBitmap" />
            </Image.Source>
          </Image>
        </StackPanel>
      </Border>
    </Grid>
  </Grid>
  ...
</phone:PhoneApplicationPage>

Das Raster mit dem Namen ContentPanel enthält die äußerste Canvas sowie drei Elemente, die immer an festen Standorten auf dem Bildschirm angezeigt werden: ein TextBlock Initialisierung Fehler einen Rahmen mit einen rotierenden Pfeil Richtung Norden angezeigt und eine weitere Grenze das Bing-Logo angezeigt.

Die äußerste Canvas hat die HorizontalAlignment-Eigenschaft und die vertikale­Alignment-Eigenschaften legen Sie auf Mitte, die schrumpft die Leinwand eine Größe Null in der Mitte des Rasters platziert. Die (0, 0) Koordinate des diese Leinwand ist daher die Mitte der Anzeige. Diese Zentrierung ist bequem für die Positionierung von Fliesen, und erlaubt auch die Skalierung und Drehung um den Ursprung auftreten.

Die äußerste Leinwand ist derjenige, der gedreht wird auf der Grundlage von Norden. Innerhalb dieser Regionen in äußerster Canvas ist eine zweite Leinwand, die TranslateTransform hat. Dies ist für das panning. Bei jedem einzelner Finger über den Bildschirm streicht, kann die gesamte Karte einfach durch Festlegen der Eigenschaften X und Y der TranslateTransform verschoben werden.

Innerhalb dieser zweiten Canvas ist eine Ellipse verwendet, um die aktuelle Position des Telefons im Verhältnis zu der Mitte der Karte anzuzeigen. Wenn der Benutzer die Karte Pfannen, bewegt sich diese Ellipse sowie. Aber wenn des Telefons GPS eine Änderung in der Lage, eine separate übersetze meldet­-Transformation auf die Ellipse bewegt sich bezogen auf die Karte.

Die innerste Leinwand heißt ImageCanvas, und es ist hier, dass die Kartenkacheln tatsächlich montiert sind. ScaleTransform auf diese Leinwand angewendet ermöglicht das Programm erhöhen oder verringern dieser gesamten Gefüge der Kartenkacheln Benutzer vergrößern oder verkleinern mit einer Prise Manipulation.

Um den kontinuierlichen Zoom aufnehmen zu können, unterhält das Programm ein ZoomFactor Feld vom Typ Doppelzimmer. Diese ZoomFactor hat die gleiche Reichweite wie die Fliese Ebenen – von 1 bis 21 — Was bedeutet, dass es tatsächlich den Logarithmus Base-2 der Gesamt-Karte-Skalierungsfaktor ist. Immer wenn die ZoomFactor um 1 erhöht, verdoppelt sich die Skalierung der Karte.

Erstmals, wenn das Programm ausgeführt wird, mit 12 ZoomFactor initialisiert wird, aber zum ersten Mal, wenn, das der Benutzer den Bildschirm mit zwei Fingern berührt, es wird einen nicht ganzzahligen Wert und sehr wahrscheinlich einen nicht ganzzahligen Wert danach bleibt. Das Programm speichert ZoomFactor als eine Benutzereinstellung und lädt es das nächste Mal, wenn das Programm ausgeführt wird. Eine anfängliche integraler BaseLevel ist eine einfache Kürzung berechnet:

baseLevel = (int)zoomFactor;

Diese BaseLevel ist immer eine ganze Zahl im Bereich zwischen 1 und 21, und es ist daher direkt zum Abrufen von Fliesen geeignet. Aus diesen beiden Zahlen berechnet das Programm einen nicht-logarithmischen Skalierungsfaktor vom Typ double:

canvasScale = Math.Pow(2, zoomFactor - baseLevel);

Dies ist der Skalierungsfaktor angewendet um den innersten Leinwand. Beispielsweise wenn die ZoomFactor 10.5 ist, dann ist die BaseLevel zum Abrufen von Fliesen 10, und CanvasScale ist 1,414.

Wenn die anfänglichen ZoomFactor 10,9 ist, könnte es weitere 11 und CanvasZoom in 0.933 BaseLevel festzusetzen sinnvoll. Das Programm tut das nicht, aber es ist natürlich eine Verfeinerung möglich.

Und zwei-Finger-Touch Eingabe

Für Fingereingabe fühlte ich mich wohler mit der XNA-TouchPanel als die Silverlight-Manipulation-Ereignisse. Der MainPage-Konstruktor ermöglicht vier Arten von XNA Gesten: FreeDrag (Schwenken), DragComplete, Prise und PinchComplete. Das Touchpad wird für die Eingabe in einem Handler für das Ereignis CompositionTarget.Rendering überprüft, wie in Abbildung 3. Aufgrund ihrer Komplexität, nur wenig von der Prise Verarbeitung wird hier gezeigt.

Abbildung 3 Touch Verarbeitung in OrientingMap

void OnCompositionTargetRendering(object sender, EventArgs args)
{
  while (TouchPanel.IsGestureAvailable)
  {
    GestureSample gesture = TouchPanel.ReadGesture();
    switch (gesture.GestureType)
    {
      case GestureType.FreeDrag:
        // Adjust delta for rotation of canvas
        Vector2 delta = TransformGestureToMap(gesture.Delta);
        // Translate the canvas
        imageCanvasTranslate.X += delta.X;
        imageCanvasTranslate.Y += delta.Y;
        // Adjust the center longitude and latitude
        centerRelativeLongitude -= delta.X / (1 << baseLevel + 8) / canvasScale;
        centerRelativeLatitude -= delta.Y / (1 << baseLevel + 8) / canvasScale;
        // Accumulate the panning distance
        accumulatedDeltaX += delta.X;
        accumulatedDeltaY += delta.Y;
        // Check if that's sufficient to warrant a screen refresh
        if (Math.Abs(accumulatedDeltaX) > 256 ||
            Math.Abs(accumulatedDeltaY) > 256)
        {
          RefreshDisplay();
          accumulatedDeltaX = 0;
          accumulatedDeltaY = 0;
        }
        break;
      case GestureType.DragComplete:
        Cleanup();
        break;
      case GestureType.Pinch:
        // Get the old and new finger positions relative to canvas origin
        Vector2 newPoint1 = gesture.Position - canvasOrigin;
        Vector2 oldPoint1 = newPoint1 - gesture.Delta;
        Vector2 newPoint2 = gesture.Position2 - canvasOrigin;
        Vector2 oldPoint2 = newPoint2 - gesture.Delta2;
        // Rotate in accordance with the current rotation angle
        oldPoint1 = TransformGestureToMap(oldPoint1);
        newPoint1 = TransformGestureToMap(newPoint1);
        oldPoint2 = TransformGestureToMap(oldPoint2);
        newPoint2 = TransformGestureToMap(newPoint2);
        ...
        RefreshDisplay();
        break;
      case GestureType.PinchComplete:
        Cleanup();
        break;
    }
  }
}

Die Eingabe von FreeDrag wird begleitet von Position und Delta-Werte (beide vom Typ Vector2) angibt, die aktuelle Position der Finger, und wie der Finger seit dem letzten Ereignis TouchPanel ist umgezogen. Die Prise Eingabe ergänzt diese mit Position2 und Delta2-Werte für den zweiten Finger.

Behalten Sie jedoch Bedenken, dass diese Werte Vector2 in Bildschirmkoordinaten sind! Da die Karte relativ zum Bildschirm gedreht wird — und der Benutzer erwartet, dass die Karte in die gleiche Richtung zu schwenken, wenn ein Finger bewegt — diese Werte auf die aktuelle anzeigen-Rotation, die in eine kleine Methode mit dem Namen TransformGestureToMap auftritt gedreht werden müssen.

Für FreeDrag Verarbeitung wird der Deltawert dann auf TranslateTransform in der XAML-Datei, sowie zwei Gleitkommazahlen Felder mit den Namen CenterRelativeLongitude und CenterRelativeLatitude angewendet. Diese Werte reichen von 0 bis 1 und geben Sie den Längen- und Breitengrad, der Mitte des Bildschirms entspricht.

An einem gewissen Punkt kann der Benutzer die Karte, um ein ausreichendes Maß Pfanne neue Fliesen, die geladen werden müssen. Um zu vermeiden, überprüfen auf diese Möglichkeit mit den einzelnen Ereignissen Note, verwaltet das Programm zwei Felder mit dem Namen AccumulatedDeltaX und AccumulatedDeltaY und nur RefreshDisplay Aufrufe wenn entweder Wert oben 256, geht die die Pixelgröße der Kartenkacheln ist.

Da RefreshDisplay eine große Aufgabe zu tun hat — bestimmen welche Fliesen sollte auf dem Bildschirm sichtbaren beruhen auf CenterRelativeLongitude und CenterRelativeLatitude und die aktuellen CanvasScale und erstellen neue Fliesen, ggf. — es ist am besten, dass sie nicht für jede Änderung in der Fingereingabe aufgerufen werden. Eine deutliche Verbesserung des Programms würde während der Eingabe Prise RefreshDisplay Anrufe einschränken.

Während der Verarbeitung Note heißt die Cleanup-Methode nur, wenn der Finger oder der Finger den Bildschirm verlassen haben. Bereinigung wird auch aufgerufen, wenn ein Ziegel Karte herunterladen abgeschlossen ist.

Die Kriterien für die BaseLevel — und initiieren dadurch einen Ersatz der übergeordneten Karte Fliese durch Kinder oder Kinder von einem Elternteil — ist sehr entspannt. Die BaseLevel wird nur erhöht, wenn CanvasScale wird größer als 2 und wieder um eins erniedrigt, wenn CanvasScale auf weniger als 0,5 sinkt. Bessere Übergangspunkte festlegen, ist eine weitere offensichtliche Verbesserung.

Das Programm hat jetzt die Anwendung nur zwei Schaltflächen: Die erste schaltet zwischen Straße und Luftbild und die zweiten Positionen die Karte so, dass die aktuelle Position in der Mitte befindet.

Jetzt brauche ich nur um herauszufinden, wie man das Programm Hilfe navigieren, Museen und Einkaufszentren zu machen.

Charles Petzold ist ein langjähriger Beitrag zum MSDN Magazine und Autor von "Programming Windows, 6th Edition" (O' Reilly Media, 2012), ein Buch über das Schreiben von Anwendungen für Windows 8. Seiner Website lautet charlespetzold.com.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Thomas Petchel