프로젝트

Flutter Map으로 여행 반경 설정

TMJeti 2025. 4. 17. 16:57

 

UI를 띄우는것 까지는 문제없었는데 매번 반경을 설정하는데 있어 문제가 발생했다. 분명 줌 인, 줌 아웃을 해서 반경을 새로 설정했는데 매번 필터링에 실패하고 전체 장소들이 추천되어지는 것이었다.

FlutterMap(
                    mapController: _mapController,
                    options: MapOptions(
                      initialCenter: currentCenter,
                      initialZoom: 13,
                      onPositionChanged: (position, _) {
                        setState(() {
                          currentCenter = position.center!;
                        });
                      },
                    ),
                    children: [
                      TileLayer(
                        urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                        userAgentPackageName: 'com.example.travelapp',
                      ),
                    ],
                  ),
                 
                  // 💙 지도 가운데 고정된 파란 원
                  Container(
                    width: 200, // 지름 (pixel 기준) – 필요 시 조절
                    height: 200,
                    decoration: BoxDecoration(
                      color: Colors.blue.withOpacity(0.3),
                      shape: BoxShape.circle,
                      border: Border.all(color: Colors.blueAccent, width: 2),
                    ),
                  ),

 

그렇다. 이 지도는 줌 인, 줌 아웃을 할 수는 있지만 실제 설정된 반경은 전혀 변하지 않았던 것이다 (...)

단순히 200px 원을 지도 중심에 올리는 것일 뿐이다.

 

근데 난 줌 레벨도 고려하여 반경을 설정하고 싶다!

FlutterMap에서 distance → 화면상 픽셀 길이로 변환하는 계산을 직접 해줘야한다.
즉, 줌(zoom) 레벨과 위도(latitude)를 이용해서 반지름(px)을 구해야 한다.

 

줌에 따라 px/미터 계산

double metersPerPixel(double zoom, double latitude){
    return 156543.03392 * cos(latitude * pi / 180) / pow(2, zoom);
  }
//  지도의 줌 레벨에 따른 픽셀 당 미터 수 계산
  double getActualRadiusKm({
    required double zoom,
    required double latitude,
    required double circleVisualDiameterPx,
  }) {
    final meterPerPixel = metersPerPixel(zoom, latitude);
    final radiusInMeters = (circleVisualDiameterPx / 2) * meterPerPixel;
    return radiusInMeters / 1000;
  }
FlutterMap(
                    mapController: _mapController,
                    options: MapOptions(
                      initialCenter: currentCenter,
                      initialZoom: currentZoom,
                      onPositionChanged: (position, hasGesture) {
                        setState(() {
                          currentCenter = position.center!;
                          currentZoom = position.zoom!;
                        });
                      },
                    ),
                    children: [
                      TileLayer(
                        urlTemplate:
                            'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                        userAgentPackageName: 'com.example.travelapp',
                      ),
                    ],
                  ),
                  // 고정된 크기의 파란 원
                  Container(
                    width: visualCircleSizePx,
                    height: visualCircleSizePx,
                    decoration: BoxDecoration(
                      color: Colors.blue.withOpacity(0.3),
                      shape: BoxShape.circle,
                      border: Border.all(color: Colors.blueAccent, width: 2),
                    ),
                  ),

 

visualCircleSizePx 은 실제 나오는 파란원의 크기이다. 필자는 160px 로 설정해놨다.

 

실제로 실행해보면

 

잘 된다 ^o^ 은행동에 있는 으능정이문화의거리 까지만 잘 가져왔다.

이제 가운데 파란색 원은 고정이고, 사용자가 지도를 움직여 원안에 맞추면 반경을 가져올수 있다.

 

필터링 기능이 모쪼록 잘 해결되어서 다행이다. 이제 관건은 이 부분이다.

 

반경을 너무 좁게 설정해버리면 장소 추천해주는 기능에 장소가 몇 개 없어 보다시피 볼거 없는(...) 코스를 추천해주는 한계가 생긴다. 사용자에게 반경을 설정하게 하는것이 아니라 어차피 그 지역에 가고싶다면 가고 싶은 장소 하나쯤은 있을테니 그 장소 주위 20km 이내에 있는 장소들을 뽑아와서 추천해주는 것도 나쁘지 않겠다.