2828public class MyTripToCanada extends VerticalLayout {
2929 public static final String MAP_API_KEY = "rNGhTaIpQWWH7C6QGKzF" ;
3030 private static final Logger log = LoggerFactory .getLogger (MyTripToCanada .class );
31+
3132 // Journey coordinates
3233 private final JLLatLng SARI = new JLLatLng (36.5633 , 53.0601 );
3334 private final JLLatLng TEHRAN = new JLLatLng (35.6892 , 51.3890 );
3435 private final JLLatLng DOHA = new JLLatLng (25.2854 , 51.5310 );
3536 private final JLLatLng MONTREAL = new JLLatLng (45.5017 , -73.5673 );
3637 private final JLLatLng CALGARY = new JLLatLng (51.0447 , -114.0719 );
38+
39+ // Custom icons for different stages of the journey
40+ private final JLIcon CAR_ICON = JLIcon .builder ()
41+ .iconUrl ("https://cdn-icons-png.flaticon.com/512/3097/3097220.png" )
42+ .iconSize (new JLPoint (64 , 64 ))
43+ .iconAnchor (new JLPoint (24 , 24 ))
44+ .build ();
45+
46+ private final JLIcon AIRPLANE_ICON = JLIcon .builder ()
47+ .iconUrl ("https://cdn-icons-png.flaticon.com/512/3182/3182857.png" )
48+ .iconSize (new JLPoint (64 , 64 ))
49+ .shadowAnchor (new JLPoint (26 , 26 ))
50+ .iconAnchor (new JLPoint (24 , 24 ))
51+ .build ();
52+ private final JLIcon EAST_AIRPLANE_ICON = JLIcon .builder ()
53+ .iconUrl ("https://cdn-icons-png.flaticon.com/512/1058/1058318.png" )
54+ .iconSize (new JLPoint (64 , 64 ))
55+ .shadowAnchor (new JLPoint (26 , 26 ))
56+ .iconAnchor (new JLPoint (24 , 24 ))
57+ .build ();
58+
59+ private final JLIcon RED_AIRPLANE_ICON = JLIcon .builder ()
60+ .iconUrl ("https://cdn-icons-png.flaticon.com/512/1077/1077903.png" )
61+ .iconSize (new JLPoint (64 , 64 ))
62+ .iconAnchor (new JLPoint (24 , 24 ))
63+ .build ();
64+
65+ private final JLIcon BRIEFCASE_ICON = JLIcon .builder ()
66+ .iconUrl ("https://cdn-icons-png.flaticon.com/512/5376/5376980.png" )
67+ .iconSize (new JLPoint (64 , 64 ))
68+ .iconAnchor (new JLPoint (24 , 24 ))
69+ .build ();
70+
71+ private final JLIcon DOCUMENT_ICON = JLIcon .builder ()
72+ .iconUrl ("https://cdn-icons-png.flaticon.com/512/3127/3127363.png" )
73+ .iconSize (new JLPoint (64 , 64 ))
74+ .iconAnchor (new JLPoint (24 , 24 ))
75+ .build ();
76+ private final JLIcon PASSPORT_ICON = JLIcon .builder ()
77+ .iconUrl ("https://cdn-icons-png.flaticon.com/512/18132/18132911.png" )
78+ .iconSize (new JLPoint (64 , 64 ))
79+ .iconAnchor (new JLPoint (24 , 24 ))
80+ .build ();
81+
82+ private final JLIcon HOUSE_ICON = JLIcon .builder ()
83+ .iconUrl ("https://cdn-icons-png.flaticon.com/512/3750/3750400.png" )
84+ .iconSize (new JLPoint (64 , 64 ))
85+ .iconAnchor (new JLPoint (24 , 48 ))
86+ .build ();
87+
3788 private JLMapView mapView ;
3889 private JLMarker currentMarker ;
3990 private JLPolyline currentPath ;
@@ -46,7 +97,7 @@ public MyTripToCanada() {
4697
4798 // Create the map view
4899 mapView = JLMapView .builder ()
49- .jlMapProvider (JLMapProvider .OSM_FRENCH
100+ .jlMapProvider (JLMapProvider .WATER_COLOR
50101 .parameter (new JLMapOption .Parameter ("key" , MAP_API_KEY ))
51102 .parameter (new JLMapOption .Parameter ("initialZoom" , "4" ))
52103 .build ())
@@ -89,52 +140,52 @@ private void startJourney() {
89140 animateSegment (
90141 SARI ,
91142 TEHRAN ,
92- "🚗" ,
143+ CAR_ICON ,
93144 "#FF5722" ,
94- 5000 ,
145+ 3000 ,
95146 7 ,
96147 () -> {
97148 // Step 2: Briefcase and passport (1 second)
98149 Notification .show ("Arriving in Tehran - Getting ready to fly..." , 2000 , Notification .Position .BOTTOM_CENTER );
99- showTransition (TEHRAN , "💼" , 1000 , () -> {
150+ showTransition (TEHRAN , BRIEFCASE_ICON , 1500 , () -> {
100151 // Step 3: Airplane Tehran to Doha (3 seconds)
101152 Notification .show ("Flying to Doha..." , 2000 , Notification .Position .BOTTOM_CENTER );
102153 animateSegment (
103154 TEHRAN ,
104155 DOHA ,
105- "✈️" ,
156+ AIRPLANE_ICON ,
106157 "#2196F3" ,
107- 3000 ,
158+ 4000 ,
108159 5 ,
109160 () -> {
110161 // Step 4: Change airplane animation (same position)
111162 Notification .show ("Transit in Doha..." , 2000 , Notification .Position .BOTTOM_CENTER );
112- showTransition (DOHA , "🛫" , 1000 , () -> {
163+ showTransition (DOHA , PASSPORT_ICON , 1500 , () -> {
113164 // Step 5: Airplane Doha to Montreal (5 seconds)
114165 Notification .show ("Flying to Montreal, Canada..." , 2000 , Notification .Position .BOTTOM_CENTER );
115166 animateSegment (
116167 DOHA ,
117168 MONTREAL ,
118- "✈️" ,
169+ EAST_AIRPLANE_ICON ,
119170 "#2196F3" ,
120171 5000 ,
121172 3 ,
122173 () -> {
123174 // Step 6: Paper document (1 second)
124175 Notification .show ("Customs in Montreal..." , 2000 , Notification .Position .BOTTOM_CENTER );
125- showTransition (MONTREAL , "📄" , 1000 , () -> {
176+ showTransition (MONTREAL , DOCUMENT_ICON , 1500 , () -> {
126177 // Step 7: Red airplane Montreal to Calgary (4 seconds)
127178 Notification .show ("Domestic flight to Calgary..." , 2000 , Notification .Position .BOTTOM_CENTER );
128179 animateSegment (
129180 MONTREAL ,
130181 CALGARY ,
131- "🛩️" ,
182+ RED_AIRPLANE_ICON ,
132183 "#E91E63" ,
133184 4000 ,
134185 6 ,
135186 () -> {
136187 // Step 8: House at Calgary
137- showTransition (CALGARY , "🏠" , 2000 , () ->
188+ showTransition (CALGARY , HOUSE_ICON , 2000 , () ->
138189 Notification .show ("🎉 Welcome to Calgary, Canada! Journey Complete!" ,
139190 5000 ,
140191 Notification .Position .TOP_CENTER )
@@ -152,18 +203,18 @@ private void startJourney() {
152203 );
153204 }
154205
155- private void animateSegment (JLLatLng start , JLLatLng end , String emoji , String pathColor ,
206+ private void animateSegment (JLLatLng start , JLLatLng end , JLIcon icon , String pathColor ,
156207 int duration , int zoomLevel , Runnable onComplete ) {
157- log .info ("Animating segment from {} to {} with emoji {}" , start , end , emoji );
208+ log .info ("Animating segment from {} to {} with icon {}" , start , end , icon );
158209
159210 // Remove previous path if exists
160211 if (currentPath != null ) {
161212 log .info ("Removing previous path" );
162213 currentPath .remove ();
163214 }
164215
165- // Create animated path with fewer points for smoother animation
166- JLLatLng [] pathPoints = createCurvedPath (start , end , 30 );
216+ // Create animated path with more points for smoother animation (10x more)
217+ JLLatLng [] pathPoints = createCurvedPath (start , end , 300 );
167218 log .info ("Created path with {} points" , pathPoints .length );
168219
169220 currentPath = mapView .getVectorLayer ().addPolyline (
@@ -189,23 +240,26 @@ private void animateSegment(JLLatLng start, JLLatLng end, String emoji, String p
189240
190241 // Animate marker along path
191242 log .info ("Starting marker animation" );
192- animateMarkerAlongPath (emoji , pathPoints , duration , onComplete );
243+ UI .getCurrent ().push ();
244+ animateMarkerAlongPath (icon , pathPoints , duration , onComplete );
193245 }
194246
195- private void animateMarkerAlongPath (String emoji , JLLatLng [] path , int duration , Runnable onComplete ) {
247+ private void animateMarkerAlongPath (JLIcon icon , JLLatLng [] path , int duration , Runnable onComplete ) {
196248 UI ui = UI .getCurrent ();
197249
198- // Reduce to reasonable number of animation steps (20 steps max )
199- int totalSteps = Math .min (20 , path .length );
250+ // Increase animation steps to 200 for smoother animation (10x more than before )
251+ int totalSteps = Math .min (200 , path .length );
200252 int delayPerStep = duration / totalSteps ;
201253
202- log .info ("Animating marker with emoji {} along {} steps, delay per step: {}ms" , emoji , totalSteps , delayPerStep );
254+ log .info ("Animating marker with icon {} along {} steps, delay per step: {}ms" , icon , totalSteps , delayPerStep );
203255
204256 // Create the marker once at starting position
205257 if (currentMarker == null ) {
206258 currentMarker = mapView .getUiLayer ().addMarker (path [0 ], null , false );
259+ setMarkerIconDirect (currentMarker , icon );
207260 } else {
208261 currentMarker .setLatLng (path [0 ]);
262+ setMarkerIconDirect (currentMarker , icon );
209263 }
210264
211265 ScheduledExecutorService executor = Executors .newSingleThreadScheduledExecutor ();
@@ -240,16 +294,18 @@ private void animateMarkerAlongPath(String emoji, JLLatLng[] path, int duration,
240294 }, 0 , delayPerStep , TimeUnit .MILLISECONDS );
241295 }
242296
243- private void showTransition (JLLatLng position , String emoji , int duration , Runnable onComplete ) {
297+ private void showTransition (JLLatLng position , JLIcon icon , int duration , Runnable onComplete ) {
244298 UI ui = UI .getCurrent ();
245299
246- log .info ("Showing transition at {} with emoji {}" , position , emoji );
300+ log .info ("Showing transition at {} with icon {}" , position , icon );
247301
248- // Just update the marker position and text , don't remove
302+ // Just update the marker position and icon , don't remove
249303 if (currentMarker == null ) {
250- currentMarker = mapView .getUiLayer ().addMarker (position , emoji , false );
304+ currentMarker = mapView .getUiLayer ().addMarker (position , null , false );
305+ setMarkerIconDirect (currentMarker , icon );
251306 } else {
252307 currentMarker .setLatLng (position );
308+ setMarkerIconDirect (currentMarker , icon );
253309 }
254310
255311 ScheduledExecutorService executor = Executors .newSingleThreadScheduledExecutor ();
@@ -303,4 +359,29 @@ private void resetJourney() {
303359 // Reset view to starting position
304360 mapView .getControlLayer ().flyTo (SARI , 4 );
305361 }
362+
363+ /**
364+ * Helper method to set marker icon using direct JavaScript execution
365+ * This bypasses the toString() issue with JLIcon parameter serialization
366+ */
367+ private void setMarkerIconDirect (JLMarker marker , JLIcon icon ) {
368+ String iconScript = String .format ("""
369+ var icon = L.icon({
370+ iconUrl: '%s',
371+ iconSize: [%d, %d],
372+ iconAnchor: [%d, %d]
373+ });
374+ this.%s.setIcon(icon);
375+ """ ,
376+ icon .getIconUrl (),
377+ (int ) icon .getIconSize ().getX (),
378+ (int ) icon .getIconSize ().getY (),
379+ (int ) icon .getIconAnchor ().getX (),
380+ (int ) icon .getIconAnchor ().getY (),
381+ marker .getJLId ()
382+ );
383+
384+ mapView .getElement ().executeJs (iconScript );
385+ log .debug ("Set icon for marker {} using direct JS" , marker .getJLId ());
386+ }
306387}
0 commit comments