Background Vector
US
Background Vector

Note: For production, use the blank-map-content.js file instead of map-content.js (this file is for demo purpose). To find the map ID, search by the state name in blank-map-content.js.

🧬 Drill-Down Map - GEO Map Hub Plugin

Drill-Down enables multi-level regional exploration. It highlights states and allows drilling into counties/regions within each state. Each state can show a text label, tooltip, and custom styling. Regions support tooltips, stroke, hover color, and optional click actions. Configurations are handled via drill_down_map_config, and enhanced interactions like zooming and fullscreen are defined in general_config

πŸ“˜ What is Drill-Down Map?

The Drill-Down Map Plugin enables hierarchical navigation in your SVG-based map, allowing users to zoom into subregions (e.g., states β†’ counties) while keeping interactivity like tooltips, strokes, and text labels.

πŸ’‘ Use Case
  • Navigate from a country to individual states, and from states to regions or counties.

  • Display additional info (tooltips, links, labels) per region level.

  • Highlight regions using color/stroke changes on hover.

  • Useful for dashboards, analytics, regional statistics, education platforms.

πŸ“ Folder Structure

Ensure your project follows this structure:

your-project/
β”œβ”€β”€ gmh-plugin/
β”‚    β”œβ”€β”€ assets/
β”‚    β”‚    β”œβ”€β”€ css/
β”‚    β”‚    β”‚    └── style.css
β”‚    β”‚    β”œβ”€β”€ js/
β”‚    β”‚    β”‚    └── script/
β”‚    β”‚    β”‚    β”‚    β”œβ”€β”€ geomaphub.js
β”‚    β”‚    β”‚    β”‚    └── lib/
β”‚    β”‚    β”‚    β”‚    β”‚   β”œβ”€β”€ drill-down-gmh.js           ← Required
β”‚    β”‚    β”‚    β”‚    β”‚   β”œβ”€β”€ advanced-zoom-gmh.js        ← Required
β”‚    β”‚    β”‚    β”‚    β”‚   └── interactive-tooltip-gmh.js  ← Required for interactive (tooltips and links.)
β”‚    β”œβ”€β”€ data/
β”‚    β”‚    β”œβ”€β”€ us/
β”‚    β”‚    β”‚    β”œβ”€β”€ map-content-drill-down.js
β”‚    β”‚    β”‚    └── us-drill-down.svg
β”‚ index.html
βœ… Configuration Breakdown

πŸ”Ή drill_down_map_config

export const drill_down_map_config = [
  {
    /**
     * @property {string} targetClass - Unique identifier for the main state.
    */
    "targetClass": "US-WA",

    /**
     * @property {string} tooltip - Text displayed when hovering over this state.
    */
    "tooltip": "Washington",

    /**
     * @property {Object} color - Fill color settings for the state.
     * @property {string} color.default - Default fill color.
     * @property {string} color.on_hover - Fill color on hover.
    */
    "color": {
      "default": "#f3faff",
      "on_hover": "#005999"
    },

    /**
     * @property {Object} stroke - Border (stroke) settings for the state.
     * @property {string} stroke.color - Border color.
     * @property {string} stroke.width - Border width.
    */
    "stroke": {
      "color": "#6B8B9E",
      "width": "0.8px"
    },

    /**
     * @property {Object} text_label - Configuration for the state's text label.
     * @property {string} text_label.tooltip - Tooltip on label hover.
     * @property {string} text_label.text - Label text (e.g., state abbreviation).
     * @property {Object} text_label.position - X and Y coordinates for positioning.
     * @property {string} text_label.position.x - X coordinate.
     * @property {string} text_label.position.y - Y coordinate.
     * @property {Object} text_label.font - Styling for label font.
     * @property {string} text_label.font.size - Font size.
     * @property {string} text_label.font.color - Font color.
     * @property {string} text_label.font.hover_color - Color on hover.
    */
    "text_label": {
      "tooltip": "Washington",

      "text": "WA",

      "position": {
        "x": "137",
        "y": "62"
      },

      "font": {
        "size": "8px",
        "color": "black",
        "hover_color": "white",
      }
    },

    /**
     * @property {Array<Object>} region - Nested counties or regions inside the state.
    */
    "region": [
      {
        /**
         * @property {string} targetClass - Unique identifier for the region.
        */
        "targetClass": "WA-Adams",

        /**
         * @property {string} tooltip - Tooltip text for the region.
        */
        "tooltip": "Adams",

        /**
         * @property {Object} color - Color settings for the region.
        */
        "color": {
          "default": "#f3faff",
          "on_hover": "#005999"
        },

        /**
         * @property {Object} stroke - Stroke settings for the region.
        */
        "stroke": {
          "color": "#6B8B9E",
          "width": "0.8px"
        },

        /**
         * @property {Object} on_click - Click behavior settings (Optional).
         * @property {string} on_click.url - Redirect URL.
         * @property {string} on_click.target - Target tab or window.
         * @property {string} on_click.cursor - Cursor style on hover.
        */
        "on_click": {
          "url": "https://en.wikipedia.org/wiki/Washington",
          "target": "_blank",
          "cursor": "pointer"
        },
      },
      {
        /**
         * @property {string} targetClass - Unique identifier for the region.
        */
        "targetClass": "WA-Asotin",

        /**
         * @property {string} tooltip - Tooltip text for the region.
        */
        "tooltip": "Asotin",

        /**
         * @property {Object} color - Color settings for the region.
        */
        "color": {
          "default": "#f3faff",
          "on_hover": "#005999"
        },

        /**
         * @property {Object} stroke - Stroke settings for the region.
        */
        "stroke": {
          "color": "#6B8B9E",
          "width": "0.8px"
        }
      },
    ]
  }
]

πŸ”§ drill_down_map_config Object

Key Description
targetClass Unique identifier for the top-level region (e.g., "US-WA")
tooltip Tooltip text shown on hover
color.default Default fill color for the region
color.on_hover Fill color when hovering over the region
stroke.color Stroke/border color for the region
stroke.width Stroke/border width
text_label.tooltip Tooltip text shown on the region label
text_label.text Abbreviation or label text (e.g., "WA")
text_label.position.x X-coordinate for label placement
text_label.position.y Y-coordinate for label placement
text_label.font.size Font size of the label (e.g., "8px")
text_label.font.color Default color of the label text
text_label.font.hover_color Color on hover
region[] Array of nested counties/regions under the top-level state

🧩 region[] Object (Nested Inside Each State)

Key Description
targetClass Unique identifier for the sub-region (e.g., "WA-Adams")
tooltip Tooltip text shown on hover
color.default Default fill color for the region
color.on_hover Fill color on hover
stroke.color Border color for the region
stroke.width Border width for the region
on_click.url URL to open when region is clicked (optional)
on_click.target HTML target behavior (_blank, _self, etc.) (optional)
on_click.cursor Cursor style on hover (pointer, default, etc.) (optional)

πŸ”Ή general_config

/**
 * @constant {Object} general_config - Global configuration settings used throughout the map.
*/
export const general_config = {
  /**
   * @property {Object} id - DOM element IDs used for various parts of the map.
  */
  "id": {
    "map_abbr": "USA",
    "svg_id": "US-DRILL-DOWN-MAP-GMH",
    "marker_id": "US-MARKER-GMH",
    "tooltip_id": "tooltip-gmh",
    "custom_tooltip_id": "custom-tooltip-gmh",
  },

  /**
   * @property {Object} advanced_zoom - Advanced zoom functionality buttons and container.
  */
  "advanced_zoom": {
    "control_id": {
      "reset_zoom": "ADVANCED-ZOOM-RESET-GMH",        /** Button ID for resetting zoom. */
      "zoom_in": "ADVANCED-ZOOM-IN-GMH",              /** Button ID for zooming in. */
      "zoom_out": "ADVANCED-ZOOM-OUT-GMH",            /** Button ID for zooming out. */
      "toggle_fullscreen": "ADVANCED-ZOOM-TOGGLE-FULLSCREEN-GMH",  /** Button ID for toggling fullscreen. */
      "fullscreen_container_class": "svg-container-gmh"          /** Class for the fullscreen container. */
    },
  },

  /**
   * @property {Object} text_label - Global text label settings.
  */
  "text_label": {
    "id": "US-DRILL-DOWN-TEXT-LABEL-GMH",

    "prefix": "TEXT",

    "font": {
      "size": "12px",
      "color": "black",
    }
  },

  /**
   * @property {Object} outer_stroke - Outer stroke styling.
  */
  "outer_stroke": {
    "id": "OUTER-STROKE",

    "stroke": {
      "color": "#6B8B9E",
      "width": "0.8px"
    },
  },

  /**
   * @property {Object} state - Default style for US states.
  */
  "state": {
    "color": {
      "default": "#f3faff",
      "on_hover": "#005999",
    },

    "stroke": {
      "color": "#6B8B9E",
      "width": "0.8px"
    },
  },

  /**
   * @property {Object} region - Default style for inner regions (counties).
  */
  "region": {
    "color": {
      "default": "#f3faff",
      "on_hover": "#005999",
    },

    "stroke": {
      "color": "#6B8B9E",
      "width": "0.8px"
    },
  }
}

βš™οΈ general_config β†’ advanced_zoom

Key Description
control_id.reset_zoom ID of the zoom reset button
control_id.zoom_in ID of the zoom-in button
control_id.zoom_out ID of the zoom-out button
control_id.toggle_fullscreen ID of the fullscreen toggle button
control_id.fullscreen_container_class Class name of the container for fullscreen toggle

πŸ”€ general_config β†’ text_label

Key Description
id ID for the text label container
prefix Prefix string used for dynamically generated IDs
font.size Default font size for all labels
font.color Default font color for all labels

🎨 general_config β†’ state and region

Key Description
color.default Default fill color
color.on_hover Fill color on hover
stroke.color Border color
stroke.width Border width
βš™οΈ Script Setup
<!-- Drill-Down Map -->
<script type="module">
  const currentCountry = "us";

  async function initMap() {
    try {
      // Dynamically import map-specific data
      const {drill_down_map_config, general_config} = await import(`/gmh-plugin/data/${currentCountry}/map-content-drill-down.js`);
      const {GEOMapHub} = await import('/gmh-plugin/assets/js/script/geomaphub.js');
      const {geoMapHubDrillDown} = await import('/gmh-plugin/assets/js/script/lib/drill-down-gmh.js');
      const {geoMapHubAdvancedZoom} = await import('/gmh-plugin/assets/js/script/lib/advanced-zoom-gmh.js');
      const {geoMapHubInteractiveTooltip} = await import('/gmh-plugin/assets/js/script/lib/interactive-tooltip-gmh.js');

      const map = new GEOMapHub("#svg-wrapper-gmh", {
        svgUrl: `/gmh-plugin/data/${currentCountry}/${currentCountry}-drill-down.svg`,
        drillDownMapConfig: drill_down_map_config,
        zoomOptions: {
          zoomControls: true,
          zoomToLocation: {
            onClick: true,
            animation: false,
          },
          handleDrag: true,
          wheelZoom: true,
          fingerPinch: true,
          toggleFullScreen: true
        },
        generalConfig: general_config,
      });

      map.registerPlugin(geoMapHubDrillDown);
      map.registerPlugin(geoMapHubAdvancedZoom);
      map.registerPlugin(geoMapHubInteractiveTooltip);

      map.init();
    } catch (error) {
      console.error("Error initializing map:", error);
    }
  }

  initMap();
</script>
<!-- Drill-Down Map -->

Here's a working example to display the map

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>GEO Map Hub – Drill-Down Map</title>
  <link rel="stylesheet" href="/gmh-plugin/assets/css/style.css" />
</head>

<body>
  <div id="tooltip-gmh"></div>
  <div id="custom-tooltip-gmh"></div>

  <div class="svg-container-gmh">
    <div id="html-content-gmh" class="zoom-element">
      <button class="home-gmh" id="ADVANCED-ZOOM-RESET-GMH">Reset</button>
      <button class="plus-gmh" id="ADVANCED-ZOOM-IN-GMH">+</button>
      <button class="minus-gmh" id="ADVANCED-ZOOM-OUT-GMH">-</button>
      <button class="fullscreen-gmh" id="ADVANCED-ZOOM-TOGGLE-FULLSCREEN-GMH">Fullscreen</button>
    </div>

    <div id="svg-wrapper-gmh"></div>
  </div>

  <!-- Drill-Down Map -->
  <script type="module">
    const currentCountry = "us";

    async function initMap() {
      try {
        // Dynamically import map-specific data
        const {drill_down_map_config, general_config} = await import(`/gmh-plugin/data/${currentCountry}/map-content-drill-down.js`);
        const {GEOMapHub} = await import('/gmh-plugin/assets/js/script/geomaphub.js');
        const {geoMapHubDrillDown} = await import('/gmh-plugin/assets/js/script/lib/drill-down-gmh.js');
        const {geoMapHubAdvancedZoom} = await import('/gmh-plugin/assets/js/script/lib/advanced-zoom-gmh.js');
        const {geoMapHubInteractiveTooltip} = await import('/gmh-plugin/assets/js/script/lib/interactive-tooltip-gmh.js');

        const map = new GEOMapHub("#svg-wrapper-gmh", {
          svgUrl: `/gmh-plugin/data/${currentCountry}/${currentCountry}-drill-down.svg`,
          drillDownMapConfig: drill_down_map_config,
          zoomOptions: {
            zoomControls: true,
            zoomToLocation: {
              onClick: true,
              animation: false,
            },
            handleDrag: true,
            wheelZoom: true,
            fingerPinch: true,
            toggleFullScreen: true
          },
          generalConfig: general_config,
        });

        map.registerPlugin(geoMapHubDrillDown);
        map.registerPlugin(geoMapHubAdvancedZoom);
        map.registerPlugin(geoMapHubInteractiveTooltip);

        map.init();
      } catch (error) {
        console.error("Error initializing map:", error);
      }
    }

    initMap();
  </script>
  <!-- Drill-Down Map -->
</body>

</html>
⚠️ Local CORS Warning

If you're testing with a .html file locally and see this error:

Access to script at 'file:///...' from origin 'null' has been blocked by CORS policy...

It means you're loading the file using the file:// protocol.

βœ… How to Fix

Option 1: Use a Local Server (Recommended for HTML)

  • Live Server (VS Code Extension)

    Install Live Server, right-click your HTML, and choose β€œOpen with Live Server”.

  • Or use any other local server:

    # Python 3
    python -m http.server
    
    # Node.js
    npx http-server
    
    # PHP
    php -S localhost:8080
    
  • Or use a local web server (e.g., XAMPP or Laragon)

Option 2: Deploy to a Real Server

You can upload your files to:

  • Your cPanel or shared hosting

  • A staging VPS or domain

Once the files are accessible via http:// or https://, the plugin works without issues.

πŸ“€ Output Behavior
Feature Behavior
🧭 State Click Zooms into a selected state to show detailed regions.
🧱 Regions Each region supports custom color, tooltip, and optional click actions.
🎯 Advanced Zoom Includes zoom in/out, reset, and fullscreen toggle.
🏷️ Text Labels Short text labels are positioned with defined styles and hover colors.
🧩 Tooltip Interactive tooltip appears on hover for states and regions.
πŸ”— Clickable Regions Regions can be linked with a URL that opens in a new tab.