@@ -2,20 +2,168 @@ import { Meta, Source } from '@storybook/blocks';
22
33import * as InteractivePopupStories from ' ./InteractivePopup.stories' ;
44
5- import Popup from ' ./InteractivePopup ' ;
5+ import InteractivePopup from ' ./InteractivePopupExample ' ;
66
77<Meta of = { InteractivePopupStories } />
88
9- # Popup
10- A popup is an information window anchored at a specified position on a map.
11- With ** react-azure-maps** , you can quickly customize the ` Popup ` component with these 3 props:
12- <Popup isVisible options = { { position: [0 , 0 ] }} />
13- { /* show basic code */ }
9+ # Interactive Popup
10+ Besides the static popup, you can also create an interactive popup containing React components.<br />
11+ Therefore, you can easily change the states of the components both inside and outside the popup.<br />
12+ ## Example
13+ Here is an example of an interactive popup that shows a counter counting the number of times the user has clicked on the popup.<br />
14+ You can also change the popup's color by clicking the button on the top left corner.
15+
16+ <InteractivePopup isVisible options = { { position: [0 , 0 ] }} />
17+
18+
19+ Let's take a look of how the interactive popup is implemented.<br />
20+ ## Implementation
21+ ### 1. Create an interactive popup component
22+ Here we initialize a new Popup instance and render the React node children for the popup's content.<br />
23+
24+ <Source code = { `
25+ import { useContext, useEffect, useState, ReactNode } from 'react';
26+ import { createRoot } from 'react-dom/client';
27+ import atlas from 'azure-maps-control';
28+ import { IAzureMapsContextProps, AzureMapsContext, IAzureMapPopupEvent } from 'react-azure-maps';
29+
30+ interface InteractivePopupProps {
31+ children: ReactNode;
32+ isVisible?: boolean;
33+ options?: atlas.PopupOptions;
34+ events?: IAzureMapPopupEvent[];
35+ }
36+
37+ const InteractivePopup = ({ children, isVisible = true, options, events }: InteractivePopupProps) => {
38+ const { mapRef } = useContext<IAzureMapsContextProps>(AzureMapsContext);
39+ const containerRef = document.createElement('div');
40+ const root = createRoot(containerRef);
41+ const [popupRef] = useState<atlas.Popup>(new atlas.Popup({ ...options, content: containerRef }));
42+
43+ // Add events to the popup when it is mounted
44+ useEffect(() => {
45+ if (mapRef) {
46+ events &&
47+ events.forEach(({ eventName, callback }) => {
48+ mapRef.events.add(eventName, popupRef, callback);
49+ });
50+ return () => {
51+ mapRef.popups.remove(popupRef);
52+ };
53+ }
54+ }, []);
55+
56+ // Render the popup content and set the options
57+ useEffect(() => {
58+ root.render(children);
59+ popupRef.setOptions({
60+ ...options,
61+ content: containerRef,
62+ });
63+ if (mapRef && isVisible && !popupRef.isOpen()) {
64+ popupRef.open(mapRef);
65+ }
66+ }, [options, children]);
67+
68+ // Toggle the popup visibility
69+ useEffect(() => {
70+ if (mapRef) {
71+ if (isVisible && !popupRef.isOpen()) {
72+ popupRef.open(mapRef);
73+ } else if (mapRef.popups.getPopups().length && !isVisible && popupRef.isOpen()) {
74+ popupRef.close();
75+ }
76+ }
77+ }, [isVisible]);
78+
79+ return null;
80+ };
81+
82+ export default InteractivePopup;
83+
84+ ` } />
85+
86+ ### 2. Create your popup content
87+ In this example we create a simple counter component that increments the count when the user clicks on the popup.<br />
88+ Also, it accepts a background color as a prop to change the popup's color.<br />
89+ ** You can create any kind of React component as the popup content.**
1490
1591<Source code = { `
16- <AzureMapPopup
17- isVisible
18- options={{ position: [0, 0] }}
19- popupContent={<div style={{ padding: '20px' }}>Hello World</div>}
20- />
21- ` } />
92+ import { useState } from 'react';
93+
94+ const PopupContent = ({ bgColor }: { bgColor: string }) => {
95+ const [count, setCount] = useState(0);
96+
97+ return (
98+ <div style={{ padding: '10px', backgroundColor: bgColor, textAlign: 'center' }}>
99+ <h3>This is a counter:</h3>
100+ <p>You have clicked {count} times.</p>
101+ <button
102+ style={{
103+ border: '1px',
104+ padding: '4px',
105+ cursor: 'pointer',
106+ backgroundColor: 'gainsboro',
107+ }}
108+ onClick={() => {
109+ setCount(count + 1);
110+ }}
111+ >
112+ Click me
113+ </button>
114+ <button
115+ style={{
116+ border: '1px',
117+ padding: '4px',
118+ cursor: 'pointer',
119+ color: 'blue',
120+ backgroundColor: 'transparent',
121+ }}
122+ onClick={() => {
123+ setCount(0);
124+ }}
125+ >
126+ Reset
127+ </button>
128+ </div>
129+ );
130+ };
131+
132+ export default PopupContent;
133+ ` } />
134+
135+ ### 3. Use the interactive popup
136+ Finally, you can use the interactive popup component on your map and pass your react component as children.<br />
137+
138+ <Source code = { `
139+ import { AzureMap, AzureMapsProvider } from 'react-azure-maps';
140+ import InteractivePopup from './InteractivePopup';
141+ import PopupContent from './PopupContent';
142+ import { useState } from 'react';
143+
144+ const YourMap = () => {
145+ const [bgColor, setBgColor] = useState('white');
146+
147+ // click to change color randomly
148+ const changeColor = () => {
149+ const color = \` #\$ {Math.floor(Math.random() * 16777215).toString(16)}\` ;
150+ setBgColor(color);
151+ };
152+ return (
153+ <AzureMapsProvider>
154+ <div>
155+ <button onClick={changeColor} style={{ marginBottom: '10px' }}>
156+ Change popup color
157+ </button>
158+ <div style={...}>
159+ <AzureMap options={yourOptions}>
160+ <InteractivePopup isVisible options={{ position: [0, 0] }}>
161+ <PopupContent bgColor={bgColor} />
162+ </InteractivePopup>
163+ </AzureMap>
164+ </div>
165+ </div>
166+ </AzureMapsProvider>
167+ );
168+ };
169+ ` } />
0 commit comments