You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Map中Polyline在用户离开建筑时未消失的问题

问题修复:Flutter Map Polyline 未根据用户位置自动隐藏

核心问题分析

  • 位置状态检查仅在getUserPositionStream初始化时执行一次,用户位置更新后未重新判断是否在建筑范围内
  • WebSocket接收坐标后直接添加Polyline,未验证用户当前是否在目标建筑区域内
  • polylines列表更新逻辑不严谨,导致旧Polyline残留显示

具体修复步骤

1. 重构位置监听逻辑,实时检查用户位置状态

修改map_view_model.dart中的getUserPositionStream方法,将位置检查逻辑移至位置流的监听回调中,确保每次位置更新都执行判断:

getUserPositionStream() async {
  var locationOptions = const LocationSettings(accuracy: LocationAccuracy.high, distanceFilter: 0);
  Geolocator.getPositionStream(locationSettings: locationOptions).listen((Position position) {
    if (this.position != position) {
      this.position = position;
      accuracy = position.accuracy;
      _updateMarker();
      
      // 每次位置更新时检查是否在当前Polyline范围内
      _checkUserLocationInPolyline();
      
      createMapLayers();
      notifyListeners();
    }
  });

  // 初始化时发送一次位置请求建筑数据
  String latLonString = '${position!.longitude},${position!.latitude}';
  channel.sink.add(latLonString);
}

// 新增方法:检查用户是否在Polyline范围内并更新状态
void _checkUserLocationInPolyline() {
  if (polylineCoordinates.isEmpty) return;
  
  bool isInPolylines = MapUtil.containsLocation(
    LatLng(position!.latitude, position!.longitude), 
    polylineCoordinates, 
    false
  );
  
  if (!isInPolylines) {
    polylineCoordinates.clear();
    polylines.clear();
    notifyListeners();
    // 发送当前位置请求新的建筑Polyline
    String latLonString = '${position!.longitude},${position!.latitude}';
    channel.sink.add(latLonString);
  }
}

2. 修改WebSocket数据接收逻辑,添加位置验证

在map_view.dart的StreamBuilder中,接收坐标后先判断用户是否在该建筑范围内,再决定是否更新Polyline:

StreamBuilder(
  stream: viewModel.channel.stream,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      Map<String, dynamic> data = json.decode(snapshot.data);
      List<dynamic> coordinates = data['coordinates'][0];
      List<LatLng> newPolylineCoords = [];
      
      for (var coordinate in coordinates) {
        double longitude = coordinate[0];
        double latitude = coordinate[1];
        newPolylineCoords.add(LatLng(latitude, longitude));
      }
      
      // 检查当前用户是否在新接收的建筑范围内
      bool isInNewBuilding = MapUtil.containsLocation(
        LatLng(viewModel.position!.latitude, viewModel.position!.longitude), 
        newPolylineCoords, 
        false
      );
      
      if (isInNewBuilding) {
        viewModel.polylineCoordinates.clear();
        viewModel.polylineCoordinates.addAll(newPolylineCoords);
        viewModel.polylines.clear();
        viewModel._buildPolylines(viewModel.polylineCoordinates);
        viewModel.notifyListeners();
      } else {
        // 用户不在该建筑内,清空Polyline
        viewModel.polylineCoordinates.clear();
        viewModel.polylines.clear();
        viewModel.notifyListeners();
      }
      
      return const Align(
        alignment: Alignment.bottomCenter,
        child: Text('data Received',style: TextStyle(color: Colors.white,decoration: TextDecoration.none,fontSize: 10.0),)
      );
    } else if (snapshot.hasError) {
      return const Text('Error');
    } else {
      viewModel.polylineCoordinates.clear();
      viewModel.polylines.clear();
      return const Text('');
    }
  },
),

3. 优化_buildPolylines方法,避免重复添加

确保每次构建Polyline前先清空列表:

List<Polyline> _buildPolylines(List<LatLng> polylineCoordinates) {
  polylines.clear(); // 清空旧Polyline,避免重复添加
  if (polylineCoordinates.isEmpty) return polylines;
  
  Polyline polyline = Polyline(
    points: polylineCoordinates,
    color: Colors.yellow,
    strokeWidth: 2,
  );
  polylines.add(polyline);
  return polylines;
}

4. 修正createMapLayers中的Polyline层逻辑

只有当polylines不为空时才添加到图层:

createMapLayers() {
  mapLayers.clear();
  mapLayers.addAll([
    TileLayerOptions(
        urlTemplate: 'http://mt3.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
        subdomains: ['a', 'b', 'c'],
        maxZoom: 20
    ),
    MarkerLayerOptions(
        markers: [
          Marker(
              point: LatLng(position!.latitude, position!.longitude),
              builder: (context)=> RotationMarker(
                rotation: compassHeading,
                builder: (context)=> Stack(
                  children: [
                    const Icon(Icons.tornado_sharp,size: 30,color: Colors.lightBlue,),
                    Positioned(
                      top:10,left: 4.1,bottom:0,
                      child: Image.asset(
                        "assets/images/current_location_gif.gif",
                      ),
                    )
                  ],
                ),
                color: Colors.blue,
                size: 50.0,
              )
          ),

        ]
    ),
    PolygonLayerOptions(
      polygons: [
        Polygon(
          points: _createCirclePoints(LatLng(position!.latitude, position!.longitude), 0.001),
          color: Colors.blue.withOpacity(0.2),
          borderColor: Colors.transparent,
        ),
      ],
    ),
  ]);
  
  // 仅在有Polyline数据时添加图层
  if (polylines.isNotEmpty) {
    mapLayers.add(PolylineLayerOptions(polylines: polylines));
  }
}

内容的提问来源于stack exchange,提问作者Soumya Manthri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 09:15:03