android Flutter:如何使用Flutter_map包在Map上更平滑地移动标记

vngu2lb8  于 2022-11-20  发布在  Android
关注(0)|答案(2)|浏览(253)

我是一个初学者在Flutter和我目前正在建立一个Map应用程序,显示一个Map与当前用户的连续位置使用Flutter_map插件,我用标记来显示它。
它真的很好地与我和相机移动以及根据用户的位置,但问题是,标记实际上从当前位置跳到新的位置,我想使标记移动在平滑的方式从一个给定的latlon位置到另一个就像我们在谷歌Map用户位置标记。有可能更新它在Map上的动画吗?如果是的,谁能告诉我怎么做?
(我不想要Google Maps标记解决方案,因为我更喜欢使用Flutter_map并显示单张Map)
下面是我的一段代码:

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map/plugin_api.dart';
import 'package:geolocator/geolocator.dart';
import 'package:latlong2/latlong.dart' as latLng;
import 'package:car_speed_limit/Components/constants.dart';
import 'dart:async';

//ignore: must_be_immutable
class RoadMap extends StatefulWidget {

  var userLat;
  var userLong;
  var userSpeed;

  RoadMap({this.userLat, this.userLong, this.userSpeed});

  @override
  _RoadMapState createState() => _RoadMapState();
}

class _RoadMapState extends State<RoadMap> with SingleTickerProviderStateMixin{

  MapController? _mapController;
  StreamSubscription<Position>? positionStreamSub2;

  @override
  void initState() {
    super.initState();
    _mapController = MapController(); 
    positionStreamSub2= Geolocator.getPositionStream(
        intervalDuration: Duration(milliseconds: 1000),
        forceAndroidLocationManager: false,
        desiredAccuracy: LocationAccuracy.best).listen((_updatedPosition) {
      if (!mounted) {
        return;
      }
      setState(() {
        _mapController?.move(latLng.LatLng(widget.userLat, widget.userLong),16.8);
        widget.userLat= _updatedPosition.latitude; 
        widget.userLong= _updatedPosition.longitude;
        widget.userSpeed= (_updatedPosition.speed*(2.23693)).toInt(); 
      });
      print('THE ROAD STREAM $_updatedPosition');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('${widget.userSpeed}'),
          backgroundColor: Color(0xFF01051C),
          leading: IconButton(
              icon: Icon(
                Icons.arrow_back,
                color: kIconColor,
                size: 35,
              ),
              onPressed: () {
                Navigator.of(context).pop();
                positionStreamSub2?.cancel();
              }
          ),
          actions: [
            Column(
              children: [
                Text('Lat: ${widget.userLat}',
                    style: TextStyle(
                      color: kIconColor,
                    )),
                Text('Long: ${widget.userLong}',
                    style: TextStyle(
                      color: kIconColor,
                    )),
              ],
            ),
          ],
        ),
        body: FlutterMap(
            mapController: _mapController,
            options: MapOptions(
              minZoom: 2.6,
              maxZoom: 18.0,
              zoom: 17.0,
              center: latLng.LatLng(widget.userLat,widget.userLong),
              interactiveFlags: InteractiveFlag.pinchZoom | InteractiveFlag.drag | InteractiveFlag.pinchMove,
            ),
            layers: [
              TileLayerOptions(
                urlTemplate: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', 
                subdomains: ['a','b','c'],
              ),
              MarkerLayerOptions(
                markers: [
                  Marker(
                      point: latLng.LatLng(widget.userLat,widget.userLong),
                      builder: (context) {
                        return Stack(
                          children:[
                            Center(
                              child: Container(
                                height: 30,
                                width: 30,
                                decoration: BoxDecoration(
                                  shape: BoxShape.circle,
                                  color: Colors.tealAccent.withOpacity(0.5),
                                ),
                              ),
                            ),
                            Center(
                              child: Container(
                                height: 17,
                                width: 17,
                                decoration: BoxDecoration(
                                  shape: BoxShape.circle,
                                  color: Colors.tealAccent[700],
                                ),
                              ),
                            ),
                          ],
                        );
                      }
                  ),
                ],
              ),
            ]
        ),
    );
  }
}
ovfsdjhp

ovfsdjhp1#

我一直在寻找一种在移动Map控制器时添加一个漂亮动画的方法,并且发现这很简单--你只需要使用一个动画控制器调用'move'。flutter_map repo中有一个例子说明了如何做到这一点:
animated_map_controller.dart
一般的想法是不直接使用mapcontroller,而是使用动画控制器来控制它,该动画控制器对缩放和位置进行“补间”:

void _animatedMapMove(LatLng destLocation, double destZoom) {
    // Create some tweens. These serve to split up the transition from one location to another.
    // In our case, we want to split the transition be<tween> our current map center and the destination.
    final latTween = Tween<double>(
        begin: mapController.center.latitude, end: destLocation.latitude);
    final lngTween = Tween<double>(
        begin: mapController.center.longitude, end: destLocation.longitude);
    final zoomTween = Tween<double>(begin: mapController.zoom, end: destZoom);

    // Create a animation controller that has a duration and a TickerProvider.
    final controller = AnimationController(
        duration: const Duration(milliseconds: 500), vsync: this);
    // The animation determines what path the animation will take. You can try different Curves values, although I found
    // fastOutSlowIn to be my favorite.
    final Animation<double> animation =
        CurvedAnimation(parent: controller, curve: Curves.fastOutSlowIn);

    controller.addListener(() {
      mapController.move(
          LatLng(latTween.evaluate(animation), lngTween.evaluate(animation)),
          zoomTween.evaluate(animation));
    });

    animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        controller.dispose();
      } else if (status == AnimationStatus.dismissed) {
        controller.dispose();
      }
    });

    controller.forward();
  }

这不是我的代码,但我在我的项目中使用了类似的东西。记住你的小部件必须使用TickerProviderStateMixin。希望这能帮助别人!

eh57zj3b

eh57zj3b2#

这是非常有帮助的。另外,如果你使用多个mixin,你会希望使用〉〉TickerProviderStateMixin而不是SingleTickerProviderStateMixin。
干杯!

相关问题