Los mapas de calor son útiles para representar la distribución y la densidad de los datos en un mapa.
Introducción
La biblioteca de utilidades del SDK de Maps para Android incluye una utilidad de mapa de calor que puedes usar para agregar uno o más mapas de calor a un mapa de Google en tu aplicación.
En este video se discute el uso de mapas de calor como alternativa a los marcadores cuando la naturaleza de tu información se condice con una gran cantidad de datos que deberían señalarse en el mapa.
Los mapas de calor permiten a los usuarios comprender la distribución y la intensidad relativa de los datos de un mapa de manera sencilla. En los mapas de calor, en lugar de colocar un marcador en cada ubicación, se usan colores para representar la distribución de los datos.
En el siguiente ejemplo, el rojo representa las áreas con una alta concentración de comisarías en Victoria, Australia.
Si todavía no configuraste la biblioteca de utilidades del SDK de Maps para Android, sigue la guía de configuración antes de leer el resto de esta página.
Cómo agregar un mapa de calor simple
Para agregar un mapa de calor a tu mapa, necesitarás un conjunto de datos compuesto por las coordenadas de cada ubicación de interés. Primero, crea HeatmapTileProvider
y pásale la colección de objetos LatLng
. Luego, crea una clase TileOverlay
nueva, pásale el proveedor de mosaicos de mapas de calor y agrega la superposición de mosaicos al mapa.
La utilidad suministra la clase HeatmapTileProvider
, que implementa la interfaz de TileProvider
para proporcionar las imágenes de mosaico del mapa de calor.
La clase HeatmapTileProvider
acepta una colección de objetos LatLng
(o de objetos WeightedLatLng
, según lo que se describe a continuación). Esta clase crea las imágenes de mosaicos para diferentes niveles de zoom según las opciones de radio, gradiente y opacidad suministradas. Puedes cambiar los valores predeterminados para estas opciones.
Una vista más detallada de los pasos:
- Usa
HeatmapTileProvider.Builder()
y pásale una colección de objetosLatLng
para agregar una claseHeatmapTileProvider
nueva. - Crea un nuevo objeto
TileOverlayOptions
con las opciones relevantes, incluidoHeatmapTileProvider
. - Llama a
GoogleMap.addTileOverlay()
para agregar la superposición al mapa.
Kotlin
private fun addHeatMap() { var latLngs: List<LatLng?>? = null // Get the data: latitude/longitude positions of police stations. try { latLngs = readItems(R.raw.police_stations) } catch (e: JSONException) { Toast.makeText(context, "Problem reading list of locations.", Toast.LENGTH_LONG) .show() } // Create a heat map tile provider, passing it the latlngs of the police stations. val provider = HeatmapTileProvider.Builder() .data(latLngs) .build() // Add a tile overlay to the map, using the heat map tile provider. val overlay = map.addTileOverlay(TileOverlayOptions().tileProvider(provider)) } @Throws(JSONException::class) private fun readItems(@RawRes resource: Int): List<LatLng?> { val result: MutableList<LatLng?> = ArrayList() val inputStream = context.resources.openRawResource(resource) val json = Scanner(inputStream).useDelimiter("\\A").next() val array = JSONArray(json) for (i in 0 until array.length()) { val `object` = array.getJSONObject(i) val lat = `object`.getDouble("lat") val lng = `object`.getDouble("lng") result.add(LatLng(lat, lng)) } return result }
Java
private void addHeatMap() { List<LatLng> latLngs = null; // Get the data: latitude/longitude positions of police stations. try { latLngs = readItems(R.raw.police_stations); } catch (JSONException e) { Toast.makeText(context, "Problem reading list of locations.", Toast.LENGTH_LONG).show(); } // Create a heat map tile provider, passing it the latlngs of the police stations. HeatmapTileProvider provider = new HeatmapTileProvider.Builder() .data(latLngs) .build(); // Add a tile overlay to the map, using the heat map tile provider. TileOverlay overlay = map.addTileOverlay(new TileOverlayOptions().tileProvider(provider)); } private List<LatLng> readItems(@RawRes int resource) throws JSONException { List<LatLng> result = new ArrayList<>(); InputStream inputStream = context.getResources().openRawResource(resource); String json = new Scanner(inputStream).useDelimiter("\\A").next(); JSONArray array = new JSONArray(json); for (int i = 0; i < array.length(); i++) { JSONObject object = array.getJSONObject(i); double lat = object.getDouble("lat"); double lng = object.getDouble("lng"); result.add(new LatLng(lat, lng)); } return result; }
Para este ejemplo, los datos se almacenan en un archivo JSON, police_stations.json
. Aquí se proporciona un extracto del archivo:
[ {"lat" : -37.1886, "lng" : 145.708 } , {"lat" : -37.8361, "lng" : 144.845 } , {"lat" : -38.4034, "lng" : 144.192 } , {"lat" : -38.7597, "lng" : 143.67 } , {"lat" : -36.9672, "lng" : 141.083 } ]
Cómo usar puntos ponderados de latitud y longitud
Cuando creas una clase HeatmapTileProvider
, puedes pasarle una colección de coordenadas ponderadas de latitud y longitud. Esto resulta útil si deseas ilustrar la importancia de un conjunto determinado de ubicaciones.
Para aplicar la ponderación a ubicaciones específicas, sigue estos pasos:
- Crea un objeto
WeightedLatLng
nuevo para cada ubicación que requiera ponderación. PasaLatLng
ydouble
, que representan la intensidad necesaria. La intensidad indica la importancia o el valor relativos de esta ubicación. Un valor superior generará un color más intenso en el gradiente del mapa de calor. De manera predeterminada, el color de mayor intensidad es el rojo. Llama a
HeatmapTileProvider.Builder().weightedData()
, en lugar de aHeatmapTileProvider.Builder().data()
, para crear el mapa de calor.
Cómo personalizar el mapa de calor
Varias propiedades del mapa de calor son personalizables. Puedes configurar las opciones en el momento de la creación, a través de las funciones Builder
.
También puedes modificar una opción en cualquier momento llamando al método set correspondiente en HeatmapTileProvider
; luego borra la caché de mosaicos de la superposición para que vuelva a dibujar todos los mosaicos con las opciones nuevas.
Están disponibles las siguientes opciones:
- Radio: Es el tamaño del desenfoque gaussiano que se aplica al mapa de calor, expresado en píxeles. El valor predeterminado es 20. Los valores mínimo y máximo son 10 y 50, respectivamente. Usa el elemento
radius()
de las funciones Builder para configurar el valor cuando creas el mapa de calor, o cambia el valor posteriormente consetRadius()
. - Gradiente: Es un rango de colores que se usan en el mapa de calor para generar el mapa de colores, con una intensidad de menor a mayor. Un gradiente se genera con dos arrays: uno con valores enteros que contiene los colores y el otro con números de punto flotante en el que se indica el punto de partida para cada color, como un porcentaje de la intensidad máxima y expresado como una fracción de 0 a 1. Debes especificar solo un color para un gradiente de un único color o dos colores como mínimo para un gradiente multicolor. El mapa de colores se genera aplicando una interpolación entre esos colores. El gradiente predeterminado tiene dos colores. Usa el elemento
gradient()
de las funciones Builder para configurar el valor cuando creas el mapa de calor, o cambia el valor posteriormente consetGradient()
. - Opacidad: Es la opacidad de toda la capa del mapa de calor y varía de 0 a 1. El valor predeterminado es 0.7. Usa el elemento
opacity()
de las funciones Builder para configurar el valor cuando creas el mapa de calor, o cambia el valor posteriormente consetOpacity()
.
Por ejemplo, crea un objeto Gradient
para configurar el gradiente antes de agregar el mapa de calor:
Kotlin
// Create the gradient. val colors = intArrayOf( Color.rgb(102, 225, 0), // green Color.rgb(255, 0, 0) // red ) val startPoints = floatArrayOf(0.2f, 1f) val gradient = Gradient(colors, startPoints) // Create the tile provider. val provider = HeatmapTileProvider.Builder() .data(latLngs) .gradient(gradient) .build() // Add the tile overlay to the map. val tileOverlay = map.addTileOverlay( TileOverlayOptions() .tileProvider(provider) )
Java
// Create the gradient. int[] colors = { Color.rgb(102, 225, 0), // green Color.rgb(255, 0, 0) // red }; float[] startPoints = { 0.2f, 1f }; Gradient gradient = new Gradient(colors, startPoints); // Create the tile provider. HeatmapTileProvider provider = new HeatmapTileProvider.Builder() .data(latLngs) .gradient(gradient) .build(); // Add the tile overlay to the map. TileOverlay tileOverlay = map.addTileOverlay(new TileOverlayOptions().tileProvider(provider));
Para cambiar la opacidad de un mapa de calor existente, utiliza este código:
Kotlin
provider.setOpacity(0.7) tileOverlay?.clearTileCache()
Java
provider.setOpacity(0.7); tileOverlay.clearTileCache();
Cómo cambiar el conjunto de datos
Si deseas cambiar el conjunto de datos a partir del cual se crea un mapa de calor, usa HeatmapTileProvider.setData()
. O bien, usa HeatmapTileProvider.setWeightedData()
para los puntos de WeightedLatLng
. Nota: Si deseas agregar puntos al mapa de calor o quitarlos, actualiza tu colección de datos y, luego, usa setData()
o setWeightedData()
.
Kotlin
val data: List<WeightedLatLng> = ArrayList() provider.setWeightedData(data) tileOverlay?.clearTileCache()
Java
List<WeightedLatLng> data = new ArrayList<>(); provider.setWeightedData(data); tileOverlay.clearTileCache();
Cómo quitar un mapa de calor
Para quitar el mapa de calor, debes quitar la superposición de mosaicos:
Kotlin
tileOverlay?.remove()
Java
tileOverlay.remove();
Cómo consultar la app de demo
Para ver otro ejemplo de la implementación de un mapa de calor, observa HeatmapsDemoActivity
en la app de demo que se incluye en la biblioteca de utilidades En la guía de configuración, se muestra cómo ejecutar la app de demo.