如何在 Flutter Web 中使用 Google 地图库?

How to use the Google Maps library with Flutter Web?

我正在将一个 flutter 移动项目移植到 flutter web,想知道如何将 google 地图库与 Flutter Web 一起使用。

请看其他回答。比这个更简单!

我能够找到一个可行的解决方案,但它并不完美。下面是实现。如果我有时间并且合法端口不会很长时间,我会 post 一个示例 repo。

import 'dart:html';

import 'package:flutter_web/material.dart';
import 'package:lift_ai/base/screen_state.dart';
import 'package:lift_ai/feature/property_common/property_contract.dart';
import 'package:lift_ai/feature/property_common/property_presenter_impl.dart';
import 'package:lift_ai/model/car_status.dart';
import 'package:lift_ai/model/property.dart';
import 'package:flutter_web_ui/ui.dart' as ui;
import 'package:lift_ai/util/widget_util.dart';


class PropertyMapPage extends StatefulWidget {
  final CarStatus carStatus;

  PropertyMapPage(Key key, this.carStatus) : super(key: key);

  @override
  _PropertyMapPageState createState() => _PropertyMapPageState(carStatus);
}

class _PropertyMapPageState extends State<PropertyMapPage>
    implements PropertyListView {
  PropertyPresenter _propertyListPresenter;
  List<Property> properties = [];
  CarStatus carStatus;
  String createdViewId = 'hello-world-html';
  bool inProgress = true;

  _PropertyMapPageState(this.carStatus) {
    _propertyListPresenter = PropertyPresenterImpl(this);
  }

  @override
  void initState() {
    super.initState();
    _propertyListPresenter.getProperties(carStatus, "");
  }

  @override
  void dispose() {
    super.dispose();
    _propertyListPresenter = null;
  }

  @override
  Widget build(BuildContext context) {
    print("Creating html view");

    if (inProgress) {
      return Center(child: CircularProgressIndicator());
    }

    return Row(
      children: <Widget>[
        Container(
            width: MediaQuery.of(context).size.width - 400,
            child: HtmlView(
              viewType: createdViewId,
            )),
        Container(
          width: 400,
          child: properties.isEmpty
              ? WidgetUtil.getEmptyPropertiesView(context)
              : ListView.builder(
                  padding: EdgeInsets.all(8.0),
                  itemCount: properties.length,
                  itemBuilder: (_, index) {
                    return WidgetUtil.buildListRow(
                        context, _propertyListPresenter, properties[index]);
                  },
                ),
        ),
      ],
    );
  }

  @override
  void showProperties(List<Property> properties) {
    String markers = "";

    for (Property property in properties) {
      String marker =
          "var marker = new google.maps.Marker({position: new google.maps.LatLng(${property.lat}, ${property.lng}), map: map, title: 'Hello ${property.id}!'});\n";
      markers += marker;
    }

    String createdViewUpdate = DateTime.now().toString();

    rootBundle.loadString('map.html').then((value) {
      value = value.replaceAll(new RegExp(r'markers'), markers);

      ui.platformViewRegistry.registerViewFactory(
          createdViewId,
          (int viewId) => IFrameElement()
            ..width = (MediaQuery.of(context).size.width - 400).toString()
            ..height = MediaQuery.of(context).size.height.toString()
            ..srcdoc = value
            ..style.border = 'none');
    });

    setState(() {
      inProgress = false;
      this.createdViewId = createdViewUpdate;
      this.properties = properties;
    });
  }

  @override
  void updateScreenState(ScreenState screenState) { }

  @override
  void showException(String string) {
    // TODO: implement showException
  }
}

map.html

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Simple Markers</title>
    <style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
</head>
<body>
<div id="map"></div>
<script>

      function initMap() {
        var myLatLng = {lat: 41.850033, lng: -87.6500523};

        var map = new google.maps.Map(document.getElementById('map'), {
          zoom: 4,
          center: myLatLng
        });

        markers

      }
    </script>
<script async defer
        src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=initMap">
</script>
</body>
</html>

下面@panavtec 概述的答案也有效,并且可能 api 更容易使用!

他的解决方案的示例存储库在这里:

https://github.com/dazza5000/flutter_web_google_maps_example

如果你需要使用这个库,我找到了这个替代方案:

Widget getMap() {
String htmlId = "7";

final mapOptions = new MapOptions()
  ..zoom = 8
  ..center = new LatLng(-34.397, 150.644);

// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(htmlId, (int viewId) {
  final elem = DivElement()
    ..id = htmlId
    ..style.width = "100%"
    ..style.height = "100%"
    ..style.border = 'none';

  new GMap(elem, mapOptions);

  return elem;
});

return HtmlElementView(viewType: htmlId);
}

我没有彻底测试它,但它似乎渲染了地图。

此解决方案的基本工作示例如下:

https://github.com/dazza5000/flutter_web_google_maps_example

创建了项目的视频演练:

https://www.youtube.com/watch?v=iW7pCBL7yWk

Barebones 博客文章遍历解决方案:

http://whereisdarran.com/2020/01/google-maps-for-flutter-web/