2013-07-13 1 views
6

J'introduis Google Maps dans mon application MVC 4. Assez simple à faire. Cependant, j'ai une question concernant la meilleure façon d'ajouter plusieurs marqueurs de manière dynamique. Mes utilisateurs vont chercher une liste d'articles à vendre, via un appel à une méthode d'action sur un contrôleur, et je veux être en mesure de leur montrer les éléments et l'emplacement de chacun sur la carte. Ce dont je ne suis pas sûr, c'est comment ou comment ajouter dynamiquement des marqueurs à une carte, qui est tout JavaScript dans le client. Essentiellement, j'aimerais pouvoir envoyer toutes les informations de marqueur du code du serveur MVC au client, mais je ne suis pas sûr que cela puisse ou doive être fait de cette façon.MVC 4 et Google Maps API v3

+0

Une fois qu'un utilisateur clique sur le bouton de recherche, est la carte seule chose qui est mis à jour? Ou les résultats de recherche sont-ils également affichés sous forme de texte et sont-ils également mis à jour? – mostruash

+0

Les résultats de recherche sont également mis à jour. – Hosea146

+0

Encore une question.Par dynamique, voulez-vous dire que les résultats de recherche sont mis à jour de manière asynchrone avec les requêtes AJAX à vos actions? – mostruash

Répondre

10

Dans le (http://docs.angularjs.org/api/ng $ http.) projet sur lequel je travaille en ce moment, voici comment nous le traitons:

Laissez le ViewModel principal être appelé FooViewModel.

ViewModels:

public class FooViewModel 
{ 
    // Your search results: 
    public IEnumerable<FooWithLocationViewModel> Foos { get; set; } 

    // Properties for your search filter: 
    public decimal? MaxPrice { get; set; } 
    public CityEnum? City { get; set; } 
    ... 
} 

public class FooWithLocationViewModel 
{ 
    public string Name { get; set; } 
    public decimal Price { get; set; } 
    ... 
    public double Latidude { get; set; } 
    public double Longitude { get; set; } 
    ... 
} 

Dans la vue, il y a un <div> pour chaque FooWithLocationViewModel. Nous allons utiliser data-* attributs qui sont valides en HTML5:

Vue:

@model FooViewModel 

... 

@foreach(FooWithLocationViewModel foo in Model.Foos) 
{ 
    <div class="foo" data-latitude="@(foo.Latitude)" 
     data-longitude="@(foo.Longitude)"> 
     <span>@foo.Name</span> 
     <span>@foo.Price</span> 
     ... 
    </div> 
} 

<div id="map-canvas"></div> 

Maintenant, il est temps pour JavaScript, je suppose que vous utilisez JQuery:

Initialiser la carte , en ajoutant les marqueurs et les stocker dans le tableau markers:

function initialize() { 
    var foos = $(".foo"); 
    var markers = new Array(); 
    var mapOptions = { 
     ... 
    }}; 
    var mapCanvas = document.getElementById('map-canvas'); 
    if (mapCanvas != null) { 
     map = new google.maps.Map(mapCanvas, mapOptions); 

     $.each(foos, function (key, value) { 
      markers[key] = new google.maps.Marker({ 
       map: map, 
       draggable: false, 
       animation: google.maps.Animation.DROP, 
       position: new google.maps.LatLng(
        Number($(value).attr("data-latitude")), 
        Number($(value).attr("data-longitude") 
       )); 
      }); 

      google.maps.event.addListener(markers[key], 'click', function() { 
       // If you need this... 
      }); 
     }); 
    } 
} 

ce qui est bien cette approche est, tout est fait dans le fu nction qui initialise votre Google Map. Ainsi, votre script ne doit pas nécessairement être intégré dans votre vue. Nous utilisons une approche conviviale HTML5. Et c'est simple.

+1

C'est une bonne réponse! C'est à peu près l'idée que je pensais, mais vous avez amélioré mes idées en utilisant les données - en tant que mécanisme de livraison, j'allais juste jeter un morceau de JavaScript, mais c'est beaucoup plus poli. – rtpHarry

+0

@rtpHarry, merci. J'espère que ça aide les autres. – mostruash

+0

comme une extension légère, si vous deviez donner une classe, ou un identifiant d'une certaine description, aux SPANS, vous pourriez réutiliser cette information si vous voulez générer du contenu de marqueur. Plus propre que l'intégration de JS ou de tableaux. – stefancarlton

2

Utilisez l'API Web et gérez-la de manière asynchrone. Transmettez un objet JSON au client, analysez vos informations, supprimez vos anciens marqueurs et ajoutez les nouveaux.

EDIT après votre commentaire:

Si vous publiez une partie de ce que vous avez essayé et n'a pas été en mesure de se rendre au travail, nous pouvons vous aider avec les problèmes que vous exécutez dans. Si vous êtes juste de commencer:

http://www.asp.net/web-api - Grands tutoriels sur l'utilisation de l'API Web http://angularjs.org/ - Check out angulaire pour la requête GET et lie vos résultats à l'

UI
+0

Merci. Mais pour 150 points de rep, je cherche un peu plus que ça. – Hosea146

0

aimerait proposer une approche de cette exigence:

  1. sur le bouton de recherche, cliquez - être (requête POST ou AJAX POST), envoyer la demande au serveur.

  2. Effectuez la recherche sur l'action search() du serveur.

  3. L'action search() comporte deux responsabilités: 1. Afficher le résultat de la recherche. 2. Afficher les marqueurs correspondants sur la carte

  4. Le résultat de la recherche sera les données et la représentation, que ce soit 'div'/'table/tr/td'.Cette représentation est générée sur le serveur sans utiliser les ressources client et le temps de traitement côté client. Ainsi, le 'SearchView' peut renvoyer à la fois les données et la représentation.

  5. Une autre responsabilité est de montrer les marqueurs correspondant à chaque résultat de recherche. Ceci est entièrement la responsabilité du client. Alors gardons-le séparé de la première responsabilité. À l'aide de la bibliothèque de sérialisation JSON, injectez le tableau json 'marqueurs' sérialisé dans le 'SearchView' au lieu de le mélanger avec le résultat de la recherche. La seule fois où vous souhaitez que les détails des marqueurs soient étroitement liés à chaque résultat de recherche, c'est lorsque vous souhaitez mettre en surbrillance les marqueurs au clic des résultats de recherche individuels. Le cas d'utilisation peut être initialement afficher tous les résultats de recherche et afficher tous les marqueurs. Ensuite, lorsque l'utilisateur clique sur/survole (étant donné que ce n'est pas un mobile ciblé car le vol stationnaire ne peut pas fonctionner), vous pouvez repositionner le marqueur ou ajouter une étiquette ou plus d'informations au résultat de recherche sélectionné.

  6. Vous pouvez également avoir le script dans un fichier distinct pour éviter de le charger lors de chaque action de recherche. Et à partir de SearchView, vous pouvez simplement appeler la fonction JS 'InitializeMap()' en lui passant les marqueurs sérialisés JSON et la position initiale de la carte. L'utilisation du JSON serait une meilleure approche et il offre la flexibilité future pour convertir facilement l'application en AJAX. En outre, il est plus rapide que l'analyse du code HTML en utilisant Jquery pour obtenir les détails du marqueur.

    function InitializeMap(initialMapPosition,markers){ 
    var latlng = new google.maps.LatLng(initialMapPosition.latitude,initialMapPosition.longitude); 
    var options = { 
        zoom: 15, 
        center: latlng, 
        mapTypeId: google.maps.MapTypeId.ROADMAP // this could be as per your requirement. 
        }; 
    
    var map = new google.maps.Map($('#map-canvas')[0], options); 
    // Place markers on map 
    for(i = 0; i < markers.length; i++) { 
        var latLng = new google.maps.LatLng(markers[i].lat, markers[i].lng); 
        var marker = new google.maps.Marker({ 
         position: latLng, 
         map: map 
        }); 
    } 
    

    }

+0

Précision sur le point 7: Analyser le code HTML (ce qui est fait du côté client) n'est rien comparé à l'affichage du contrôle Google Map, du point de vue du calcul. Donc ce n'est absolument pas un fardeau. – mostruash

+0

D'accord sur la vitesse (bien que cela dépend du nombre de résultats de recherche). Mais pour les changements futurs, ce serait certainement la bonne option pour avoir un objet JSON. –

0

Voici mes réflexions sur le sujet.

Récemment, j'ai réalisé un projet qui consistait en une seule page, une application Web pilotée par AJAX (je sais que vous ne cherchez pas une solution basée sur AJAX mais restez avec moi).

J'ai intégré des cartes Google dans cette application qui était utilisée pour montrer l'emplacement de différentes entités.

Lorsque l'utilisateur cherchait quelque chose, au lieu de faire du géocodage dans le navigateur (qui était, parfois, très lent), j'ai envoyé la requête au serveur. Sur le serveur, le texte entrant était géocodé (à l'aide de l'API Google) et le résultat était mis en cache dans la base de données locale pour une utilisation ultérieure. Si, la même demande est venue encore, je récupère les Geo-cordinates de la DB et les renvoie au client.

Le type de retour était assez simple. à savoir

public class Marker 
{ 
    public double Lat{set;get;} 
    public double Lon{set;get;} 
    public string Title{set;get;} 
} 

Sur le client, je voudrais simplement itérer sur la liste et tracer les repères sur la carte (traçage des marqueurs est plus rapide que la demande géocodage).

Maintenant, la même chose peut être faite en post-retour. Tout ce que vous avez à faire est, dans votre initialize appel de fonction

var markers = @Html.Action("GetMarkers") 

cela remplira les marqueurs var avec la liste de tous vos marqueurs que vous pouvez itérer.

Rappelez-vous, le type de retour de GetMarkers est

public JsonResult GetMarkers() 
{ 
    ... 
    // returns List<Markers> 
}