sep 122012
 

Buenas,

Estoy aquí de nuevo con otra versión de los componentes GMLib para Delphi/C++ Builder. En esta ocasión no tenemos nuevo componentes (es lo que tiene venir de vacaciones jejejeje), pero al menos he puesto al día los existentes con las nuevas características de la API de Google Maps y les he añadido alguna que otra mejora.

También he incluido un par de librerías OpenSource, la MarkerWithLabel y la StyledMarker. No descarto que en próximas versiones se incluya alguna otra de estas magníficas librerías.

Aquí la lista de cambios:

  • error: algún memory leak corregido (aun queda alguno que miraré de ir corrigiendo) (gracias Donovan)
  • cambio: TGMCircle -> modificados métodos Set y ShowElement para que usen el nuevo método ChangeProperties heredado de TLinkedComponent
  • cambio: GMFunctions -> añadidas nuevas funciones de transformación de tipos
  • cambio: TGMGeoCode-> añadida propiedad booleana PaintMarkerFound. A true se generarán automáticamente los marcadores (si hay un TGMMarker asociado) (por Luis Joaquin Sencion)
  • cambio: TGMGeoCode-> en DoMarkers se codifica la URL generada en UTF8 para evitar problemas con carácteres especiales (ñ, acentos, ….)
  • cambio: TGMMap.TNonVisualProp -> añadida propiedad MapMaker. A true si queremos que los mosaicos de Map Marker se muestren en lugar de los normales
  • cambio: TLatLngEvent -> los eventos de este tipo ahora reciben un nuevo parámetro, X y Y, de tipo Real, con la información del punto (X,Y)
  • cambio: TLinkedComponent -> añadida propiedad booleana ShowInfoWinMouseOver. A true, se mostrará el InfoWindows mientras el ratón esté encima del objeto. Actualmente válido sólo para TMarker (por Luis Joaquin Sencion).
  • cambio: TLinkedComponent -> añadido método protegido ChangeProperties para centralizar en un sólo sitio el cambio de las propiedades de los objectos.
  • cambio: TGMMarker -> modificados métodos Set y ShowElement para que usen el nuevo método ChangeProperties heredado de TLinkedComponent
  • cambio: suprimida clase TMarkerLatLng. Ahora se usa directamente la clase TLatLng
  • cambio: TMarker -> la pripiedad Position ahora es de tipo TLatLng.
  • cambio: TMarker -> añadida propiedad MarkerType para especificar el tipo de marcador a mostrar (mtStandard, mtColored, mtStyledMarker).
  • cambio: TMarker -> añadida propiedad ColoredMarker para especificar la forma del marcador si MarkerType = mtColored.
  • cambio: TMarker -> añadida propiedad StyledMarker para especificar la forma del marcador si MarkerType = mtStyledMarker.
  • cambio: TGMMarker -> añadido método público LoadFromCSV para una carga masiva de marcadores que estén en un archivo CSV (unos 50 marcadores/seg.).
  • cambio: TGMMarker-> 4 nuevos eventos: OnLoadFile y AfterLoadFile para el procesado del fichero CSV, y OnColoredMarkerChange y OnStyledMarkerChange para el cambio de las propiedades
  • cambio: TGMPolygon -> modificados métodos Set y ShowElement para que usen el nuevo método ChangeProperties heredado de TLinkedComponent
  • cambio: creada clase intermedia (TBasePolyline) entre TLinkedComponent y TPolyline. TPolygon desciende ahora de TBasePolyline.
  • cambio: creada clase intermedia (TGMBasePolyline) entre TGMLinkedComponent y TGMPolyline. TGMPolygon desciende ahora de TGMBasePolyline.
  • cambio: TGMPolyline -> modificados métodos Set y ShowElement para que usen el nuevo método ChangeProperties heredado de TLinkedComponent
  • cambio: TPolyline -> nueva propiedad Icon para definir el tipo de linea de la polilinea.
  • cambio: TGMRectangle -> modificados métodos Set y ShowElement para que usen el nuevo método ChangeProperties heredado de TLinkedComponent

Como siempre, podéis ver más explicaciones y descargar los componentes en su página.

Qué los disfrutéis!

Nos leemos

ago 072012
 

Buenas,

Antes de bajar la persiana por vacaciones, quiero presentaros una nueva versión de los componentes GMLib para Delphi. Hay bastantes novedades (sobretodo en el mapa al que se le han añadido varias capas -layers-) y un nuevo componente, el TGMDirections. Aquí la lista de las novedades:

  • Nuevo componente, el TGMDirection, para el cálculo de rutas. Dado que es un componente complejo (por el volumen de clases que intervienen -20 clases nuevas-), agradecería comentarios de funcionalidad.
  • Cambio: se translada a la clase base la función GetConvertedString.
  • Nuevo: TGMObjects -> nueva clase que hereda de TGMBase y de la que heredarán clases como TGMLinkedComponent o TGMDirection
  • Nuevo: TGMMaps -> añadida propiedad Layers para el acceso a las capas (layers) de Google Maps como:
    • Panoramio (clase TPanoramio)
    • Traffic (clase TTraffic)
    • Transit (clase TTransit)
    • Bicyclig (clase TBicycling)
    • Weather (clase TWeather)
  • Nuevo: TGMMaps -> añadidos eventos OnWeatherClick y FOnPanoramioClick.
  • Cambio: TGMMaps -> se cambian los métodos xxToStr y StrToxxx para reducir código.
  • Cambio: TGMMaps -> los métodos Printxxxx y SaveToJPGFile usan los métodos de la unidad WebControls.
  • Error: TGMPolyline -> corregido error cuando se intentaba mostrar una polilineasin TLinePoints.
  • Nuevo: Lang -> añadido el idioma francés (gracias Stéphane).
  • Nuevo: TWebControl -> Se añade método SaveToJPGFile.
  • Nuevo: TSizeable -> añadido método Assign.
  • Error: TSizeable -> cuando no era circular, el radio crecía más que el máximo.
  • Nuevo: TAddressComponent -> añadido método Assign.
  • Nuevo: TAddressComponentsList -> añadido método Assign.
  • Nuevo: TGeometry -> añadido método Assign.
  • Nuevo: TGeoResult -> añadido método Assign.
  • Nuevo: TGoogleBusiness -> añadido método Assign.
  • Nuevo: TGMGeoCode -> se sobreescribe el método Notification para controlar la propiedad Marker.
  • Cambio: TGMGeoCode -> se trasladan los métodos xxToStr y StrToxxx a la clase TTransform de la unidad GMFunctions.
  • Nuevo: TGMGeoCode -> añadido método Assign.
  • Nuevo: TTransform -> nueva clase con transformaciones xxxToStr y StrToxxx para transformar las propiedades tipo Set a string y de string a la propiedad tipo Set.
  • Nuevo: General -> el proyecto se ha dividido en 2 packages para poder compilar en 64 bits en XE2.
  • Nuevo: General -> Compilado para Delphi 2009 y C++ XE2

Como siempre, podéis ver más explicaciones y descargar los componentes en su página.

Qué los disfrutéis!

Nos leemos

jul 122012
 

Buenas,

Pues nada, ya estamos aquí con una nueva versón de la GMLib. Esta nueva versión viene con bastantes cambios y, como no, con un componente nuevo. Aquí tenéis la relación de las novedades:

  • Nuevo componente, el TGMGeoCode, para poder realizar Geocodificaciones (pasar de una dirección a una lat/lng o de una lat/lng a una dirección).
  • Error:  TGMBaseInfoWindow -> la función GetConvertedString ahora tiene en cuenta la comilla simple.
  • Cambio: TGMCircle -> la propiedad Radius pasa a ser un entero.
  • Nuevo: TGMCircle -> añadida propiedad AutoResize.
  • Error: TLatLng -> corregido error en la función LatLngToStr (gracias Erasmo).
  • Cambio: TLatLng -> se controla la posible excepción en la función StringToReal (cambio de string a real).
  • Cambio: TLatLngBounds -> se suprime la función GetCenter.
  • Error: TGMMarker -> se controlan la comilla simple en la propiedad Title.
  • Nuevo: TGMPolyline -> añadida propiedad CountLinePoints.
  • Nuevo: TLinePoint -> añadido método ToStr.
  • Nuevo: TLinePoint -> añadida método StringToReal.
  • Nuevo: TRectangle -> añadido método GetCenter.
  • Nuevo: TGMMap -> añadidos eventos OnActiveChange, OnIntervalEventsChange y OnPrecisionChange.
  • Error: TGMMap -> corregido error en RemoveLinkedComponent cuando se intentaba suprimir un objeto sin estar la lista creada.
  • Cambio: TGMMap -> se controlan los métodos Set de las propiedades Zoom y MapType para actualizar el mapa automáticamente.
  • Cambio: TGMMap -> Zoom, MaxZoom y MinZoom se limitan al rango de 0 a 15
  • Nuevo: TLinkedComponent -> se añade la propiedad Text (visible a todos sus descendientes menos a TMarker porque ya tiene la propiedad Title).
  • Nuevo: TGMLinkedComponent -> añadida propiedad Count.
  • Error: cuando había figuras de diferentes tipos juntas o superpuestas, daba un error de JavaScript al pasar el ratón sobre ellas (gracias Erasmo).
  • Nuevo: mega demo que incluye la gestión de todos los componentes.

Como siempre, más información en la página de los componentes.

Qué los disfrutéis

Nos leemos

jun 262012
 

Buenas,

Siguiendo con los GMLib, hoy os traigo la versión 0.1.4 Pre-Alpha, con los siguientes cambios y novedades:

  • Nuevo componente, el TCircle. Con este componente ya terminamos con las figuras.
  • Nuevo: se ha ampliado la funcionalidad del TGMMap haciéndolo imprimible mediante los métodos PrintNoDialog, PrintWithDialog, PrintPreview y PrintPageSetup, y también la posibilidad de guardar el mapa a un JPG mediante el método SaveToJPGFile.
  • Cambio: cambios en el JavaScript del mapa para evitar duplicidad de código.
  • Error: corregido error en el método LatLngToStr de la clase TLatLng (gracias Shaun)

Como siempre, más información en la página de los componentes.

Que los disfrutéis

Nos leemos

jun 212012
 

Buenas,

Hoy os traigo una nueva versión de los componentes GMLib, la versión 0.1.3 Pre-Alpha, con bastantes cambios internos y novedades:

  • Nuevo componente, el TRectangle que, como su nombre indica, no es más que un rectángulo.
  • Cambio: se ha cambiado la carpeta destino de los DCU. Ahora, cada versión de Delphi tiene la suya.
  • Nuevo: se ha añadido el evento OnChange en la clase TLatLng.
  • Nuevo: se ha añadido el método público StringToReal en la clase TLatLng. Este método tiene en cuenta la configuración regional en el momento de hacer el cambio. Con esta función se intenta corregir los problemas que había entre los países con diferente configuración regional.
  • Nuevo: se ha añadido el método GetCenter en la clase TLatLngBounds.
  • Cambio: se han publicado las propiedades NE y SW de la clase TLatLngBounds.
  • Nuevo: se ha añadido la propiedad Tag (entero) a la clase TLinkedComponent (por lo que afecta a todos los CollectionItems heredados de la misma como TMarker, TPolygon,….).
  • Nuevo: se ha añadido la propiedad FObject (TObject) a la clase TLinkedComponent.
  • Nuevo: se han añadido métodos protegidos (SetProperty) en la clase TLinkedComponent para generalizar el cambio de las propiedades y evitar la duplicidad de código.
  • Nuevo: se ha añadido la propiedad Icon al TMarker para poder especificar un icono a mostrar (en lugar del estándar). Éste puede ser un archivo en el PC o una imagen en la web. El componente lo que hace es comprobar si existe el dato especificado como archivo y, en caso de no existir, asume que es una URL (no me he complicado mucho la vida en hacer muchas comprobaciones). En blanco para la imagen por defecto.
  • Nuevo: se ha añadido el evento OnIconChange a la clase TGMMarker.
  • Cambio: se han cambiado todos los métodos Set de las clases descendientes de TLinkedComponent para evitar la duplicidad de código y hacer las llamadas a los nuevos métodos de TLinkedComponent (SetProperty).

Como siempre, más información en la página de los componentes.

Que los disfrutéis

Nos leemos

may 292012
 

Buenas,

Sigo con las nuevas actualizaciones de los componentes, hoy presentando la 0.1.2 Pre-Alpha. Las novedades de esta nueva versión son las siguientes:

  • Un nuevo componente, el TGMPolygon. Éste es como el TGMPolyline pero con la particularidad que el último punto se unirá con el primero.
  • Bug: corregido error en TGMMarker que hacía que al cambiar alguna de sus propiedades diera un error de JavaScript.
  • Cambio: cuando cambia la lat/lng de un TLinePoint, se actualiza en el mapa.
  • Bug: implementado SetPath en JavaScript.

Como siempre, más información en la página de los componentes.

Que los disfrutéis

Nos leemos

 

abr 162012
 

Buenas,

Hoy vengo a presentaros una nueva versión (la 0.1.1 Pre-Alpha) de los componentes GMLib. Las novedades de esta nueva versión son las siguientes:

  • Un nuevo componente, el TGMPolyline, para la creación de polilineas (una polilinea es un conjunto de puntos unidos entre sí mediante líneas).
  • Corrección de algún bug encontrado.
  • Se le ha añadido la propiedad AutoOpen a la clase TInfoWindow.
  • Se ha añadido el evento OnPositionChange a la clase TInfoWindow.
  • Muchos cambios en el JavaScript para hacer las funciones más genéricas.
  • Se ha añadido el método Clear a la clase base TGMLinkedComponent.
  • Se ha añadido el método Assign a la clase base TGMLinkedComponent.
  • Se ha añadido el método Clear en la clase base TLinkedComponents.
  • Se ha cambiado las referencias a la API de Google Maps al nuevo dominio.
  • Cuando se cambia la lat/lng de un marcador, se cambia automáticamente en el mapa.
  • Se ha añadido el método Assign en la clase TGMSize.

Podéis encontrar más explicaciones en la página de los componentes.

Espero que os sea de utilidad

Nos leemos

 

mar 202012
 

Buenas,

A raíz de los diferentes artículos hechos sobre el uso de la API de Google Maps desde aplicaciones Delphi, se me ocurrió el realizar una serie de componentes que encapsularan dicho funcionamiento y hacer más fácil la vida al programador.

De momento os presento los tres primeros componentes:

  • TGMMaps: componente que diseña el mapa plano, sin objetos, sólo con lo necesario para visualizar una zona y desplazarte por la misma (zoom, scroll, ……). También es el que gestiona la comunicación con el mapa a nivel de eventos y/o cambio de cualquier tipo de propiedad/objeto del mapa. A su vez, mantiene un TList con todo objeto que se linca a él y que represente algún tipo de objeto en el mapa (marcadores, ventanas de información, lineas, polilíneas, rectángulos,……).
  • TGMMarker: componente que mantiene una relación de marcadores (clase TMarker) mediante una TCollection (TMarkers).
  • TGMInfoWindow: componente que mantiene una relación de ventanas de información o balloons (clase TInfoWindow) mediante una TCollection (TInfoWindows).

El próximo componente será el TGMPolyline, para gestionar las polilíneas.

He creado una página específica de estos componente donde se explica el funcionamiento, sus propiedades y métodos y desde donde podréis descargar los fuentes y demos.

Espero que os sean de utilidad

Nos leemos

oct 192010
 

Buenas,

Vimos en un mensaje anterior cómo configurar visualmente nuestro mapa de Google Maps. Antes de ver el StreetView quería comentar una cosa al respecto. En la documentación del API podemos observar la existencia de un método llamado setOptions que, como parámetro, recibe un objeto de tipo MapOptions. Por el nombre del método y el parámetro recibido podríamos pensar que no sería necesaria la creación de todo el mapa si queremos cambiar el comportamiento inicial del mapa. Pues bien, he realizado la prueba y no termina de funcionar como debe, así que daremos por válido lo que decía antes de que se debe de establecer todo en la creación.

Y ahora, el StreetView

Bien, dicho ésto, vamos a ver el StreetView.

Cualquier mapa de Google Maps contiene la imagen de un hombrecito en la zona del zoom (ver imagen 1 al pie del mensaje) que arrastrándolo y soltándolo donde queramos, nos abre el StreetView. Fijaros que, en el momento de arrastrarlo, donde existe StreetView se colorea en azul (ver imagen 2 al pie del mensaje).

Este hombrecito es, como todo aspecto visual de un mapa de Google Maps, configurable en la creación del mapa. Estas propiedades las obvié en el mensaje anterior expresamente para poderlas explicar ahora. Por supuesto, pertenecen al objeto MapOptions.

  • streetViewControl: booleano para mostrar o no el hombrecito.
  • streetView: propiedad de tipo StreetViewPanorama que representa la panorámica StreetView que se mostrará al soltar el hombrecillo. Si no se define ninguna, se generará una predeterminada y se mostrará en el div del mapa. Os recomiendo una lectura de esta clase dado que aquí sólo veremos el constructor de la misma, el cual recibe dos parámetros, container que es dónde se mostrará (un div) y opts de tipo StreetViewPanoramaOptionsdel que veremos ahora sus propiedades:
    • addressControl: booleano para mostrar o ocultar el cartel con la dirección.
    • addressControlOptions: propiedad de tipo StreetViewAddressControlOptionscon las opciones de visualización del control de dirección.
      • position: propiedad de tipo ControlPosition para especificar dónde aparecerá el control. Por defecto TOP_LEFT.
      • style: string con la especificación CSS a aplicar al control de posición. Por ejemplo, {backgroundColor: ‘red’}.
    • enableCloseButton: booleano para mostrar o ocultar el botón de cierre de la ventana StreetView.
    • linksControl: booleano para mostrar o ocultar el control de desplazamiento por las calles.
    • navigationControl: booleano para mostrar o ocultar el control de navegación.
    • navigationControlOptions: propiedad de tipo NavigationControlOptionscon las opciones de visualización del control de navegación.
      • position: propiedad de tipo ControlPosition para especificar dónde aparecerá el control. Por defecto TOP_LEFT.
      • style: propiedad de tipo NavigationControlStyle para especificar el tipo de navegador.
    • position: propiedad de tipo LatLng donde se centrará el mapa.
    • pov: propiedad de tipo StreetViewPovpara especificar la orientación de la cámara (según ángulo, inclinación y zoom).
      • heading: numérico que expresa el ángulo en grados respecto al norte absoluto siendo el norte 0º, el este 90º, el sur 180º y el oeste 270.
      • pitch: numérico que expresa la inclinación de la cámara en grados respecto al vehículo de Street View y oscila entre 90º (arriba) y -90º (abajo).
      • zoom: numérico para indicar el nivel del zoom siendo el más lejano el 0.

En la imagen 3 podéis ver a qué se refiere cada una de las propiedades.

Desde Delphi

Vista la teoría, llega el momento de ponerlo en práctica.

Cuando creamos un mapa, tenemos dos opciones, especificar una panorámica o dejar que el objeto mapa cree una predeterminada. Con la primera opción, podremos controlar todo el aspecto visual del StreeView. En cambio, si dejamos que se cree la predeterminada, mediante los métodos del StreetViewPanorama sólo podremos controlar la longitud/latitud (método setPosition) y la orientación de la cámara (método setPov).

Una vez creado el mapa, sea de la forma que sea, podemos acceder a la panorámica del mismo gracias al método getStreetView de la clase Map. Así mismo, podríamos establecer una panorámica nueva mediante setStreetView.

En nuestro ejemplo, escogeremos la opción de personalizar el StreetView en la creación del mapa y mostrarlo en un div diferente al mapa, así podremos ver las diferentes alternativas que tenemos. Para ello, lo primero es modificar la pantalla para poder acceder a las opciones del StreetView (ver imagen 4 al pie del mensaje). Hay que tener presente que, si las coordenadas pasadas no tienen una referencia válida para StreetView, éste no aparecerá.

Lo primero que hay que hacer es adaptar nuestra función JavaScript para poder recibir la configuración del StreetView. Para ello añadiremos 8 nuevos parámetros. También se tiene que crear el objeto StreetViewPanorama con sus opciones. Y puestos a modificar, para no repetir código, crearemos funciones para la obtención de las diferentes constantes.

  function GetPosition(aPos) {
    switch (aPos) {
      case "BOTTOM": return google.maps.ControlPosition.BOTTOM; break;
      case "BOTTOM_LEFT": return google.maps.ControlPosition.BOTTOM_LEFT; break;
      case "BOTTOM_RIGHT": return google.maps.ControlPosition.BOTTOM_RIGHT; break;
      case "LEFT": return google.maps.ControlPosition.LEFT; break;
      case "RIGHT": return google.maps.ControlPosition.RIGHT; break;
      case "TOP": return google.maps.ControlPosition.TOP; break;
      case "TOP_LEFT": return google.maps.ControlPosition.TOP_LEFT; break;
      default: return google.maps.ControlPosition.TOP_RIGHT;
    }
  }

  function GetNavigationControl(aNav) {
    switch (aNav) {
      case "ANDROID": return google.maps.NavigationControlStyle.ANDROID; break;
      case "SMALL": return google.maps.NavigationControlStyle.SMALL; break;
      case "ZOOM_PAN": return google.maps.NavigationControlStyle.ZOOM_PAN; break;
      default: return google.maps.NavigationControlStyle.DEFAULT;
    }
  }

  function MenuStyle(aStyleMenu) {
    switch (aStyleMenu) {
      case "DROPDOWN_MENU": return google.maps.MapTypeControlStyle.DROPDOWN_MENU; break;
      case "HORIZONTAL_BAR": return google.maps.MapTypeControlStyle.HORIZONTAL_BAR; break;
      default: return google.maps.MapTypeControlStyle.DEFAULT;
    }
  }

  function MapType(aTMap) {
    switch (aTMap) {
      case "HYBRID": return google.maps.MapTypeId.HYBRID; break;
      case "ROADMAP": return google.maps.MapTypeId.ROADMAP; break;
      case "SATELLITE": return google.maps.MapTypeId.SATELLITE; break;
      default: return google.maps.MapTypeId.TERRAIN;
    }
  }

  function DoWeb(Lat,Lon,TMap,aZoom,ZClick,MoveMap,Keyb,Wheel,HideAll,ShowTM,
                 PosTM,StyleTM,ShowNav,PosNav,StyleNav,ShowScale,PosScale,
                 SV,DirecSV,PosDirecSV,CloseSV,LinksSV,NavSV,PosNavSV,StyleNavSV) {
    if (map != null) map.setStreetView(null);
    panorama = null;
    map = null;

    aTMap = MapType(TMap);
    aPosTM = GetPosition(PosTM);
    aStyleTM = MenuStyle(StyleTM);
    aPosNav = GetPosition(PosNav);
    aStyleNav = GetNavigationControl(StyleNav);
    aPosScale = GetPosition(PosScale);
    aPosDirecSV = GetPosition(PosDirecSV);
    aPosNavSV = GetPosition(PosNavSV);
    aStyleNavSV = GetNavigationControl(StyleNavSV);

    var latlng = new google.maps.LatLng(Lat,Lon); 

    var panoOpts = {
      addressControl: DirecSV,
      addressControlOptions: {position: aPosDirecSV},
      enableCloseButton: CloseSV,
      linksControl: LinksSV,
      navigationControl: NavSV,
      navigationControlOptions: {position: aPosNavSV, style:aStyleNavSV},
      position: latlng
    }

    panorama =
        new google.maps.StreetViewPanorama(document.getElementById("streetview"),
        panoOpts);

    var myOptions = {
      center: latlng,
      mapTypeId: aTMap,
      zoom: aZoom, 

      disableDoubleClickZoom: ZClick,
      draggable: MoveMap,
      keyboardShortcuts: Keyb,
      scrollwheel: Wheel, 

      mapTypeControl: ShowTM,
      mapTypeControlOptions: {position: aPosTM, style: aStyleTM},
      navigationControl: ShowNav,
      navigationControlOptions: {position: aPosNav, style: aStyleNav},
      scaleControl: ShowScale,
      scaleControlOptions: {position: aPosScale},

      streetViewControl: true,
      streetView: panorama
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  }

A nivel de código Delphi, lo único que tendremos que hacer es modificar la llamada a la función JavaScript pasándole los nuevos parámetros.

Si quisiéramos que la panorámica de StreetView se viera en el mismo div que el mapa, bastará con que cambiemos la línea de creación del panorama y pasarle de parámetro el div del mapa

panorama =
    new google.maps.StreetViewPanorama(document.getElementById("map_canvas"),
    panoOpts);

No obstante, con las pruebas que he realizado, sólo funciona correctamente la primera vez que se crea el mapa con la panorámica de StreetView personalizada. Si alguien hace pruebas y ve cómo arreglarlo, estaría agradecido que me lo comentara.

Más en próximos artículos.

 

Como siempre, podéis descargaros el programa demo desde aquí.

Nos leemos

oct 092010
 

Buenas,

Una vez visto cómo mostrar un mapa de Google Maps, cómo centrarlo y cómo poner marcas, ahora toca el momento de personalizarlo.

En la versión 3 del API de Google Maps, hay que tener en cuenta que no se permite añadir o eliminar controles de forma dinámica, éstos deben de establecerse en la creación del mapa.

El objeto MapOptions

Este objeto será el encargado de dar la forma inicial a nuestro mapa. Para ver todas sus propiedades, te aconsejo una visita a la API de Google Maps ya que aquí sólo veremos los más interesantes (o al menos desde mi punto de vista).

Obligatorias
  • center: propiedad que determina dónde se centrará el mapa al mostrarlo. Es obligatoria y es de tipo LatLng.
  • mapTypeId: propiedad de tipo MapTypeId obligatoria y que es cómo se mostrará inicialmente el mapa.
  • zoom: entero obligatorio con el zoom aplicado al mapa.
Visuales
  • disableDefaultUI: booleano para mostrar o no todos los controles del mapa. Por defecto están habilitados.
  • mapTypeControl: booleano para mostrar o no el tipo de mapa. Por defecto habilitado.
  • mapTypeControlOptions: propiedad del tipo MapTypeControlOptions para configuración del control del tipo de mapa cuando éste se muestra.
    • mapTypeIds: array con los tipos de mapa a mostrar. Ver MapTypeId.
    • position: propiedad de tipo ControlPosition para especificar dónde se mostrará el control. Por defecto TOP_RIGHT. Las constantes posibles son:
      • BOTTOM
      • BOTTOM_LEFT
      • BOTTOM_RIGHT
      • LEFT
      • RIGHT
      • TOP
      • TOP_LEFT
      • TOP_RIGHT
    • style: propiedad de tipo MapTypeControlStyle para determinar el estilo del control. Los posibles valores son:
      • DEFAULT
      • DROPDOWN_MENU
      • HORIZONTAL_BAR
  • navigationControl: booleano para mostrar o no el control de navegación.
  • navigationControlOptions: propiedad de tipo NavigationControlOptions con las propiedades del control de navegación.
    • position: propiedad de tipo ControlPosition.
    • style: propiedad de tipo NavigationControlStyle para especificar el tipo de navegador. Las constantes posibles son:
      • ANDROID
      • DEFAULT
      • SMALL
      • ZOOM_PAN
  • scaleControl: booleano para mostrar o no el control de escala.
  • scaleControlOptions: propiedad de tipo ScaleControlOptions con las opciones del control de escala.
No visuales
  • disableDoubleClickZoom: booleano para des/habilitar el zoom con el clic de ratón.
  • draggable: booleano para des/habilitar el poder mover el mapa. Por defecto se puede.
  • keyboardShortcuts: booleano para des/habilitar el control del mapa con el teclado. Por defecto habilitado.
  • scrollwheel: booleano para des/habilitar el control de la rueda del ratón. Habilitado por defecto.

Aplicando lo visto a Delphi

Una vez vistas las configuraciones posibles del mapa, nos queda ver cómo hacerlo desde Delphi.

Basándonos en los ejemplos anteriores, crearemos una constante (MAPA_CODE) que contendrá el código html y JavaScript necesario. En éste, destacar la creación de una nueva función JavaScript que será llamada desde Delphi y será la encargada de generar el mapa con la configuración que hayamos especificado en el programa. La función es esta:

  function DoWeb(Lat,Lon,TMap,aZoom,ZClick,MoveMap,Keyb,Wheel,ShowTM,
                 PosTM,StyleTM,ShowNav,PosNav,StyleNav,ShowScale,PosScale) {
    switch (TMap) {
      case "HYBRID": aTMap = google.maps.MapTypeId.HYBRID; break;
      case "ROADMAP": aTMap = google.maps.MapTypeId.ROADMAP; break;
      case "SATELLITE": aTMap = google.maps.MapTypeId.SATELLITE; break;
      default: aTMap = google.maps.MapTypeId.TERRAIN;
    } 

    switch (PosTM) {
      case "BOTTOM": aPosTM = google.maps.ControlPosition.BOTTOM; break;
      case "BOTTOM_LEFT": aPosTM = google.maps.ControlPosition.BOTTOM_LEFT; break;
      case "BOTTOM_RIGHT": aPosTM = google.maps.ControlPosition.BOTTOM_RIGHT; break;
      case "LEFT": aPosTM = google.maps.ControlPosition.LEFT; break;
      case "RIGHT": aPosTM = google.maps.ControlPosition.RIGHT; break;
      case "TOP": aPosTM = google.maps.ControlPosition.TOP; break;
      case "TOP_LEFT": aPosTM = google.maps.ControlPosition.TOP_LEFT; break;
      default: aPosTM = google.maps.ControlPosition.TOP_RIGHT;
    } 

    switch (StyleTM) {
      case "DROPDOWN_MENU": aStyleTM = google.maps.MapTypeControlStyle.DROPDOWN_MENU; break;
      case "HORIZONTAL_BAR": aStyleTM = google.maps.MapTypeControlStyle.HORIZONTAL_BAR; break;
      default: aStyleTM = google.maps.MapTypeControlStyle.DEFAULT;
    } 

    switch (PosNav) {
      case "BOTTOM": aPosNav = google.maps.ControlPosition.BOTTOM; break;
      case "BOTTOM_LEFT": aPosNav = google.maps.ControlPosition.BOTTOM_LEFT; break;
      case "BOTTOM_RIGHT": aPosNav = google.maps.ControlPosition.BOTTOM_RIGHT; break;
      case "LEFT": aPosNav = google.maps.ControlPosition.LEFT; break;
      case "RIGHT": aPosNav = google.maps.ControlPosition.RIGHT; break;
      case "TOP": aPosNav = google.maps.ControlPosition.TOP; break;
      case "TOP_LEFT": aPosNav = google.maps.ControlPosition.TOP_LEFT; break;
      default: aPosNav = google.maps.ControlPosition.TOP_RIGHT;
    } 

    switch (StyleNav) {
      case "ANDROID": aStyleNav = google.maps.NavigationControlStyle.ANDROID; break;
      case "SMALL": aStyleNav = google.maps.NavigationControlStyle.SMALL; break;
      case "ZOOM_PAN": aStyleNav = google.maps.NavigationControlStyle.ZOOM_PAN; break;
      default: aStyleNav = google.maps.NavigationControlStyle.DEFAULT;
    } 

    switch (PosScale) {
      case "BOTTOM": aPosScale = google.maps.ControlPosition.BOTTOM; break;
      case "BOTTOM_LEFT": aPosScale = google.maps.ControlPosition.BOTTOM_LEFT; break;
      case "BOTTOM_RIGHT": aPosScale = google.maps.ControlPosition.BOTTOM_RIGHT; break;
      case "LEFT": aPosScale = google.maps.ControlPosition.LEFT; break;
      case "RIGHT": aPosScale = google.maps.ControlPosition.RIGHT; break;
      case "TOP": aPosScale = google.maps.ControlPosition.TOP; break;
      case "TOP_LEFT": aPosScale = google.maps.ControlPosition.TOP_LEFT; break;
      default: aPosScale = google.maps.ControlPosition.TOP_RIGHT;
    } 

    var latlng = new google.maps.LatLng(Lat,Lon);
    var myOptions = {
      center: latlng,
      mapTypeId: aTMap,
      zoom: aZoom, 

      disableDoubleClickZoom: ZClick,
      draggable: MoveMap,
      keyboardShortcuts: Keyb,
      scrollwheel: Wheel, 

      mapTypeControl: ShowTM,
      mapTypeControlOptions: {position: aPosTM, style: aStyleTM},
      navigationControl: ShowNav,
      navigationControlOptions: {position: aPosNav, style: aStyleNav},
      scaleControl: ShowScale,
      scaleControlOptions: {position: aPosScale} 

    };
    map = null;
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  }
Las constantes posibles son:

Como podemos ver, la función recibe tantos parámetros como posibles configuraciones tengamos. Lo primero que hace es coger el valor de las constantes necesarias según los parámetros recibidos (los 6 switch). Luego creamos el objeto que contendrá la longitud y latitud y el que contendrá todas las opciones del mapa. Para terminar, liberamos el objeto map por si existía y lo volvemos a crear con las características nuevas.

A nivel de código Delphi, pues queda hacer la llamada cómo ya hemos visto en anterioridad:

const
  StrParams = '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s';
var
  Doc2: IHTMLDocument2;
  Win2: IHTMLWindow2;
  Params: String;
begin
  Doc2 := wbWeb.Document as IHTMLDocument2;
  Win2 := Doc2.parentWindow;

  Params := Format(StrParams, [eLong.Text,
                               eLat.Text,
                               QuotedStr(cbTypMap.Text),
                               IntToStr(tbZoom.Position),
                               LowerCase(BoolToStr(not chZoomClick.Checked, True)),
                               LowerCase(BoolToStr(chDrag.Checked, True)),
                               LowerCase(BoolToStr(chTeclado.Checked, True)),
                               LowerCase(BoolToStr(chWheel.Checked, True)),
                               LowerCase(BoolToStr(chShowTypeMap.Checked, True)),
                               QuotedStr(cbTMPosition.Text),
                               QuotedStr(cbTMStyle.Text),
                               LowerCase(BoolToStr(chNavigation.Checked, True)),
                               QuotedStr(cbNPosition.Text),
                               QuotedStr(cbNStyle.Text),
                               LowerCase(BoolToStr(chScale.Checked, True)),
                               QuotedStr(cbSPosition.Text)
                               ]);

  Win2.execScript('DoWeb(' + Params + ')', 'JavaScript');
end;

Aquí os dejo un ejemplo de la pantalla.

También podéis descargaros los fuentes y el binario del programa desde aquí.

Otro día más.

Nos leemos