네이티브 라이브러리를 사용한 것이 아닌 Javascript 라이브러리를 이용하여 제작한 플러그인 입니다.
web 에서는 WebView 대신 iframe 으로 지도를 그립니다. 별도 설정 없이 flutter run -d chrome 으로 실행되지만, 카카오 콘솔에 사이트 도메인을 등록해야 지도가 표시됩니다.
카카오 JavaScript API 자체에 없는 기능이라 이 플러그인으로도 제공할 수 없습니다.
1.0.0 은 첫 안정 버전입니다. 제거된 API 는 없습니다. 시그니처는 모두 그대로이고, 아래 항목만 동작이 달라졌으므로 해당 코드가 있는지 확인하세요.
-
기본 지도 생성
Scaffold(
body: KakaoMap(),
);
-
맵 생성 callback
Scaffold(
body: KakaoMap(
onMapCreated: ((controller) {
mapController = controller;
}),
),
);
-
마커 생성 - 지도가 생성되면 마커 추가되는 예제
Set<Marker> markers = {};
Scaffold(
body: KakaoMap(
onMapCreated: ((controller) async {
mapController = controller;
markers.add(Marker(
markerId: UniqueKey().toString(),
latLng: await mapController.getCenter(),
));
setState(() { });
}),
markers: markers.toList(),
center: LatLng(37.3608681, 126.9306506),
),
);
-
마커 클러스터 생성 - 지도가 생성되면 마커 추가되는 예제 (마커와 클러스터 함께 사용하지 마세요. 클러스터 안에 마커를 넣어서 사용하세요.)
Clusterer? clusterer;
Scaffold(
body: KakaoMap(
onMapCreated: ((controller) async {
mapController = controller;
Set<Marker> markers = {};
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.27943075229118, 127.01763998406159)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.55915668706214, 126.92536526611102)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.13854258261161, 129.1014781294671)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.55518388656961, 126.92926237742505)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.20618517638034, 129.07944301057026)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.561110808242056, 126.9831268386891)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.86187129655063, 127.7410250820423)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.47160156778542, 126.62818064142286)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.10233410927457, 129.02611815856181)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.10215562270429, 129.02579793018205)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.475423012251106, 128.76666923366042)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.93282824693927, 126.95307628834287)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.33884892276137, 127.393666019664)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.520412849636, 126.9742764161581)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.155139675209675, 129.06154773758374)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.816041994696576, 127.11046706211324)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(38.20441110638504, 128.59038671285234)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.586112739308916, 127.02949148517999)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.50380641844987, 127.02130716617751)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.55155704387368, 126.92161115892036)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.55413060051369, 126.92207472929526)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.362321615174835, 127.35000483225389)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.55227862908755, 126.92280546294998)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.490413948014606, 127.02079678472444)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.172358507549596, 126.90545394866643)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.15474103200252, 129.11827889154455)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.516081250973485, 127.02369057166361)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.80711722863776, 127.14020346037576)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.28957415752673, 127.00103752005424)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.83953896766896, 128.7566880321854)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.51027412948879, 127.08227718124704)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.493581783270294, 126.72541955660554)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.135291862962795, 129.10060911448775)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.174574933144065, 126.91389980787773)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.795887691878654, 127.10660416587146)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.59288687521181, 126.96560524627377)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.45076411130452, 127.14593003749792)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.86008337557079, 127.1263912488061)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.23773491330953, 129.08371037429578)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.524297321304886, 127.05018281937049)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.33386658021849, 127.4461721466889)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.72963747546802, 128.27079056365005)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.02726828142973, 129.37257233594056)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.0708030360945, 129.0593185494088)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.86835862950247, 128.59755089175871)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(33.51133264696746, 126.51852347452322)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.61284289586752, 127.03120547238589)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.851696038722466, 128.59092937125666)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.59084695083232, 127.01872773588882)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.52114874288784, 129.33573629945764)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.362326407439845, 127.33577420148076)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.28941189110747, 127.00446132665141)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.32049801117398, 129.1810343576788)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.53338631541601, 127.00615481678061)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.413461468258156, 126.67735680840826)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.920390371093205, 128.54411720249956)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.65489374054824, 127.48374816871991)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.49491987110441, 127.01493134206048)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.64985695608336, 127.14496345268074)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.55686770317417, 127.16927880543041)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.37014007589146, 127.10614330185591)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.5350236507627, 126.96157681184789)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.40549630594667, 126.8980581820004)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(34.867950544005744, 128.69069690081176)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.16317059543225, 128.98452978748048)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.607484825953186, 127.48520451195111)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.651724785213986, 126.58306748337554)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.86059690063427, 128.59193087665244)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.25685847585025, 128.59912605060455)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(33.509258155694496, 126.5109451464813)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.64366155701157, 126.63255039247507)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.82667262227336, 127.1030670574823)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.82003554991111, 127.14810974062483)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.097485195649455, 128.99486181862338)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.32204249590605, 127.95591893585816)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.50535127272031, 127.1047465440526)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.99081407156533, 127.09338324956647)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.323486640444834, 127.12285239871076)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.78973089440451, 127.13644319545601)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.641373953578196, 129.35463220719618)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.47423127310911, 126.97625029161996)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.84357192991226, 128.61143720719716)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.180974984085736, 128.20294526341132)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.57895718642583, 126.9316897337244)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(33.49077253755052, 126.49314817000993)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.42175925330255, 128.67409133225766)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.46405540570109, 126.7153544119173)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.594758776232126, 127.10099917489818)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.7239966558994, 127.0478671731854)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.86680171505329, 128.5923738376741)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.560573727266785, 126.81239107485251)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.78692224857484, 126.98966010341789)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.10368644802913, 129.0206862606022)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.063839948992644, 127.06856523030079)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.34344643728643, 127.94382181350932)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.512521267219064, 127.40054805648133)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.15286653837983, 126.90419903971498)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.173238445546296, 129.176082844468)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.082394201323524, 129.40330471725923)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.51043665598106, 127.03974070036524)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.627816673285054, 127.44969866021904)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.59194624756919, 127.01817545576053)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.387147045560866, 127.1253365438929)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.89948383848115, 128.60809550730653)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.555316235235324, 127.14038447894715)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.09622092762977, 128.43314679004078)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.582855922985544, 126.91907857008522)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.516000983841586, 128.72798872032757)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.48429363675198, 127.0379630203579)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.54502575965604, 126.95429338245707)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.236247173046394, 128.8677618015292)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.40157536691968, 127.11717457214067)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.95191038001258, 127.91064040877527)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.491526492971346, 126.85463749525812)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(36.124356479753196, 128.09517052346138)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.15715169307048, 128.15853461363773)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.5808156608605, 126.95109705510639)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.46931787249714, 126.89904775044873)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.52195614910054, 129.3209904841746)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.58625703195563, 126.9496035206742)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.28463639199199, 126.85984474757359)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.534169458631226, 129.31169021536095)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.553341234194285, 127.15481222237025)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(37.62293367990081, 126.83445005122417)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.5272027005698, 127.72953798950101)));
markers.add(Marker(
markerId: '${markers.length + 1}',
latLng: LatLng(35.180032285898854, 128.06954509175367)));
clusterer = Clusterer(
markers: markers.toList(),
minLevel: 6,
gridSize: 45,
calculator: [30, 60],
texts: ['적음', '보통', '많음'],
styles: [
ClustererStyle(
width: 50,
height: 50,
background: Colors.blue.withOpacity(0.8),
borderRadius: 25,
color: Colors.white,
textAlign: 'center',
lineHeight: 60,
),
ClustererStyle(
width: 50,
height: 50,
background: Colors.red.withOpacity(0.8),
borderRadius: 25,
color: Colors.yellow,
textAlign: 'center',
lineHeight: 60,
),
ClustererStyle(
width: 50,
height: 50,
background: Colors.purple.withOpacity(0.8),
borderRadius: 25,
color: Colors.white,
textAlign: 'center',
lineHeight: 60,
),
],
);
setState(() { });
}),
clusterer: clusterer,
center: LatLng(37.3608681, 126.9306506),
),
);
-
Circle, Polyline, Polygon, Rectangle 예제
Set<Circle> circles = {};
Set<Polyline> polylines = {};
Set<Polygon> polygons = {};
Set<Rectangle> rectangles = {};
Scaffold(
appBar: AppBar(
title: Text(widget.title ?? selectedTitle),
),
body: KakaoMap(
onMapCreated: ((controller) async {
mapController = controller;
circles.add(
Circle(
circleId: circles.length.toString(),
center: LatLng(33.450701, 126.570667),
strokeWidth: 5,
strokeColor: Colors.red,
strokeOpacity: 0.5,
strokeStyle: StrokeStyle.longDashDotDot,
fillColor: Colors.black,
fillOpacity: 0.7,
radius: 50,
),
);
polylines.add(
Polyline(
polylineId: 'polyline_${polylines.length}',
points: [
LatLng(33.452344169439975, 126.56878163224233),
LatLng(33.452739313807456, 126.5709308145358),
LatLng(33.45178067090639, 126.5726886938753)
],
strokeColor: Colors.purple,
),
);
polygons.add(
Polygon(
polygonId: 'polygon_${polygons.length}',
points: [
LatLng(33.45133510810506, 126.57159381623066),
LatLng(33.44955812811862, 126.5713551811832),
LatLng(33.449986291544086, 126.57263296172184),
LatLng(33.450682513554554, 126.57321034054742),
LatLng(33.451346760004206, 126.57235740081413)
],
strokeWidth: 4,
strokeColor: Colors.blue,
strokeOpacity: 1,
strokeStyle: StrokeStyle.shortDashDot,
fillColor: Colors.black,
fillOpacity: 0.3,
),
);
rectangles.add(
Rectangle(
rectangleId: 'rectangle_${rectangles.length}',
rectangleBounds: LatLngBounds(
LatLng(33.42133510810506, 126.53159381623066),
LatLng(33.44955812811862, 126.5713551811832),
),
strokeWidth: 6,
strokeColor: Colors.blue,
strokeOpacity: 1,
strokeStyle: StrokeStyle.dot,
fillColor: Colors.black,
fillOpacity: 0.7,
),
);
setState(() {});
}),
circles: circles.toList(),
polylines: polylines.toList(),
polygons: polygons.toList(),
rectangles: rectangles.toList(),
center: LatLng(33.450701, 126.570667),
),
);
-
불러올 확장 라이브러리 선택 - 기본값은 전체(services, clusterer, drawing)입니다. 쓰지 않는 라이브러리를 빼면 지도 생성이 조금 빨라집니다.
AuthRepository.initialize(
appKey: 'YOUR_JAVASCRIPT_KEY',
libraries: {KakaoMapLibrary.services},
);
KakaoMap(
libraries: const {KakaoMapLibrary.services, KakaoMapLibrary.drawing},
);
-
로드뷰 생성 - onRoadviewCreated 로 받은 KakaoRoadviewController 로 파노라마 이동과 시점을 제어합니다.
KakaoRoadviewController? roadviewController;
Scaffold(
body: KakaoRoadMap(
center: LatLng(33.450701, 126.570667),
radius: 50,
viewpoint: const Viewpoint(pan: 90, tilt: 0, zoom: 0),
markers: [
Marker(
markerId: 'm1',
latLng: LatLng(33.450701, 126.570667),
altitude: 5,
range: 100,
),
],
onRoadviewCreated: (controller) => roadviewController = controller,
onViewpointChange: (viewpoint) => print('pan ${viewpoint.pan}'),
onRoadviewNotFound: (latLng) => print('이 지점에는 로드뷰가 없습니다.'),
),
);
await roadviewController?.setPanoIdNear(LatLng(37.566826, 126.9786567));
await roadviewController?.setViewpoint(const Viewpoint(pan: 180, tilt: 0, zoom: 1));
-
지도와 로드뷰 함께 쓰기 - 한 화면에서 지도 클릭으로 로드뷰를 옮기고, 지도 위 동동이(MapWalker)가 로드뷰 시점 방향을 따라갑니다.
KakaoMapRoadviewController? linkController;
Scaffold(
body: KakaoMapRoadviewView(
center: LatLng(33.450701, 126.570667),
initialViewMode: RoadviewViewMode.split,
splitRatio: 50,
showRoadviewOverlay: true,
useMapWalker: true,
onCreated: (controller) => linkController = controller,
),
);
await linkController?.toggleRoadview(LatLng(33.450701, 126.570667));
await linkController?.setViewMode(RoadviewViewMode.roadview);
-
Drawing Library - 사용자가 지도 위에 마커·선·다각형·원 등을 직접 그리고, 그린 결과를 데이터로 가져옵니다.
late KakaoMapController mapController;
Scaffold(
body: KakaoMap(
onMapCreated: ((controller) async {
mapController = controller;
await mapController.createDrawingManager(
options: const DrawingOptions(
drawingMode: [
DrawingOverlayType.marker,
DrawingOverlayType.polyline,
DrawingOverlayType.polygon,
],
polylineStyle: DrawingStyle(strokeColor: Colors.blue, strokeWidth: 3),
),
);
await mapController.showDrawingToolbox();
await mapController.selectDrawingMode(DrawingOverlayType.polyline);
}),
onDrawingEnd: (type) async {
final data = await mapController.getDrawingData();
for (final line in data.polylines) {
print('선 좌표 ${line.points.length}개');
}
},
),
);
await mapController.undoDrawing();
await mapController.redoDrawing();
await mapController.cancelDrawing();
-
커스텀 타일셋 - 직접 만든 타일 이미지를 기본 지도로 쓰거나 기존 지도 위에 겹칩니다.
await mapController.addTileset(const Tileset(
id: 'MY_TILES',
urlTemplate: 'https://tiles.example.com/{z}/{y}/{x}.png',
copyright: [TilesetCopyright('© Example')],
));
await mapController.setTileset('MY_TILES');
await mapController.setMapTypeId(MapType.normal);
await mapController.addTileset(const Tileset(
id: 'TILE_NUMBER',
tileFunction: '''
function (x, y, z) {
var div = document.createElement('div');
div.innerHTML = x + ', ' + y + ', ' + z;
div.style.border = '1px dashed #ff5050';
return div;
}
''',
));
await mapController.addOverlayTileset('TILE_NUMBER');
await mapController.removeOverlayTileset('TILE_NUMBER');
urlFunction / tileFunction 은 WebView 안에서 그대로 실행되므로 앱이 직접 작성한 문자열만 넘기세요.
-
앱 느낌으로 만들기 - 인포윈도우 스타일, 테마, Flutter 컨트롤, 위젯 마커
카카오 SDK 가 직접 그리는 UI(인포윈도우, 줌/지도타입 컨트롤, 클러스터, 기본 마커)는 웹페이지 느낌이 납니다. 아래 기능으로 앱 디자인에 맞출 수 있습니다. 지정하지 않으면 기존 모양 그대로입니다.
Marker(
markerId: 'm1',
latLng: LatLng(37.5665, 126.9780),
infoWindowContent: '<b>서울시청</b><br>02-120',
infoWindowStyle: const InfoWindowStyle.material(),
);
KakaoMap(
theme: const KakaoMapTheme(
infoWindowStyle: InfoWindowStyle.material(),
backgroundColor: Color(0xFFEFF3F6),
fontFamily: 'Pretendard, sans-serif',
),
copyrightPosition: CopyrightPosition.bottomLeft,
);
Stack(children: [
KakaoMap(onMapCreated: (c) => setState(() => controller = c)),
if (controller != null) KakaoMapControls(controller: controller!, showMapType: true),
]);
KakaoDrawingToolbar(controller: controller!, modes: const [DrawingOverlayType.polyline, DrawingOverlayType.polygon]);
Marker(markerId: 'p', latLng: latLng, icon: MarkerIcon.pin(color: Colors.red), width: 28, height: 40, offsetX: 14, offsetY: 40);
final tag = await MarkerIcon.fromWidget(PriceTag('12,000원'), logicalSize: const Size(96, 44));
Marker(markerId: 't', latLng: latLng, icon: tag, width: 96, height: 44, offsetX: 48, offsetY: 44);
Clusterer(markers: markers, styles: [ClustererStyle.material(Colors.indigo, size: 48)]);
-
Flutter 위젯 오버레이 - 진짜 Flutter 위젯을 지도 좌표에 붙이기
KakaoMap(
widgetOverlays: [
KakaoMapWidgetOverlay(
id: 'cafe',
position: LatLng(37.5665, 126.9780),
anchor: Alignment.bottomCenter,
child: GestureDetector(
onTap: () => showModalBottomSheet(...),
child: Card(child: Padding(padding: EdgeInsets.all(8), child: Text('카페 · 4,500원'))),
),
),
],
)
지도를 움직이면 JS 가 픽셀 좌표를 보내 위젯이 따라옵니다(프레임당 1회). web 에서도 눌립니다. 수백 개 이상이면 CustomOverlay 를 쓰세요.
-
오버레이 이벤트와 길게 누르기
KakaoMap(
onPolylineTap: (id, latLng, level) {},
onCircleTap: (id, latLng, level) {},
onRectangleTap: (id, latLng, level) {},
onMapLongPress: (latLng) {},
)
-
마우스 hover - 마우스 포인터가 있는 환경(데스크톱 브라우저) 전용
터치 기기에서는 호출되지 않으므로 탭 콜백을 함께 처리하세요. 실행 환경은 await controller.supportsHover() 로 확인할 수 있습니다.
KakaoMap(
onMarkerMouseOver: (id, latLng, level) {},
onPolygonMouseOver: (id, latLng, level) {},
onMarkerTap: (id, latLng, level) {},
)
-
마커 옵션과 부분 갱신
Marker(
markerId: 'bus', latLng: latLng,
opacity: 0.6, clickable: false, title: '툴팁(web)', visible: true,
markerImageSrc: 'https://…/sprite.png', width: 36, height: 37,
spriteOrigin: Point(0, 46), spriteWidth: 36, spriteHeight: 691,
);
await controller.setMarkerPosition('bus', newLatLng);
await controller.setMarkerVisible('bus', false);
await controller.showInfoWindow('bus');
await controller.hideInfoWindow('bus');
-
검색 페이지 정보
final r = await controller.keywordSearch(KeywordSearchRequest(keyword: '카페', size: 15, page: 1));
if (r.pagination?.hasNextPage == true) {
final next = await controller.keywordSearch(KeywordSearchRequest(keyword: '카페', size: 15, page: 2));
}
-
카카오맵 앱으로 연결하기 (길찾기·장소·로드뷰) - URL 만 만들고 실행은 url_launcher 로
final uri = KakaoMapLinks.web.route(to: LatLng(37.5665, 126.9780), toName: '서울시청', mode: KakaoMapRouteMode.transit);
await launchUrl(uri, mode: LaunchMode.externalApplication);
KakaoMapLinks.app.route(to: LatLng(37.5665, 126.9780), mode: KakaoMapRouteMode.car);
-
정적 지도 - 움직이지 않는 지도 이미지가 필요할 때 (목록 썸네일, 공유 미리보기 등)
KakaoStaticMap(
center: LatLng(33.450701, 126.570667),
currentLevel: 3,
markers: [
Marker(markerId: 'm1', latLng: LatLng(33.450701, 126.570667), infoWindowContent: '카카오'),
],
)
-
카메라 제어와 측정
await mapController.jump(LatLng(37.5665, 126.9780), 5, animate: true, duration: const Duration(milliseconds: 400));
await mapController.panToBounds(LatLngBounds(LatLng(37.55, 126.96), LatLng(37.58, 127.0)), padding: 48);
await mapController.fitBounds(points, padding: 48);
await mapController.panBy(0, -150);
await mapController.setMinLevel(2);
await mapController.setMaxLevel(10);
final meters = await mapController.getPolylineLength('route');
final squareMeters = await mapController.getPolygonArea('area');
-
지도 생성 옵션과 이벤트
KakaoMap(
mapTypeId: MapType.skyView,
disableDoubleClickZoom: true,
onMapTypeChanged: (type) => print('지도 타입: $type'),
onLinkTap: (url) => launchUrl(url, mode: LaunchMode.externalApplication),
)
같은 코드가 브라우저에서 그대로 동작합니다. (Chrome, flutter run -d chrome)