Saltar al contenido

¿Cómo cambiar el tamaño del icono del marcador de Google Maps en Flutter?

Solución:

TL; DR: Siempre que puedan codificar cualquier imagen en bytes sin formato, como Uint8List, debería estar bien usándolo como marcador.


A partir de ahora, puede usar Uint8List datos para crear sus marcadores con Google Maps. Eso significa que puedes usar crudo datos para pintar lo que quieras como marcador de mapa, siempre y cuando mantengas el formato de codificación correcto (que en este escenario particular, es un png).

Revisaré dos ejemplos en los que puedes:

  1. Elija un activo local y cambie dinámicamente su tamaño a lo que desee y renderícelo en el mapa (una imagen del logotipo de Flutter);
  2. Dibuja algunas cosas en el lienzo y renderízalas como marcador también, pero esto puede ser alguna renderizar widget.

Además de esto, incluso puede transformar un widget de renderizado en una imagen estática y, por lo tanto, usarlo también como marcador.


1. Usar un activo

Primero, cree un método que maneje la ruta del activo y reciba un tamaño (esto puede ser el ancho, el alto o ambos, pero usar solo uno preservará la proporción).

import 'dart:ui' as ui;

Future<Uint8List> getBytesFromAsset(String path, int width) async {
  ByteData data = await rootBundle.load(path);
  ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width);
  ui.FrameInfo fi = await codec.getNextFrame();
  return (await fi.image.toByteData(format: ui.ImageByteFormat.png)).buffer.asUint8List();
}

Luego, simplemente agréguelo a su mapa usando el descriptor correcto:

final Uint8List markerIcon = await getBytesFromAsset('assets/images/flutter.png', 100);
final Marker marker = Marker(icon: BitmapDescriptor.fromBytes(markerIcon));

Esto producirá lo siguiente para 50, 100 y 200 de ancho respectivamente.

asset_example


2. Usando lienzo

Puedes dibujar lo que quieras con el lienzo y luego usarlo como marcador. Lo siguiente producirá una caja redondeada simple con un Hello world! texto en él.

Entonces, primero dibuja algunas cosas usando el lienzo:

Future<Uint8List> getBytesFromCanvas(int width, int height) async {
  final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
  final Canvas canvas = Canvas(pictureRecorder);
  final Paint paint = Paint()..color = Colors.blue;
  final Radius radius = Radius.circular(20.0);
  canvas.drawRRect(
      RRect.fromRectAndCorners(
        Rect.fromLTWH(0.0, 0.0, width.toDouble(), height.toDouble()),
        topLeft: radius,
        topRight: radius,
        bottomLeft: radius,
        bottomRight: radius,
      ),
      paint);
  TextPainter painter = TextPainter(textDirection: TextDirection.ltr);
  painter.text = TextSpan(
    text: 'Hello world',
    style: TextStyle(fontSize: 25.0, color: Colors.white),
  );
  painter.layout();
  painter.paint(canvas, Offset((width * 0.5) - painter.width * 0.5, (height * 0.5) - painter.height * 0.5));
  final img = await pictureRecorder.endRecording().toImage(width, height);
  final data = await img.toByteData(format: ui.ImageByteFormat.png);
  return data.buffer.asUint8List();
}

y luego utilícelo de la misma manera, pero esta vez proporcionando los datos que desee (por ejemplo, ancho y alto) en lugar de la ruta del activo.

final Uint8List markerIcon = await getBytesFromCanvas(200, 100);
final Marker marker = Marker(icon: BitmapDescriptor.fromBytes(markerIcon));

Y aquí lo tienes.

canvas_example

Actualicé la función anterior, ahora puedes escalar la imagen como quieras.

  Future<Uint8List> getBytesFromCanvas(int width, int height, urlAsset) async {
    final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
    final Canvas canvas = Canvas(pictureRecorder);

    final ByteData datai = await rootBundle.load(urlAsset);
    var imaged = await loadImage(new Uint8List.view(datai.buffer));
    canvas.drawImageRect(
      imaged,
      Rect.fromLTRB(
          0.0, 0.0, imaged.width.toDouble(), imaged.height.toDouble()),
      Rect.fromLTRB(0.0, 0.0, width.toDouble(), height.toDouble()),
      new Paint(),
    );

    final img = await pictureRecorder.endRecording().toImage(width, height);
    final data = await img.toByteData(format: ui.ImageByteFormat.png);
    return data.buffer.asUint8List();
  }

Aquí hay un ejemplo de mayo de 2020 de cómo agregar un marcador de mapa de Google personalizado.

Mi aplicación de ejemplo:

importaciones:

import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';

Cree una instancia de su mapa de marcadores en algún lugar de su clase principal con estado:

Map<MarkerId, Marker> markers = <MarkerId, Marker>{};

Función para convertir el activo del icono en un objeto Uint8List (no complicado en absoluto):

Future<Uint8List> getBytesFromAsset(String path, int width) async {
    ByteData data = await rootBundle.load(path);
    ui.Codec codec =
        await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width);
    ui.FrameInfo fi = await codec.getNextFrame();
    return (await fi.image.toByteData(format: ui.ImageByteFormat.png)).buffer.asUint8List();
   }

agregar función de marcador (llame a esto con sus coordenadas de latitud y longitud en el lugar donde desea los marcadores)

  Future<void> _addMarker(tmp_lat, tmp_lng) async {
    var markerIdVal = _locationIndex.toString();
    final MarkerId markerId = MarkerId(markerIdVal);
    final Uint8List markerIcon = await getBytesFromAsset('assets/img/pin2.png', 100);

    // creating a new MARKER
    final Marker marker = Marker(
      icon: BitmapDescriptor.fromBytes(markerIcon),
      markerId: markerId,
      position: LatLng(tmp_lat, tmp_lng),
      infoWindow: InfoWindow(title: markerIdVal, snippet: 'boop'),
    );

    setState(() {
      // adding a new marker to map
      markers[markerId] = marker;
    });
  }

pubspec.yaml (siéntase libre de probar diferentes íconos)

flutter:

  uses-material-design: true

  assets:
    - assets/img/pin1.png
    - assets/img/pin2.png
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *