2023-12-22 21:23:24 +08:00
|
|
|
|
import 'dart:async';
|
|
|
|
|
import 'dart:typed_data';
|
|
|
|
|
import 'dart:ui';
|
|
|
|
|
|
|
|
|
|
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
|
|
|
|
import 'package:amap_map/amap_map.dart';
|
2023-12-22 23:13:56 +08:00
|
|
|
|
import 'package:x_amap_base/x_amap_base.dart';
|
2023-12-22 21:23:24 +08:00
|
|
|
|
import 'dart:math';
|
|
|
|
|
|
2023-12-30 07:54:59 +08:00
|
|
|
|
class MarkerConfigDemoPage extends StatefulWidget {
|
|
|
|
|
const MarkerConfigDemoPage();
|
2023-12-22 21:23:24 +08:00
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
State<StatefulWidget> createState() => _State();
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-30 07:54:59 +08:00
|
|
|
|
class _State extends State<MarkerConfigDemoPage> {
|
2023-12-22 21:23:24 +08:00
|
|
|
|
static final LatLng mapCenter = const LatLng(39.909187, 116.397451);
|
|
|
|
|
|
|
|
|
|
Map<String, Marker> _markers = <String, Marker>{};
|
|
|
|
|
BitmapDescriptor? _markerIcon;
|
|
|
|
|
String? selectedMarkerId;
|
|
|
|
|
|
|
|
|
|
void _onMapCreated(AMapController controller) {}
|
|
|
|
|
|
|
|
|
|
///通过BitmapDescriptor.fromAssetImage的方式获取图片
|
|
|
|
|
Future<void> _createMarkerImageFromAsset(BuildContext context) async {
|
|
|
|
|
if (_markerIcon == null) {
|
|
|
|
|
final ImageConfiguration imageConfiguration =
|
|
|
|
|
createLocalImageConfiguration(context);
|
|
|
|
|
BitmapDescriptor.fromAssetImage(imageConfiguration, 'assets/start.png')
|
|
|
|
|
.then(_updateBitmap);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///通过BitmapDescriptor.fromBytes的方式获取图片
|
|
|
|
|
Future<void> _createMarkerImageFromBytes(BuildContext context) async {
|
|
|
|
|
final Completer<BitmapDescriptor> bitmapIcon =
|
|
|
|
|
Completer<BitmapDescriptor>();
|
|
|
|
|
final ImageConfiguration config = createLocalImageConfiguration(context);
|
|
|
|
|
|
|
|
|
|
const AssetImage('assets/end.png')
|
|
|
|
|
.resolve(config)
|
|
|
|
|
.addListener(ImageStreamListener((ImageInfo image, bool sync) async {
|
|
|
|
|
final ByteData bytes =
|
|
|
|
|
(await image.image.toByteData(format: ImageByteFormat.png))!;
|
|
|
|
|
final BitmapDescriptor bitmap =
|
|
|
|
|
BitmapDescriptor.fromBytes(bytes.buffer.asUint8List());
|
|
|
|
|
bitmapIcon.complete(bitmap);
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
bitmapIcon.future.then((value) => _updateBitmap(value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _updateBitmap(BitmapDescriptor bitmap) {
|
|
|
|
|
setState(() {
|
|
|
|
|
_markerIcon = bitmap;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _add() {
|
|
|
|
|
final int markerCount = _markers.length;
|
|
|
|
|
LatLng markPostion = LatLng(
|
|
|
|
|
mapCenter.latitude + sin(markerCount * pi / 12.0) / 20.0,
|
|
|
|
|
mapCenter.longitude + cos(markerCount * pi / 12.0) / 20.0);
|
|
|
|
|
final Marker marker = Marker(
|
|
|
|
|
position: markPostion,
|
|
|
|
|
icon: _markerIcon!,
|
|
|
|
|
infoWindow: InfoWindow(title: '第 $markerCount 个Marker'),
|
|
|
|
|
onTap: (markerId) => _onMarkerTapped(markerId),
|
|
|
|
|
onDragEnd: (markerId, endPosition) =>
|
|
|
|
|
_onMarkerDragEnd(markerId, endPosition),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers[marker.id] = marker;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _onMarkerTapped(String markerId) {
|
|
|
|
|
final Marker? tappedMarker = _markers[markerId];
|
|
|
|
|
final String? title = tappedMarker!.infoWindow.title;
|
|
|
|
|
print('$title 被点击了,markerId: $markerId');
|
|
|
|
|
setState(() {
|
|
|
|
|
selectedMarkerId = markerId;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _onMarkerDragEnd(String markerId, LatLng position) {
|
|
|
|
|
final Marker? tappedMarker = _markers[markerId];
|
|
|
|
|
final String? title = tappedMarker!.infoWindow.title;
|
|
|
|
|
print('$title markerId: $markerId 被拖拽到了: $position');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _remove() {
|
|
|
|
|
final Marker? selectedMarker = _markers[selectedMarkerId];
|
|
|
|
|
//有选中的Marker
|
|
|
|
|
if (selectedMarker != null) {
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers.remove(selectedMarkerId);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
print('无选中的Marker,无法删除');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _removeAll() {
|
|
|
|
|
if (_markers.length > 0) {
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers.clear();
|
|
|
|
|
selectedMarkerId = null.toString();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _changeInfo() async {
|
|
|
|
|
final Marker marker = _markers[selectedMarkerId]!;
|
|
|
|
|
final String newTitle = marker.infoWindow.title! + '*';
|
|
|
|
|
if (selectedMarkerId != null) {
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers[selectedMarkerId!] = marker.copyWith(
|
|
|
|
|
infoWindowParam: marker.infoWindow.copyWith(
|
|
|
|
|
titleParam: newTitle,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _changeAnchor() {
|
|
|
|
|
final Marker marker = _markers[selectedMarkerId]!;
|
|
|
|
|
final Offset currentAnchor = marker.anchor;
|
|
|
|
|
double dx = 0;
|
|
|
|
|
double dy = 0;
|
|
|
|
|
if (currentAnchor.dx < 1) {
|
|
|
|
|
dx = currentAnchor.dx + 0.1;
|
|
|
|
|
} else {
|
|
|
|
|
dx = 0;
|
|
|
|
|
}
|
|
|
|
|
if (currentAnchor.dy < 1) {
|
|
|
|
|
dy = currentAnchor.dy + 0.1;
|
|
|
|
|
} else {
|
|
|
|
|
dy = 0;
|
|
|
|
|
}
|
|
|
|
|
final Offset newAnchor = Offset(dx, dy);
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers[selectedMarkerId!] = marker.copyWith(
|
|
|
|
|
anchorParam: newAnchor,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _changePosition() {
|
|
|
|
|
final Marker marker = _markers[selectedMarkerId]!;
|
|
|
|
|
final LatLng current = marker.position;
|
|
|
|
|
final Offset offset = Offset(
|
|
|
|
|
mapCenter.latitude - current.latitude,
|
|
|
|
|
mapCenter.longitude - current.longitude,
|
|
|
|
|
);
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers[selectedMarkerId!] = marker.copyWith(
|
|
|
|
|
positionParam: LatLng(
|
|
|
|
|
mapCenter.latitude + offset.dy,
|
|
|
|
|
mapCenter.longitude + offset.dx,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _changeAlpha() async {
|
|
|
|
|
final Marker marker = _markers[selectedMarkerId]!;
|
|
|
|
|
final double current = marker.alpha;
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers[selectedMarkerId!] = marker.copyWith(
|
|
|
|
|
alphaParam: current < 0.1 ? 1.0 : current * 0.75,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _changeRotation() async {
|
|
|
|
|
final Marker marker = _markers[selectedMarkerId]!;
|
|
|
|
|
final double current = marker.rotation;
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers[selectedMarkerId!] = marker.copyWith(
|
|
|
|
|
rotationParam: current == 330.0 ? 0.0 : current + 30.0,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _toggleVisible(value) async {
|
|
|
|
|
final Marker marker = _markers[selectedMarkerId]!;
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers[selectedMarkerId!] = marker.copyWith(
|
|
|
|
|
visibleParam: value,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _toggleDraggable(value) async {
|
|
|
|
|
final Marker marker = _markers[selectedMarkerId]!;
|
|
|
|
|
setState(() {
|
|
|
|
|
_markers[selectedMarkerId!] = marker.copyWith(
|
|
|
|
|
draggableParam: value,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void initState() {
|
|
|
|
|
super.initState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void dispose() {
|
|
|
|
|
super.dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
///以下几种获取自定图片的方式使用其中一种即可。
|
|
|
|
|
//最简单的方式
|
|
|
|
|
if (null == _markerIcon) {
|
|
|
|
|
_markerIcon = BitmapDescriptor.fromIconPath('assets/location_marker.png');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//通过BitmapDescriptor.fromAssetImage的方式获取图片
|
|
|
|
|
// _createMarkerImageFromAsset(context);
|
|
|
|
|
//通过BitmapDescriptor.fromBytes的方式获取图片
|
|
|
|
|
// _createMarkerImageFromBytes(context);
|
|
|
|
|
|
|
|
|
|
final AMapWidget map = AMapWidget(
|
|
|
|
|
onMapCreated: _onMapCreated,
|
|
|
|
|
markers: Set<Marker>.of(_markers.values),
|
|
|
|
|
);
|
|
|
|
|
return Container(
|
|
|
|
|
height: MediaQuery.of(context).size.height,
|
|
|
|
|
width: MediaQuery.of(context).size.width,
|
|
|
|
|
child: Column(
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
|
|
|
children: [
|
|
|
|
|
Container(
|
|
|
|
|
height: MediaQuery.of(context).size.height * 0.6,
|
|
|
|
|
width: MediaQuery.of(context).size.width,
|
|
|
|
|
child: map,
|
|
|
|
|
),
|
|
|
|
|
Expanded(
|
|
|
|
|
child: SingleChildScrollView(
|
|
|
|
|
child: Row(
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
Row(
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
Column(
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
TextButton(
|
|
|
|
|
child: const Text('添加'),
|
|
|
|
|
onPressed: _add,
|
|
|
|
|
),
|
|
|
|
|
TextButton(
|
|
|
|
|
child: const Text('移除'),
|
|
|
|
|
onPressed:
|
|
|
|
|
(selectedMarkerId == null) ? null : _remove,
|
|
|
|
|
),
|
|
|
|
|
TextButton(
|
|
|
|
|
child: const Text('更新InfoWidow'),
|
|
|
|
|
onPressed:
|
|
|
|
|
(selectedMarkerId == null) ? null : _changeInfo,
|
|
|
|
|
),
|
|
|
|
|
TextButton(
|
|
|
|
|
child: const Text('修改锚点'),
|
|
|
|
|
onPressed: (selectedMarkerId == null)
|
|
|
|
|
? null
|
|
|
|
|
: _changeAnchor,
|
|
|
|
|
),
|
|
|
|
|
TextButton(
|
|
|
|
|
child: const Text('修改透明度'),
|
|
|
|
|
onPressed: (selectedMarkerId == null)
|
|
|
|
|
? null
|
|
|
|
|
: _changeAlpha,
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
Column(
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
TextButton(
|
|
|
|
|
child: const Text('全部移除'),
|
|
|
|
|
onPressed: _markers.length > 0 ? _removeAll : null,
|
|
|
|
|
),
|
|
|
|
|
AMapSwitchButton(
|
|
|
|
|
label: Text('允许拖动'),
|
|
|
|
|
onSwitchChanged: (selectedMarkerId == null)
|
|
|
|
|
? null
|
|
|
|
|
: _toggleDraggable,
|
|
|
|
|
defaultValue: false,
|
|
|
|
|
),
|
|
|
|
|
AMapSwitchButton(
|
|
|
|
|
label: Text('显示'),
|
|
|
|
|
onSwitchChanged: (selectedMarkerId == null)
|
|
|
|
|
? null
|
|
|
|
|
: _toggleVisible,
|
|
|
|
|
defaultValue: true,
|
|
|
|
|
),
|
|
|
|
|
TextButton(
|
|
|
|
|
child: const Text('修改坐标'),
|
|
|
|
|
onPressed: (selectedMarkerId == null)
|
|
|
|
|
? null
|
|
|
|
|
: _changePosition,
|
|
|
|
|
),
|
|
|
|
|
TextButton(
|
|
|
|
|
child: const Text('修改旋转角度'),
|
|
|
|
|
onPressed: (selectedMarkerId == null)
|
|
|
|
|
? null
|
|
|
|
|
: _changeRotation,
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|