leptos_leaflet/components/
circle.rs1use leaflet::CircleOptions;
2use leptos::prelude::*;
3
4use super::{
5 extend_context_with_overlay, FillRule, LayerEvents, LeafletMapContext, LineCap, LineJoin,
6 MouseEvents, MoveEvents, PopupEvents, Position, StringEmptyOption, TooltipEvents,
7};
8use crate::{
9 core::{JsSignal, JsStoredValue},
10 setup_layer_leaflet_option, setup_layer_leaflet_option_ref, setup_layer_leaflet_string,
11};
12
13#[component(transparent)]
18pub fn Circle(
19 #[prop(into)] center: JsSignal<Position>,
20 #[prop(into, optional)] stroke: Signal<Option<bool>>,
21 #[prop(into, optional)] color: Signal<String>,
22 #[prop(into, optional)] weight: Signal<Option<f64>>,
23 #[prop(into, optional)] interactive: Signal<Option<bool>>,
24 #[prop(into, optional)] opacity: Signal<Option<f64>>,
25 #[prop(into, optional)] line_cap: Signal<Option<LineCap>>,
26 #[prop(into, optional)] line_join: Signal<Option<LineJoin>>,
27 #[prop(into, optional)] dash_array: Signal<String>,
28 #[prop(into, optional)] dash_offset: Signal<String>,
29 #[prop(into, optional)] fill: Signal<Option<bool>>,
30 #[prop(into, optional)] fill_color: Signal<String>,
31 #[prop(into, optional)] fill_opacity: Signal<Option<f64>>,
32 #[prop(into, optional)] fill_rule: Signal<Option<FillRule>>,
33 #[prop(into, optional)] bubbling_mouse_events: Signal<Option<bool>>,
34 #[prop(into, optional)] class_name: Signal<String>,
35 #[prop(into, optional)] mouse_events: MouseEvents,
36 #[prop(into, optional)] layer_events: LayerEvents,
37 #[prop(into, optional)] popup_events: PopupEvents,
38 #[prop(into, optional)] tooltip_events: TooltipEvents,
39 #[prop(into, optional)] move_events: MoveEvents,
40
41 #[prop(into)] radius: Signal<f64>,
42 #[prop(optional)] children: Option<Children>,
43) -> impl IntoView {
44 let position_tracking = center;
45 let overlay_context = extend_context_with_overlay();
46 let overlay = JsStoredValue::new_local(None::<leaflet::Circle>);
47
48 let color_clone = color;
49 let fill_color_clone = fill_color;
50 Effect::new(move |_| {
51 if let Some(map) = use_context::<LeafletMapContext>()
52 .expect("map context")
53 .map()
54 {
55 let options = CircleOptions::new();
56 setup_layer_leaflet_option!(stroke, options);
57 setup_layer_leaflet_string!(color, options);
58 setup_layer_leaflet_option!(weight, options);
59 setup_layer_leaflet_option!(opacity, options);
60 setup_layer_leaflet_option!(interactive, options);
61 setup_layer_leaflet_option_ref!(line_cap, options);
62 setup_layer_leaflet_option_ref!(line_join, options);
63 setup_layer_leaflet_string!(dash_array, options);
64 setup_layer_leaflet_string!(dash_offset, options);
65 setup_layer_leaflet_option!(fill, options);
66 setup_layer_leaflet_string!(fill_color, options);
67 setup_layer_leaflet_option!(fill_opacity, options);
68 setup_layer_leaflet_option_ref!(fill_rule, options);
69 setup_layer_leaflet_option!(bubbling_mouse_events, options);
70 setup_layer_leaflet_string!(class_name, options);
71 let circle =
72 leaflet::Circle::new_with_options(¢er.get_untracked().into(), &options);
73
74 leaflet::Circle::set_radius(&circle, radius.get_untracked());
75
76 mouse_events.setup(&circle);
77 popup_events.setup(&circle);
78 tooltip_events.setup(&circle);
79 layer_events.setup(&circle);
80 move_events.setup(&circle);
81
82 circle.add_to(&map);
83 overlay_context.set_container(&circle);
84 overlay.set_value(Some(circle));
85 };
86 });
87
88 let radius_stop = Effect::watch(
89 move || radius.get(),
90 move |radius, _, _| {
91 if let Some(polygon) = overlay.get_value().as_ref() {
92 polygon.set_radius(*radius);
93 }
94 },
95 false,
96 );
97
98 let stroke_stop = Effect::watch(
99 move || stroke.get(),
100 move |stroke, _, _| {
101 if let (Some(stroke), Some(overlay)) = (stroke, overlay.get_value().as_ref()) {
102 let options = CircleOptions::new();
103 options.set_stroke(*stroke);
104 overlay.set_style(&options);
105 }
106 },
107 false,
108 );
109
110 let color_stop = Effect::watch(
111 move || color_clone.get(),
112 move |color, _, _| {
113 if let (Some(color), Some(overlay)) = (color.to_option(), overlay.get_value().as_ref())
114 {
115 let options = CircleOptions::new();
116 options.set_color(color.to_string());
117 overlay.set_style(&options);
118 }
119 },
120 false,
121 );
122
123 let fill_color_stop = Effect::watch(
124 move || fill_color_clone.get(),
125 move |color, _, _| {
126 if let (Some(color), Some(overlay)) = (color.to_option(), overlay.get_value().as_ref())
127 {
128 let options = CircleOptions::new();
129 options.set_fill_color(color.to_string());
130 overlay.set_style(&options);
131 }
132 },
133 false,
134 );
135
136 let opacity_stop = Effect::watch(
137 move || opacity.get(),
138 move |opacity, _, _| {
139 if let (Some(opacity), Some(overlay)) = (opacity, overlay.get_value().as_ref()) {
140 let options = CircleOptions::new();
141 options.set_opacity(*opacity);
142 overlay.set_style(&options);
143 }
144 },
145 false,
146 );
147
148 let fill_opacity_stop = Effect::watch(
149 move || fill_opacity.get(),
150 move |opacity, _, _| {
151 if let (Some(opacity), Some(overlay)) = (opacity, overlay.get_value().as_ref()) {
152 let options = CircleOptions::new();
153 options.set_fill_opacity(*opacity);
154 overlay.set_style(&options);
155 }
156 },
157 false,
158 );
159
160 let weight_stop = Effect::watch(
161 move || weight.get(),
162 move |weight, _, _| {
163 if let (Some(weight), Some(overlay)) = (weight, overlay.get_value().as_ref()) {
164 let options = CircleOptions::new();
165 options.set_weight(*weight);
166 overlay.set_style(&options);
167 }
168 },
169 false,
170 );
171
172 let position_stop = Effect::watch(
173 move || position_tracking.get(),
174 move |position_tracking, _, _| {
175 if let Some(circle) = overlay.get_value().as_ref() {
176 circle.set_lat_lng(&position_tracking.as_lat_lng());
177 }
178 },
179 false,
180 );
181
182 on_cleanup(move || {
183 position_stop.stop();
184 radius_stop.stop();
185 stroke_stop.stop();
186 color_stop.stop();
187 fill_color_stop.stop();
188 opacity_stop.stop();
189 fill_opacity_stop.stop();
190 weight_stop.stop();
191 if let Some(overlay) = overlay.try_get_value().flatten().as_ref() {
192 overlay.remove();
193 }
194 });
195
196 children.map(|child| child())
197}