Ce tutoriel vous guidera dans le développement d'un site Web mobile basé sur la localisation à l'aide du moteur de recherche Google Place et de Sencha Touch 2.1. Il s’agit d’un tutoriel en deux parties. Dans cette première partie, nous allons apprendre à créer un projet avec Sencha cmd, à créer un thème intéressant en utilisant SASS / Compass et à rechercher des services proches de l’emplacement de l’utilisateur..
Google fournit un ensemble d’API permettant de rechercher différents services par type et par emplacement. À l'heure actuelle, Google prend en charge un total de 96 types de services. Il y a 30 autres services qui ne peuvent être récupérés que par la recherche. Google en a une liste complète.
Pour accéder à l'API Places, l'objectif principal est d'enregistrer l'application sur la console d'API de Google. Une fois l'authentification effectuée, nous obtiendrons une clé API requise pour chaque demande d'API. Google a un guide étape par étape.
L'API Google Adresses utilise une clé API pour identifier votre application. Les clés API sont gérées via la console Google APIs. Vous aurez besoin de votre propre clé API avant de pouvoir commencer à utiliser l'API. Pour activer l'API Places et créer votre clé:
Je suppose que vous avez un serveur local et que l'installation de Sencha est terminée. Sinon, veuillez parcourir la documentation détaillée ici avec toutes les étapes. Nous générons l'application Locator en utilisant cette commande dans notre serveur local.
sencha -sdk / path / to / sdk générer une application locator c: / xampp / htdocs / locator
Une fois que nous aurons terminé, nous ouvrirons l'application dans le navigateur avec l'URL. http: // localhost / locator et voir une application à onglets de base.
Maintenant, nous devons structurer l'application avec les composants MVC.
Contrôleurs
Des vues
Magasins
Des modèles
Une application Sencha peut avoir plusieurs fichiers de contrôleur. Cependant, pour une petite application comme celle-ci, un contrôleur suffira. Nous allons conserver toutes les liaisons de l'événement et les fonctionnalités associées dans ce contrôleur.
Les vues représentent les pages de l'application.
Comme nous avons deux listes, nous maintenons deux modèles: Catégorie et Endroit. De même, deux rangements Les catégories et Des endroits sont nécessaires pour récupérer et sauvegarder les données associées. Nous devons ajouter tous ces détails de composant dans app.js afin que le moteur Sencha puisse les charger au démarrage.
Ext.Loader.setPath ('Ext': 'touch / src', 'Locator': 'app'); Ext.application (name: 'Locator', nécessite: ['Ext.MessageBox', 'Locator.util.Util'], vues: ['Main', 'Categories', 'PlaceList'], contrôleurs: ['App '], modèles: [' Catégorie ',' Lieu '], magasins: [' Catégories ',' Lieux '], icône: ' 57 ':' ressources / icons / Icon.png ',' 72 ':' ressources /icons/Icon~ipad.png ',' 114 ':' resources/icons/[email protected] ',' 144 ':' resources/icons/[email protected] ', isIconPrecomposed: true, startupImage : '320x460': 'ressources / démarrage / 320x460.jpg', '640x920': 'ressources / démarrage / 640x920.png', '768x1004': 'ressources / démarrage / 768x1004.png', 'ressources' /startup/748x1024.png ',' 1536x2008 ':' ressources / démarrage / 1536x2008.png ',' 1496x2048 ':' ressources / démarrage / 1496x2048.png ', lancez: fonction () // Détruisez l'élément #appLoadingIndicator Ext.fly ('appLoadingIndicator'). Destroy (); // initialise la vue principale Ext.Viewport.add (Ext.create ('Locator.view.Main'));, le à jour: function () Ext.Msg .confirm ("Application Update", "Cette application vient d’être lancée avec succès. mis à jour à la dernière version. Recharger maintenant? ", Function (buttonId) if (buttonId === 'oui') window.location.reload ();););
Pour chaque application, nous avons besoin d'un ensemble de fonctions et de propriétés communes qui seront utilisées dans toute l'application. Nous créons une classe singleton Util pour la même chose et mettons le fichier sous le app / util / annuaire. Vous n'avez pas besoin de comprendre les fonctions de ce fichier pour le moment. Nous allons continuer à discuter de ces fonctions à mesure que nous avançons.
Ext.define ('Locator.util.Util', singleton: true, // si les vues de l'application auront une animation lors de la modification = = non enablePageAnimations: true, // l'emplacement actuel de l'utilisateur est enregistré ici emplacement_utilisateur: null, / / Google place clé API API_KEY: 'AIzaSyBmbmtQnXfq22RJhJfitKao60wDgqrC5gA', // Toutes les adresses api: (function () // var baseUrl = 'https://maps.googleapis.com/maps/api/place/; var base = 'php / action.php'; return baseUrl: baseUrl, catégories: 'ressources / data / categories.json', adresses les plus proches: basesUrl + ", nearBySearch: 'nearbysearch', photo: 'photo', détails: 'détails' ) (), // Détruit une vue Sencha destroyCmp: fonction (enfant, parent) parent = parent || Ext.Viewport; if (enfant) Ext.defer (function () parent.remove (enfant); , Locator.util.Util.animDuration);, // Afficher l'alerte générale du message showMsg: function (msg, titre, cb, portée) if (msg) Ext.Msg.alert (title || 'Error' , msg.toString (), cb || function () , scope || fenêtre); renvoie ceci;, // Animat e l'élément actif showActiveItem: function (parentPanel, childPanel, animation) animation = Ext.apply (type: 'slide', durée: LocatrConfig.amimationDuration, animation || ); if (parentPanel && childPanel) if (this.enablePageAnimations && animation && animation.type) parentPanel.animateActiveItem (childPanel, animation); else parentPanel.setActiveItem (childPanel); renvoyer ceci; , // Afficher une boîte de chargement sur showLoading: function (panneau, doShow, message) panel = panel || Ext.Viewport; if (panneau) if (doShow) panel.setMasked (xtype: 'loadmask', message: message || 'Chargement…'); else panel.setMasked (false); renvoyer ceci; , // Majuscule le premier caractère de chaque mot d'une chaîne toTitleCase: function (str) if (! Str) return "; return str.replace (/ \ w \ S * / g, function (txt) return txt.charAt (0) .toUpperCase () + txt.substr (1) .toLowerCase ();););
Nous avons mis en place le Principale view qui encapsule toutes les vues. Nous utilisons La navigation Voir pour la même chose, ce qui est très utile pour la mise en page simple carte et la gestion du bouton Précédent. Au lancement, il n’a que la liste des catégories comme enfant.
/ ** * Vue principale - détenteur de toutes les vues. * Présentation de la carte par défaut afin de prendre en charge plusieurs vues en tant qu'éléments * / Ext.define ('Locator.view.Main', extend: 'Ext.NavigationView', xtype: 'main', config: cls: 'default- bg ', éléments: [xtype:' categories ');
Maintenant, la configuration de l'application est terminée. Nous avons la clé API Google Places et nous sommes prêts à créer une liste de tous les types et à l'afficher dans la page d'accueil. Il y a un problème, cependant. Google ne fournit pas d'API pour récupérer tous ces types. Nous devons créer manuellement un fichier de données répertoriant tous les types. J'ai créé un JSON fichier nommé catégories.json listant tous les types disponibles, et le mettre à l'intérieur du ressources / données annuaire.
catégories: [type: "comptabilité", type: "aéroport", type: "amusement_park", type: "aquarium", type: "art_gallery", type: "atm" , type: "boulangerie", type: "banque", type: "bar", type: "beauty_salon", type: "bicycle_store", type: "book_store", type: "bowling_alley", type: "bus_station", type: "café", type: "camping", type: "car_dealer", type: "car_rental", type : "car_repair", type: "car_wash", type: "casino", type: "cimetière", type: "église", type: "city_hall", type: " Magasin de vêtements ", type:" magasin de commodité ", type:" palais de justice ", type:" dentiste ", type:" magasin de magasin ", type:" médecin ", type:" électricien " , type: "magasin_électronique", type: "ambassade", type: "établissement", type: "finance", type: "station_feu", type: "fleuriste", type: "food", type: "funeral_home", type: "furniture_store", type: "gas_station", type: "general_contractor", type: "épicerie_ou_supermarché", type : "gym", type: "hair_care", type: "hardware_store", type: "health", type: "hindu_temple", type: "home_goods_store", type : "hôpital", type: "assurance_agence", type: "bijouterie", type: "blanchisserie", type: "avocat", type: "bibliothèque", type: " liquor_store ", type:" local_gouvernement_office ", type:" serrurier ", type:" logement ", type:" repas_livraison ", type:" repas_takeaway ", type:" mosquée " , type: "movie_rental", type: "movie_theater", type: "moving_company", type: "musée", type: "night_club", type: "peintre", type: "park", type: "parking", type: "pet_store", type: "pharmacie", type: "physiothérapeute", type: "place_of_worship", type : "plombier", type: "police", type: "post_office", type: "real_estate_agency", type: "restaurant", type: "roofing_contractor", type: " rv_park ", type:" school ", type:" shoe_store ", type:" shopping_mall ", type:" spa ", type:" stadium ", type:" storage " , type: "store", type: "station de métro", type: "synagogue", type: "taxi_stand", type: "station de train", type: "agence de voyage", type: "université", type: "veterinary_care", type: "zoo"]
Ext.define ('Locator.model.Category', extension: 'Ext.data.Model', config: champs: ["type", nom: "nom", type: "chaîne", converti: fonction ( v, record) // Convertit en casse du titre et retourne le retour Locator.util.Util.toTitleCase (record.get ('type'). split ('_'). join ("));," taille " ]);
La propriété "name" de ce modèle utilise la même valeur "type" de la catégorie. Comme la plupart des types ont un "trait de soulignement", cette fonction de conversion crée une valeur en omettant le "_" et en convertissant la chaîne en casse du titre. Ainsi, "travel_agency" devient "Agence de voyage"et on enregistre sous la propriété name de ce modèle.
Ext.define ('Locator.store.Categories', extend: 'Ext.data.Store', config: modèle: 'Locator.model.Category', autoLoad: true, trieurs: 'nom', groupeur: groupFn : function (record) return record.get ('name') [0];, proxy: type: 'ajax', url: Locator.util.Util.api.categories, lecteur: type: 'json ', rootProperty:' categories ');
Nous chargeons automatiquement le magasin car il devrait s'agir de la première demande de l'application. Nous utilisons une fonction de groupeur pour une liste groupée et trions par le premier caractère de chaque nom de service.
La vue par catégorie est une liste simple. Nous utilisons les fonctionnalités indexBar et groupées pour accéder facilement à tous les types.
Ext.define ('Locator.view.Categories', extend: 'Ext.List', xtype: 'categories', config: cls: 'default-bg category-list', itemTpl: 'name', magasin : 'Catégories', groupées: true, indexBar: true, titre: Lang.home);
La liste ressemble à ceci:
Nous pouvons ajouter certains ensembles de variables préexistantes pour modifier le thème Sencha existant et obtenir un nouveau look. Ce qui suit est le fichier SASS. Si vous n'avez pas encore configuré SASS, suivez ce billet pour un guide détaillé..
// Définitions de couleurs de base $ base-color: # 333; $ base-gradient: 'matte'; $ active-color: # 36B8FF; // Styles de barre d'outils $ toolbar-base-color: # 444; // Liste des styles $ list-header-bg-color: # ABE2FF; @import 'sencha-touch / default / all'; // Vous pouvez supprimer l'un des modules suivants que vous // n'utilisez pas pour créer un fichier css plus petit. @include sencha-panel; @include sencha-buttons; @include sencha-sheet; @include sencha-picker; @include sencha-tabs; @include sencha-toolbar; @include sencha-toolbar-forms; @include sencha-indexbar; @include sencha-list; @include sencha-layout; @include sencha-carrousel; @include sencha-form; @include sencha-msgbox; @include sencha-loading-spinner; @include sencha-list-pullrefresh;
Nous changeons la couleur de la barre d’outils supérieure et celle de l’en-tête de la liste, puis ajoutons le plug-in liste.
Une fois que nous avons cliqué sur l'un des éléments de catégorie, nous souhaitons afficher toutes les entreprises situées à proximité de l'emplacement actuel de l'utilisateur dans cette catégorie. Nous devons suivre cet ensemble de tâches:
Nous pouvons soit utiliser directement la fonction de géolocalisation du navigateur, soit utiliser celle de Sencha. Ext.device.Geolocation. Nous enregistrons la latitude et la longitude dans le Util exemple pour une utilisation future.
Ext.device.Geolocation.getCurrentPosition (success: function (position) me.util.userLocation = position.coords.latitude + ',' + position.coords.longitude;, échec: function () me.util. showMsg (Lang.locationRetrievalError););
L'API Google Places ne prend pas encore en charge les requêtes JSONP. Par conséquent, nous ne pourrons pas récupérer les données directement du côté client. Nous devons utiliser un serveur proxy pour récupérer les données. Ce problème peut être résolu en utilisant PHP et cURL.
le Config Le fichier contient un certain nombre de constantes. Nous définissons l'URL de base de l'API, le type de sortie de données et les détails de taille.
define ("BASE_API_URL", "https://maps.googleapis.com/maps/api/place/"); define ("DATA_OUTPUT_TYPE", "json"); define ("IMAGE_MAX_HEIGHT", 500); define ("IMAGE_MAX_WIDTH", 500);
C'est une classe PhP qui contient la fonctionnalité pour configurer l'URL, envoyer des requêtes cURL et récupérer des données.
class Locatr / ** * Configure l'URL en fonction des paramètres passés * @return String Une URL complète avec toutes les chaînes de la requête * / fonction statique privée getFinalUrl () return html_entity_decode (BASE_API_URL. $ _ REQUEST ["action"]. " /".DATA_OUTPUT_TYPE. "?". $ _ SERVER ['QUERY_STRING']); / ** * Une fonction générique pour envoyer toutes les demandes cURL * @return String Réponse pour cette demande cURL * / fonction statique privée sendCurlRequest () // Récupère la ressource cURL $ curl = curl_init (); // Définit quelques options - nous passons aussi ici dans un agent utilisateur curl_setopt_array ($ curl, array (CURLOPT_RETURNTRANSFER => 1, CURLOPT_URL => self :: getFinalUrl (), CURLOPT_SSL_VERIFYPEER => false, CURLOPT_USER = )); // Envoyer la demande et enregistrer la réponse à $ resp $ response = curl_exec ($ curl); // Ferme la requête pour effacer certaines ressources curl_close ($ curl); return $ response; / ** * Récupère tous les lieux à proximité et une image de chacun s'il est disponible * @return String Renvoie tous les lieux dans json * / fonction statique publique getNearBySearchLocations () try $ data = json_decode (self :: sendCurlRequest ()) ; $ item = ""; pour ($ i = 0; $ i < count($data -> résultats); $ i ++) $ item = $ data -> résultats [$ i]; if (isset ($ item -> photos)) $ imageUrl = BASE_API_URL. "photo? photoreference =". $ item -> photos [0] -> photo_reference. "& sensor = false & maxheight = 300 & maxwidth = 300 & key =". $ _ GET ["key"]; $ data -> résultats [$ i] -> photos [0] -> url = $ imageUrl; return json_encode ($ data); catch (Exception $ e) print "Erreur à getNearBySearchLocations:". $ e -> getMessage ();
Voici les fonctionnalités de chaque méthode de cette classe:
file_get_contents ()
méthode aussi bien pour obtenir les données ici.Cette URL est construite avec la première référence d'image et transmise avec les données de réponse pour chaque lieu. Cela nous aide à afficher au moins une image disponible pour chaque entreprise..
Ce fichier est juste utilisé pour appeler le getNearBySearchLocations fonction de la classe Locator. Nous envoyons les demandes ajax de notre côté client directement dans ce fichier.
include_once 'config.php'; include_once 'Locatr.php'; $ action = $ _REQUEST ["action"]; if (! isset ($ action)) lance une nouvelle exception ("le paramètre" action "n'est pas fourni"); switch ($ action) case "nearbysearch": print Locatr :: getNearBySearchLocations (); Pause;
Pour la liste des places, nous avons besoin d’un magasin et d’un modèle similaire à la liste des catégories..
Ext.define ('Locator.model.Place', extension: 'Ext.data.Model', config: champs: ["adresse_formé", "géométrie", "icône", "id", "nom", " classement "," référence "," types "," environs "," photos "]);
Ext.define ('Locator.store.Places', extend: 'Ext.data.Store', config: modèle: 'Locator.model.Place', proxy: type: 'ajax', url: Locator.util .Util.api.nearestPlaces, lecteur: type: 'json', rootProperty: 'results');
Jusqu'à présent, nous n'avions besoin d'un contrôleur pour aucune fonctionnalité, car la liste de catégories était automatiquement renseignée par son magasin. Nous avons maintenant besoin du contrôleur pour gérer les événements. Nous listerons tous les composants requis sous la propriété des références du contrôleur.
refs: categoriesList: 'catégories', main: 'main', placeList: 'placelist'
La liste click event dans les contrôles:
contrôle: categoriesList: itemtap: 'loadPlaces'
Lorsque vous cliquez sur une catégorie, nous voulons afficher la liste des lieux disponibles dans cette catégorie. Comme indiqué précédemment, nous allons d'abord rechercher l'emplacement actuel de l'utilisateur, puis, avec la latitude et la longitude, nous enverrons une demande ajax au fichier action.php. Le contrôleur avec le "loadPlaces"fonction ressemble à ceci:
Ext.define ('Locator.controller.App', extend: 'Ext.app.Controller', nécessite: ['Ext.device.Geolocation', 'Ext.Map'], util: Locator.util.Util, config : refs: categoriesList: 'categories', main: 'main', placeList: 'placelist', contrôle: categoriesList: itemtap: 'loadPlaces', / ** * Récupérer toutes les places pour une particlur category * / loadPlaces: function (liste, index, cible, enregistrement) var me = ceci, loadPlaces = function () // Afficher la page de liste d'emplacements me.showPlaceList (record); // charger le magasin avec l'emplacement de l'utilisateur, radius, type et clé api store.getProxy (). setExtraParams (emplacement: me.util.userLocation, action: me.util.api.nearBySearch, rayon: me.util.defaultSearchRadius, capteur: false, clé: me.util .API_KEY, types: record.get ('type')); store.load (fonction (enregistrements) me.util.showLoading (me.getPlaceList (), false););, store = Ext.getStore ('Lieux'); // Si l'emplacement de l'utilisateur n'est pas défini, récupérez-le. // Sinon, chargez les emplacements pour l'emplacement enregistré de l'utilisateur if (! Me.uti l.userLocation) Ext.device.Geolocation.getCurrentPosition (success: function (position) me.util.userLocation = position.coords.latitude + ',' + position.coords.longitude; loadPlaces (); , échec: function () me.util.showMsg (Lang.locationRetrievalError); ); else // Nettoyer le magasin s'il y a des données précédentes. removeAll (); loadPlaces (); , / ** * Afficher la liste des lieux * / showPlaceList: function (record) this.getMain (). Push (xtype: 'placelist', titre: record.get ('name')); );
le PlaceList La vue est aussi une simple liste. Nous utilisons ici XTemplate pour utiliser certaines fonctions de filtrage. le getImage fonction reçoit l'image de l'entreprise. Si l'image n'est pas disponible, elle renvoie l'icône de cette entreprise..
Ext.define ('Locator.view.PlaceList', extend: 'Ext.List', xtype: 'placelist', config: cls: 'placelist default-bg', magasin: 'Places', emptyText: Lang.placeList .emptyText, itemTpl: Ext.create ('Ext.XTemplate', '[this.getImage (values)]', '','', // Renvoie l'image de l'entreprise si disponible. Sinon, l'icône disponible pour cette entreprise getImage: function (data) if (data.photos && data.photos.length> 0) return ''; revenir 'prénom','environs',' rating: this.getRating ',''; , // Affiche un classement par étoiles. Les détails fonctionnels sont donnés dans la classe Util getRating: function (rating) return Locator.util.Util.getRating (rating); ));
Nous obtenons une note de zéro à cinq pour les entreprises. Au lieu d'afficher le numéro d'évaluation, nous pouvons écrire une fonction simple pour afficher les évaluations sous forme d'étoiles. Nous ajoutons le getRating fonction à la util fichier, qui peut être utilisé dans les fonctions de ce modèle PlaceList:
Il y a trois images: aucune étoile, une étoile et une étoile. Le CSS est donné ci-dessous:
getRating: function (rating, max, hideRatingValue) if (rating! == undefined) var str = ''; classement = parseFloat (classement); max = max || 5; // On divise l’évaluation en une partie jusqu’à la valeur maximale pour (var i = 1; i < = max; i++) // For each 1 rating, add a full star if (i < = rating) str += ''; if (i> rating) // Si la notation de la pièce est une décimale comprise entre 0 et 1, ajoutez une demi-étoile if (notation% 1! == 0 &&; (i - rating) < 1) str += ''; // Pour toute valeur d'évaluation de pièce 0, n'ajoutez pas d'étoile else str + = ''; if (! hideRatingValue) str + = ''; retour str; return Lang.noRating;'+ rating +''; str + = '
.évaluations débordement: auto; .ratings div.star float: left; hauteur: 14px; largeur: 14px; taille du fond: 12px! important; position de base: 50%; .ratings .full-star background: url (… /images/full_star.png) no-repeat; .ratings .half-star background: url (… /images/half_star.png) no-repeat; .ratings .no-star background: url (… /images/no_star.png) no-repeat; .ratings .value float: left; taille de police: 13px; poids de police: gras; marge gauche: 5px;
Voici la finale PlaceList vue.
/ ******************************* Liste des lieux ***************** ************* / .placelist.x - list - emptytext font - size: 14px; couleur: #fff; rembourrage: 20px; .x - list.placelist.x - list - item.x - dock - horizontal border: 0! important; .x - list.placelist.x - list - item.item / * background: rgba (255, 255, 255, 0.8); taille de police: 14px; remplissage: 8px; * / / * fond: rgba (255, 255, 255, 0.8); * / fond: -webkit - dégradé (linéaire, gauche en haut, gauche en bas, couleur - stop (0%, #ffffff), couleur - stop (47%, # f6f6f6), couleur - stop (100%, #ededed)); / * Chrome, Safari4 + * / background: -webkit - linéaire - dégradé (en haut, #ffffff 0%, # f6f6f6 47%, avec une taille inférieure à 100%); / * Chrome10 +, Safari5.1 + * / font - size: 14px; bordure - rayon: 5px; rembourrage: 8px; - webkit - box - shadow: 0 0 10px 2px rgba (0, 0, 0, 0.6); rembourrage - droite: 82px; .x - list.placelist.x - list - item.item.name font - weight: bold; marge: 3px 0 8px 0; .x - list.placelist.x - list - item.item.vicinity font - size: 12px; couleur: # 222; marge inférieure: 10px; .x-list.placelist .x-list-item .item .rating .x-list.placelist .x-list-item .photo, .x-list.placelist .x-list-item .icon-wrapper position: absolue; afficher: -webkit-box; -webkit-box-align: centre; -webkit-box-pack: centre; à droite: 25px; en haut: 6px; .x-list.placelist .x-list-item .photo img largeur max: 75px; hauteur maximale: 63px; bordure: blanc 2px; -webkit-box-shadow: 0 0 5px 0px rgba (0, 0, 0, 0.5); fond: noir; .x-list.placelist .x-list-item .icon-wrapper background: # 960000; bordure: blanc 2px; - webkit - box - shadow: 0 0 5px 0px rgba (0, 0, 0, 0.5); .x - list.placelist.x - list - item.icon width: 50px; hauteur: 50px; fond blanc; - webkit - mask - image: url (http: //maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png); - webkit - masque - taille: 35px; - webkit - masque - répéter: non - répéter; - kit web - masque - position: 50%; / ******************************* Liste des End End FIN *************** *************** /Et comme nous utilisons un arrière-plan sombre, nous devons modifier un peu le fichier CSS tiré de l'actualisation pour l'actualiser. Donc, ajoutez les css suivants dans le fichier locator.css:Nous pouvons ajouter un plug-in d'extraction à rafraîchir à cette liste d'emplacement. Ajoutez simplement le code ci-dessous dans le PlaceList configuration de tableau.
plugins: [xclass: 'Ext.plugin.PullRefresh', pullRefreshText: Lang.placeList.pullToRefresh]
/ * Tirez pour rafraîchir le plugin * / .x-list-pullrefresh color: #fff; .X-list-pullrefresh-flèche -webkit - masque: url centre centre (données: image / png; base64, iVBORw0KGgoAAAANSUhEUgAAACgAAAA8CAYAAAAUufjgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjFJREFUeNrsmU8oREEYwOexdtNuKBfFwdVhCyfuysnFiXISS + 1BLopyUpKLXETkRLaUi1LK3Q2lpPbiQLnIn03a / Hm + z86Ttv0zM ++ bfbOar36Hbad5v535Zp7v47iuy0wOpyoEHccRHV9L9NxPkUE / bhKCOKiOSPAdn69DsJ5I8E2HYA0QJRJ8Bb50CDYRCT7pEMQD0kwk + CByUFQEW4gE73UIhoA2IsFb4ENEMCQ5MdU1IxwygpT3oKNLMGyyYFVscdhusc8tDpu + xRG7xf95BW0O2kNiV1AgIvaQ2BzUJNgJNJYZGyUU7OG1cal4Bi68oqkDPszy2teEwJp5Cdyu / lZ1g8CwIYJ7wEF + 2YmrNw90Byx3BizgKhaqizEP1wg7CLLxCEzy / CtauMeBlQDyEfNuGrgU6SyM8F9SyVgHdmRaH6tAb4XkToEp2d4M5mOK0TWMigU2koa8vJMRZPxEb2ss2LEVPMpPLlMRxBgDZjQJLgNbxb6Uab9tAn3EcifAeKkBMoLY + j0GWonk7oB + lmsFkwhidAGHBPmIeTcAnJcbKCuIMQEs + hScAzZEBqoIYuzyFVCJI36lMJ2CDfxibZeUu + EX / 4uMIFP8ZyLejxkgK0hG5a8kP4IYSZbr1IuQVHmAX0HGX4VuGfZVJ6cQxPd1uoRcWqDW0SroFVzZAnJZ / h0LWhAjUUAw4XdSSsH8fExRTEgtGAOuOTETBb16Jk412e + bxOSwglYw6PgWYABvLk8P7zGJFwAAAABJRU5ErkJggg == ) non - répéter; background: #fff;
Ici ça va:
Ceci est la première partie du tutoriel. Nous avons créé une liste de services fournis par l'API Google Adresses, puis pour un service donné, et une liste de tous les lieux à proximité. Dans la prochaine et dernière partie de ce didacticiel, nous aborderons les fonctionnalités suivantes:
Sencha est actuellement l'une des plus puissantes bibliothèques mobiles basées sur HTML5. Une fois que vous l'avez configuré, vous serez capable d'écrire de superbes applications mobiles fluides. Ces applications peuvent être utilisées comme sites Web mobiles ou peuvent être intégrées à Phonegap pour créer des applications hybrides iOS et Android..
La deuxième partie de ce tutoriel est disponible maintenant. Trouvez-le ici: Créez un site sensible à la localisation avec Sencha Touch - Affichage des lieux.