使用网络图像的谷歌地图标记(无法将字节解释为有效图像.)



我试图让我的谷歌地图标记从firebase存储生成图标,我尝试了一些事情与BitmapDescriptor和Uint8list,但未能理解什么是需要使这项工作。需要什么使标记图标从网络图像?我见过这个插件,但它不适合web。我需要做些什么才能使下面的代码显示标记图标。

删除旧的不良示例代码

我已经更新了代码,试图实现Curt的建议。我终于把它归结为一个错误,似乎我很接近了。
  1. [ERROR:flutter/runtime/dart_vm_initializer.cc(41)]未处理异常:PlatformException(错误,无法将字节解释为有效图像)。
  2. :无法将字节解释为有效的图像。

当我打印字节时,它以一系列数字的形式出现,当我打印_bitmapdescriptor时,我不幸地得到" 'BitmapDescriptor'的实例"备份错误信息。

我需要做些什么才能正确地解释它?

import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import '../models/marker_collect_model.dart';
class ShowMapPublic extends StatefulWidget {
@override
_ShowMapState createState() => _ShowMapState();
}
class _ShowMapState extends State<ShowMapPublic> {
GoogleMapController? controller;
List<Marker> list = [];
List<String> listDocuments = [];
void _onMapCreated(GoogleMapController controllerParam) {
setState(() {
controller = controllerParam;
});
}
void readDataFromFirebase() async {
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference<Map<String, dynamic>> collectionReference =
firestore.collection('2022BHAM');
collectionReference.snapshots().listen((event) async {
List<DocumentSnapshot> snapshots = event.docs;
for (var map in snapshots) {
Map<String, dynamic> data =
map.data() as Map<String, dynamic>; // add this line
MarkerCollectModel model =
await MarkerCollectModel.fromMap(data); // use data here
String nameDocument = map.id;
listDocuments.add(nameDocument);
Marker marker = await createMarker(model, nameDocument);
setState(() {
list.add(marker);
});
}
});
}
Future<BitmapDescriptor> _buildMarkerIcon(String pathImage) async {
// Fetch the PNG
Image _image = await Image.network(pathImage);
// Encode the image as a list of ints
List<int> list = utf8.encode(_image.toString());
// Convert the int list into an unsigned 8-bit bytelist
Uint8List bytes = Uint8List.fromList(list);
// And construct the BitmapDescriptor from the bytelist
BitmapDescriptor _bitmapDescriptor = BitmapDescriptor.fromBytes(bytes);
// And return the product
return _bitmapDescriptor;
}
Future<Marker> createMarker(
MarkerCollectModel markerCollectModel, String nameDocument) async {
Marker marker;
marker = Marker(
markerId: MarkerId(nameDocument),
icon: await _buildMarkerIcon(markerCollectModel.urlavatar!),
position: LatLng(markerCollectModel.lat!, markerCollectModel.lng!),
);
return marker;
}
Set<Marker> myMarkers() {
return list.toSet();
}
// Method
@override
void initState() {
super.initState();
readDataFromFirebase();
}
@override
Widget build(BuildContext context) {
CameraPosition cameraPosition =
CameraPosition(target: LatLng(40.788717, -99.496509), zoom: 2.5);
return Scaffold(
backgroundColor: Colors.black,
body: Center(
child: Stack(
children: <Widget>[
GoogleMap(
initialCameraPosition: cameraPosition,
markers: myMarkers(),
onMapCreated: _onMapCreated,
),
],
)));
}
}

icon应该是BitmapDescriptor类。该类只能通过BitmapDescriptor.fromJson()构造函数用json初始化。json应该描述标记的颜色,主要是颜色。请看这里的官方文档。

如果必须使用图像作为图标,则应该使用flutter_map包。这意味着你将不得不重做大量的代码。本教程可能会有所帮助。

首先要知道这个答案应该作为一个解决方案大纲来阅读。我没有在实际的工作代码中实现任何这些。话虽如此,它应该工作。在阅读各种文档的基础上,我把这个解决方案放在一起,如果我真的要编码它,我就会尝试这样做。

约束:根据Google文档,加载的图像必须编码(或至少返回)为PNG。

<<p>

解决方案计划/strong>BitmapDescriptor提供了一个FromBytes方法,可以用来从序列化的数据流中构造一个BitmapDescriptor。

接下来,观察Image提供toString()方法,将加载的图像转换为字符串。 然后你可以把这个字符串转换成Uint8List
通过利用一些实用程序方法
List<int> list = utf8.encode(source);
Uint8List bytes = Uint8List.fromList(list);

(感谢Osama Gamal在之前的回答中提供了这部分解决方案)

最后使用BitmapDescriptor.FromBytes()生成图标数据。

再次,假设您加载的网络图像是BitMapDescriptor所要求的PNG,似乎可以达到您的目标。

把它放在一起…

我把它写成了一个异步方法。还有其他的方法等待图像出现,但这是最简单的说明目的。

您将'等待_buildMarkerIcon(foo)'或'_buildMarkerIcon(foo) '。然后((位图描述符bmd){使用它}'作为你的用例需要。

祝你好运,我希望这能帮助到别人。

BitmapDescriptor _buildMarkerIcon(String pathImage) async {
// Fetch the PNG
Image _image = await Image.network(pathImage);
// Encode the image as a list of ints
List<int> list = utf8.encode(_image.toString());
// Convert the int list into an unsigned 8-bit bytelist
Uint8List bytes = Uint8List.fromList(list);
// And construct the BitmapDescriptor from the bytelist
BitmapDescriptor _bitmapDescriptor = BitmapDescriptor.fromBytes(bytes);
// And return the product
return _bitmapDescriptor;
}