Flutter 지도에서 애니메이션 및 대화형 사용자 지정 지도 마커를 추가하는 방법
이 블로그에서는 마커를 추가하고 애니메이션하는 방법을 설명하겠습니다. Flutter Maps 위젯을 처음 사용하는 경우 진행하기 전에 다음 블로그 게시물을 참조하세요.
Introducing Flutter Maps Widget [블로그]
[블로그]
로드 시간에 애니메이션 마커 추가
로드 시 애니메이션 마커를 추가하려면 애니메이션 위젯을 MapMarker의 자식으로 추가하고 initState에서 애니메이션을 시작해야 합니다.
다음 예에서는 로드 시간에 네 번째 인덱스 마커를 애니메이션했습니다.
class _LoadAnimatableMarkerAtLoadtime extends StatefulWidget {
@override
_LoadAnimatableMarkerAtLoadtimeState createState() =>
_LoadAnimatableMarkerAtLoadtimeState();
}
class _LoadAnimatableMarkerAtLoadtimeState
extends State<_LoadAnimatableMarkerAtLoadtime>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late CurvedAnimation _animation;
late Map<String, MapLatLng> _markers;
int _selectedMarkerIndex = 4;
@override
void initState() {
_controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 750));
_animation =
CurvedAnimation(parent: _controller, curve: Curves.easeOutBack);
_markers = <String, MapLatLng>{
'Chad': MapLatLng(15.454166, 18.732206),
'Nigeria': MapLatLng(9.081999, 8.675277),
'DRC': MapLatLng(-4.038333, 21.758663),
'CAR': MapLatLng(6.600281, 20.480205),
'Sudan': MapLatLng(12.862807, 30.217636),
'Kenya': MapLatLng(0.0236, 37.9062),
'Zambia': MapLatLng(-10.974129, 30.861397),
'Egypt': MapLatLng(25.174109, 28.776359),
'Algeria': MapLatLng(24.276672, 7.308186),
};
_controller.repeat(min: 0.15, max: 1.0, reverse: true);
super.initState();
}
@override
void dispose() {
_controller.stop();
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Load animatable marker at loadtime'),
),
body: MapTileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
initialZoomLevel: 3,
initialFocalLatLng: MapLatLng(2.3104, 16.5581),
initialMarkersCount: _markers.length,
markerBuilder: (BuildContext context, int index) {
final double size = _selectedMarkerIndex == index ? 40 : 25;
final MapLatLng markerData = _markers.values.elementAt(index);
final Icon current = Icon(Icons.location_pin, size: size);
return MapMarker(
latitude: markerData.latitude,
longitude: markerData.longitude,
child: Transform.translate(
offset: Offset(0.0, -size / 2),
child: _selectedMarkerIndex == index
? ScaleTransition(
alignment: Alignment.bottomCenter,
scale: _animation,
child: current)
: current,
),
);
},
),
);
}
}
Flutter 맵의 초기 로드 중 애니메이션 마커 추가
프로그래밍 방식으로 마커 추가
마커를 동적으로 추가하거나 업데이트하려면 마커를 포함하기 위해 MapShapeLayerController 또는 MapTileLayerController을 사용하는지 여부에 따라 MapShapeLayer 또는 MapTileLayer의 도움이 필요합니다. MapShapeLayerController 및 MapTileLayerController는 마커를 추가, 제거, 업데이트 및 지우는 방식으로 마커 컬렉션을 동적으로 제어합니다.
다음 예제에서는 insertMarker의 MapShapeLayerController 메서드를 사용하여 정확한 좌표에 마커를 동적으로 추가합니다. 여기서는 Icon 위젯을 마커로 사용합니다. MapShapeLayerControl의 insertMarker 메서드를 호출하면 해당 인덱스와 함께 TileLayer 의 markerBuilder 콜백이 트리거됩니다. 여기서 현재 인덱스에서 업데이트할 MapMarker을 반환해야 합니다.
class AddingMarkerDynamically extends StatefulWidget {
@override
_AddingMarkerDynamicallyState createState() =>
_AddingMarkerDynamicallyState();
}
class _AddingMarkerDynamicallyState extends State
with SingleTickerProviderStateMixin {
late MapTileLayerController _tileLayerController;
@override
void initState() {
_tileLayerController = MapTileLayerController();
super.initState();
}
@override
void dispose() {
_tileLayerController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add a marker dynamically'),
),
body: MapTileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
initialZoomLevel: 3,
initialFocalLatLng: MapLatLng(2.3104, 16.5581),
controller: _tileLayerController,
markerBuilder: (BuildContext context, int index) {
return MapMarker(
latitude: 6.6111,
longitude: 20.9394,
child: Transform.translate(
offset: Offset(0.0, -20.0),
child: Icon(Icons.location_pin, size: 40),
),
);
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add_location),
onPressed: () => _tileLayerController.insertMarker(0),
),
);
}
}
Flutter 지도에서 애니메이션 마커를 동적으로 추가
마커 또는 마커 그룹을 동적으로 애니메이션화
동적 마커 업데이트에는 MapShapeLayerController 및 MapTileLayerController 의 도움이 필요합니다. 다음 예제는 MapMarker 의 자식을 애니메이션 위젯으로 동적으로 업데이트하여 애니메이션을 시작하는 방법을 보여줍니다.
동시에 각각의 마커 인덱스와 함께 호출updateMarkers하여 마커를 업데이트합니다.
class AnimateGroupOfMarkersDynamically extends StatefulWidget {
@override
_AnimateGroupOfMarkersDynamicallyState createState() =>
_AnimateGroupOfMarkersDynamicallyState();
}
class _AnimateGroupOfMarkersDynamicallyState
extends State
with TickerProviderStateMixin {
late AnimationController _controller;
late CurvedAnimation _animation;
late MapTileLayerController _tileLayerController;
late Map<String, MapLatLng> _markers;
List _selectedMarkerIndices = [];
@override
void initState() {
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 750),
reverseDuration: const Duration(milliseconds: 750));
_animation =
CurvedAnimation(parent: _controller, curve: Curves.easeOutBack);
_tileLayerController = MapTileLayerController();
_markers = <String, MapLatLng>{
'Chad': MapLatLng(15.454166, 18.732206),
'Nigeria': MapLatLng(9.081999, 8.675277),
'DRC': MapLatLng(-4.038333, 21.758663),
'CAR': MapLatLng(6.600281, 20.480205),
'Sudan': MapLatLng(12.862807, 30.217636),
'Kenya': MapLatLng(0.0236, 37.9062),
'Zambia': MapLatLng(-10.974129, 30.861397),
'Egypt': MapLatLng(25.174109, 28.776359),
'Algeria': MapLatLng(24.276672, 7.308186),
};
_controller.repeat(min: 0.1, max: 1.0, reverse: true);
super.initState();
}
@override
void dispose() {
_controller.stop();
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Animate group of markers dynamically')),
body: MapTileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
initialZoomLevel: 3,
initialFocalLatLng: MapLatLng(2.3104, 16.5581),
controller: _tileLayerController,
initialMarkersCount: _markers.length,
markerBuilder: (BuildContext context, int index) {
final double size = _selectedMarkerIndices.contains(index) ? 40 : 25;
final MapLatLng markerLatLng = _markers.values.elementAt(index);
Widget current = Icon(Icons.location_pin, size: size);
return MapMarker(
latitude: markerLatLng.latitude,
longitude: markerLatLng.longitude,
child: Transform.translate(
offset: Offset(0.0, -size / 2),
child: _selectedMarkerIndices.contains(index)
? ScaleTransition(
alignment: Alignment.bottomCenter,
scale: _animation,
child: current)
: current,
),
);
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.animation),
onPressed: () {
_selectedMarkerIndices = [0, 2, 4];
_tileLayerController.updateMarkers(_selectedMarkerIndices);
_controller.repeat(min: 0.1, max: 1.0, reverse: true);
},
),
);
}
}
Futter 맵에서 동적으로 마커 애니메이션
상호 작용 시 마커 애니메이션
탭 또는 클릭 제스처에서 단일 마커를 애니메이션화할 마커 그룹이 있다고 가정합니다.
이를 위해 마커의 자식을 GestureDetector 안에 래핑하고 GestureDetector.onTap 콜백을 사용하여 탭 상호 작용을 처리해야 합니다. 탭할 때 마커 인덱스로 updateMarkers을 호출하여 애니메이션을 적용합니다.
다음 코드는 이를 보여줍니다.
int _selectedMarkerIndex = -1;
int _prevSelectedMarkerIndex = -1;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Animate a single marker dynamically'),
),
body: MapTileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
initialZoomLevel: 3,
initialFocalLatLng: MapLatLng(2.3104, 16.5581),
controller: _tileLayerController,
initialMarkersCount: _markers.length,
markerBuilder: (BuildContext context, int index) =>
_buildMarker(context, index),
),
);
}
MapMarker _buildMarker(BuildContext context, int index) {
final double size = _selectedMarkerIndex == index ? 40 : 25;
final MapLatLng markerLatLng = _markers.values.elementAt(index);
final Icon current = Icon(Icons.location_pin);
return MapMarker(
latitude: markerLatLng.latitude,
longitude: markerLatLng.longitude,
child: GestureDetector(
onTap: () {
_prevSelectedMarkerIndex = _selectedMarkerIndex;
_selectedMarkerIndex = index;
_tileLayerController.updateMarkers([
if (_prevSelectedMarkerIndex != -1) _prevSelectedMarkerIndex,
_selectedMarkerIndex
]);
},
child: AnimatedContainer(
transform: Matrix4.identity()..translate(0.0, -size / 2),
duration: const Duration(milliseconds: 250),
height: size,
width: size,
child: FittedBox(child: current),
),
),
);
}
Flutter 지도의 상호 작용에 대한 마커 애니메이션
자원
자세한 내용은 GitHub에서 이animating markers on Flutter Maps project를 참조하세요.
결론
이 블로그에서는 로드 시 동적으로 그리고 SyncfusionFlutter Maps 위젯의 상호 작용을 통해 단일 마커 및 마커 그룹에 애니메이션을 적용하는 방법을 배웠습니다. 사용해 보고 아래 댓글 섹션에 피드백을 남겨주세요.
user guide에서 Flutter Maps의 다른 기능을 확인하고 Flutter Maps project samples을 살펴보십시오. 또한 Android , iOS , web , Windows 및 Linux 과 같은 다양한 플랫폼에서 사용할 수 있는 데모 앱을 확인하십시오.
Flutter 프레임워크용 새 위젯이나 기존 위젯의 새 기능이 필요한 경우 support forums , Direct-Trac 또는 feedback portal 를 통해 문의할 수 있습니다. 언제나처럼 기꺼이 도와드리겠습니다!
이 블로그 게시물이 마음에 들면 다음 기사도 마음에 드실 것입니다.
[블로그]
[블로그]
[블로그]
Reference
이 문제에 관하여(Flutter 지도에서 애니메이션 및 대화형 사용자 지정 지도 마커를 추가하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/syncfusion/how-to-add-animated-and-interactive-custom-map-markers-in-flutter-maps-429p텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)