Skip to content

Popup

Popups are used to display information on the map, usually used in conjunction with click or hover events. The SDK provides flexible popup functionality, supporting HTML content, custom styles, and multiple positioning methods.

Basic Usage

Create Popup

javascript
// Create popup instance
const popup = new navMap.Popup({
  closeButton: true,        // Show close button
  closeOnClick: true,        // Close on map click
  anchor: "bottom",          // Anchor position
  offset: [0, -10],         // Offset
  className: "custom-popup", // Custom CSS class
});

// Set position and content
popup.setLngLat([116.3974, 39.9093])
     .setHTML("<h3>Beijing</h3><p>Capital of China</p>")
     .addTo(sdk.map);

Set HTML Content

javascript
// Set simple HTML
popup.setHTML("<h3>Title</h3><p>Content</p>");

// Set complex HTML
popup.setHTML(`
  <div class="popup-content">
    <h3>${feature.properties.name}</h3>
    <p>Coordinates: ${coordinates.join(", ")}</p>
    <button onclick="doSomething()">Action</button>
  </div>
`);

Set Text Content

javascript
// Set plain text
popup.setText("This is text content");

Remove Popup

javascript
// Remove popup
popup.remove();

// Or
popup.removeFrom(sdk.map);

Show Popup on Click

Basic Click Popup

javascript
sdk.on("click", (e) => {
  const popup = new navMap.Popup()
    .setLngLat(e.lngLat)
    .setHTML("<h3>Click Position</h3>")
    .addTo(sdk.map);
});

Show Popup on Feature Click

javascript
sdk.on("click", "airport", (e) => {
  const feature = e.features[0];
  const popup = new navMap.Popup()
    .setLngLat(e.lngLat)
    .setHTML(`<h3>${feature.properties.name}</h3>`)
    .addTo(sdk.map);
});

Using ClickManager

javascript
// Use ClickManager to simplify click popup
sdk.clickObj.clickPopup(
  "airport",                    // Layer ID
  (feature) => {                // HTML generation function
    return `<h3>${feature.properties.name}</h3>
            <p>Type: ${feature.properties.type}</p>`;
  },
  {                             // Popup options
    anchor: "bottom",
    closeButton: true,
  }
);

Async Content Loading

javascript
// Support async content loading
sdk.clickObj.clickPopup(
  "airport",
  async (feature) => {
    // Async fetch data
    const data = await fetch(`/api/airport/${feature.properties.id}`)
      .then(r => r.json());
    
    return `<h3>${data.name}</h3>
            <p>Details: ${data.description}</p>`;
  },
  {
    anchor: "bottom",
  }
);

Show Popup on Hover

Basic Hover Popup

javascript
sdk.on("mouseenter", "airport", (e) => {
  const popup = new navMap.Popup({
    closeButton: false,  // Hover popups usually don't show close button
  })
    .setLngLat(e.lngLat)
    .setHTML(`<h3>${e.features[0].properties.name}</h3>`)
    .addTo(sdk.map);
});

sdk.on("mouseleave", "airport", () => {
  popup.remove();
});

Using HoverManager

javascript
// Use HoverManager to simplify hover popup
sdk.hover.hoverPopup(
  "airport",                    // Layer ID
  (feature) => {                // HTML generation function
    return `<div>${feature.properties.name}</div>`;
  },
  {                             // Popup options
    anchor: "top",
    closeButton: false,
  }
);

Async Content Loading

javascript
// Support async content loading
sdk.hover.hoverPopup(
  "airport",
  async (feature) => {
    const data = await fetch(`/api/airport/${feature.properties.id}`)
      .then(r => r.json());
    return `<div>${data.name}</div>`;
  },
  {
    anchor: "top",
  }
);

Anchor Position

javascript
const popup = new navMap.Popup({
  anchor: "bottom",  // Options:
                     // "center" | "top" | "bottom" | "left" | "right" |
                     // "top-left" | "top-right" | "bottom-left" | "bottom-right"
});

Offset

javascript
const popup = new navMap.Popup({
  offset: [0, -10],  // [x, y] pixel offset
});

// Or use object
const popup = new navMap.Popup({
  offset: {
    "bottom": [0, -10],
    "top": [0, 10],
    "left": [-10, 0],
    "right": [10, 0],
  },
});

Max Width

javascript
const popup = new navMap.Popup()
  .setMaxWidth("300px");  // Set max width

Custom CSS Class

javascript
const popup = new navMap.Popup({
  className: "custom-popup",
});

// CSS
.custom-popup {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

Listen to Popup Events

javascript
const popup = new navMap.Popup();

// Open event
popup.on("open", () => {
  console.log("Popup opened");
});

// Close event
popup.on("close", () => {
  console.log("Popup closed");
});

popup.setLngLat([116.3974, 39.9093])
     .setHTML("<h3>Content</h3>")
     .addTo(sdk.map);

Dynamic Content Updates

Update Position

javascript
// Update popup position
popup.setLngLat([121.4737, 31.2304]);

Update Content

javascript
// Update HTML content
popup.setHTML("<h3>New Content</h3>");

// Update text content
popup.setText("New text");

Track Map Movement

javascript
// Popup follows feature movement
sdk.on("move", () => {
  if (popup.isOpen()) {
    const newPosition = calculateNewPosition();
    popup.setLngLat(newPosition);
  }
});

Multiple Popup Management

Singleton Pattern

javascript
// Ensure only one popup at a time
let currentPopup = null;

sdk.on("click", "airport", (e) => {
  // Close previous popup
  if (currentPopup) {
    currentPopup.remove();
  }
  
  // Create new popup
  currentPopup = new navMap.Popup()
    .setLngLat(e.lngLat)
    .setHTML(`<h3>${e.features[0].properties.name}</h3>`)
    .addTo(sdk.map);
});
javascript
class PopupManager {
  constructor(map) {
    this.map = map;
    this.popups = new Map();
  }
  
  show(id, lngLat, html) {
    // Close previous popup
    this.hide(id);
    
    // Create new popup
    const popup = new navMap.Popup()
      .setLngLat(lngLat)
      .setHTML(html)
      .addTo(this.map);
    
    this.popups.set(id, popup);
  }
  
  hide(id) {
    const popup = this.popups.get(id);
    if (popup) {
      popup.remove();
      this.popups.delete(id);
    }
  }
  
  hideAll() {
    this.popups.forEach(popup => popup.remove());
    this.popups.clear();
  }
}

// Usage
const popupManager = new PopupManager(sdk.map);
popupManager.show("airport-1", [116.3974, 39.9093], "<h3>Beijing</h3>");

Style Customization

Custom Styles

css
/* Global popup styles */
.maplibregl-popup {
  font-family: Arial, sans-serif;
}

.maplibregl-popup-content {
  padding: 15px;
  border-radius: 8px;
}

.maplibregl-popup-close-button {
  font-size: 18px;
  color: #333;
}

/* Custom class styles */
.custom-popup .maplibregl-popup-content {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
}

Responsive Design

css
@media (max-width: 768px) {
  .maplibregl-popup-content {
    max-width: 90vw;
    font-size: 14px;
  }
}

Complete Example

javascript
let sdk;
let currentPopup = null;

async function initMap() {
  sdk = new navMap.MapSDK({
    container: "map",
    center: [116.39, 39.9],
    zoom: 10,
  });

  sdk.on("loadComplete", () => {
    setupPopups();
  });
}

function setupPopups() {
  // 1. Show popup on click
  sdk.on("click", "airport", (e) => {
    const feature = e.features[0];
    
    // Close previous popup
    if (currentPopup) {
      currentPopup.remove();
    }
    
    // Create new popup
    currentPopup = new navMap.Popup({
      closeButton: true,
      closeOnClick: true,
      anchor: "bottom",
      className: "airport-popup",
    })
      .setLngLat(e.lngLat)
      .setHTML(`
        <div class="popup-content">
          <h3>${feature.properties.name}</h3>
          <p>Type: ${feature.properties.type}</p>
          <p>Coordinates: ${e.lngLat.lng.toFixed(4)}, ${e.lngLat.lat.toFixed(4)}</p>
        </div>
      `)
      .addTo(sdk.map);
    
    // Listen to popup events
    currentPopup.on("close", () => {
      console.log("Popup closed");
    });
  });

  // 2. Use ClickManager
  sdk.clickObj.clickPopup(
    "airline",
    async (feature) => {
      // Async load data
      const data = await fetch(`/api/airline/${feature.properties.id}`)
        .then(r => r.json());
      
      return `
        <h3>${data.name}</h3>
        <p>${data.description}</p>
      `;
    },
    {
      anchor: "bottom",
      closeButton: true,
      maxWidth: "300px",
    }
  );

  // 3. Use HoverManager
  sdk.hover.hoverPopup(
    "airport",
    (feature) => {
      return `<div>${feature.properties.name}</div>`;
    },
    {
      anchor: "top",
      closeButton: false,
    }
  );
}

initMap();

Notes

  1. Memory Management: Promptly remove unnecessary popups to avoid memory leaks
  2. Event Cleanup: Remove popup event listeners before page unload
  3. Performance Optimization: Avoid creating popups in frequently triggered events
  4. Content Security: Pay attention to XSS protection when using setHTML
  5. Responsive Design: Consider popup display effects on mobile devices