Documentation

JSVectorMap Integration

JSVectorMap Integration

UltraViolet Pro includes JSVectorMap, a powerful library for creating interactive vector maps and geographical data visualization. This library provides beautiful, scalable maps that work perfectly with Bootstrap and modern web applications.

Overview

JSVectorMap is a modern JavaScript library for creating interactive vector maps. Key features include:

  • Vector-based: Scalable maps that look crisp at any resolution
  • Interactive: Hover effects, tooltips, and click events
  • Customizable: Full control over colors, styling, and behavior
  • Lightweight: Optimized for performance and fast loading
  • Responsive: Works seamlessly across all device sizes

Basic Usage

HTML Setup

<!-- Include JSVectorMap -->
<script src="https://cdn.jsdelivr.net/npm/jsvectormap@1.7.0/dist/js/jsvectormap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/jsvectormap@1.7.0/dist/css/jsvectormap.min.css" rel="stylesheet" />

<!-- Create map container -->
<div id="world-map" style="height: 500px;"></div>

JavaScript Initialization

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: 'transparent'
});

Map Types

World Map

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: 'transparent',
    regionStyle: {
        initial: {
            fill: '#e4e4e4',
            fillOpacity: 0.9,
            stroke: 'none',
            strokeWidth: 0,
            strokeOpacity: 0
        },
        hover: {
            fillOpacity: 0.8,
            cursor: 'pointer'
        }
    }
});

Country Maps

// USA Map
new jsVectorMap({
    selector: '#usa-map',
    map: 'usa',
    backgroundColor: 'transparent'
});

// Canada Map
new jsVectorMap({
    selector: '#canada-map',
    map: 'canada',
    backgroundColor: 'transparent'
});

// Europe Map
new jsVectorMap({
    selector: '#europe-map',
    map: 'europe',
    backgroundColor: 'transparent'
});

Regional Maps

// Asia Map
new jsVectorMap({
    selector: '#asia-map',
    map: 'asia',
    backgroundColor: 'transparent'
});

// Africa Map
new jsVectorMap({
    selector: '#africa-map',
    map: 'africa',
    backgroundColor: 'transparent'
});

Data Visualization

Color-coded Data

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: 'transparent',
    series: {
        regions: [{
            values: {
                'US': 100,
                'CA': 80,
                'GB': 90,
                'DE': 70,
                'FR': 60,
                'IT': 50,
                'ES': 40,
                'AU': 30
            },
            scale: ['#C8EEFF', '#0071A4'],
            normalizeFunction: 'polynomial'
        }]
    },
    onRegionTooltipShow: function(event, tooltip, code) {
        tooltip.html(`
            <div class="tooltip-content">
                <h6>${event.target.attributes['data-name'].value}</h6>
                <p>Value: ${event.target.attributes['data-value'].value}</p>
            </div>
        `);
    }
});

Multiple Data Series

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: 'transparent',
    series: {
        regions: [{
            name: 'Population',
            values: {
                'US': 331000000,
                'CA': 38000000,
                'GB': 67000000,
                'DE': 83000000,
                'FR': 67000000
            },
            scale: ['#FFE5E5', '#FF0000'],
            normalizeFunction: 'polynomial'
        }, {
            name: 'GDP',
            values: {
                'US': 20953000,
                'CA': 1736000,
                'GB': 2830000,
                'DE': 3846000,
                'FR': 2603000
            },
            scale: ['#E5F5E5', '#00FF00'],
            normalizeFunction: 'polynomial'
        }]
    }
});

Interactive Features

Click Events

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: 'transparent',
    onRegionClick: function(event, code) {
        const countryName = event.target.attributes['data-name'].value;
        console.log('Clicked on:', countryName);

        // Handle click event
        showCountryDetails(countryName);
    }
});

function showCountryDetails(countryName) {
    // Show modal or navigate to country details
    alert(`You clicked on ${countryName}`);
}

Hover Effects

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: 'transparent',
    regionStyle: {
        initial: {
            fill: '#e4e4e4',
            fillOpacity: 0.9,
            stroke: 'none',
            strokeWidth: 0,
            strokeOpacity: 0
        },
        hover: {
            fillOpacity: 0.8,
            cursor: 'pointer',
            fill: '#0071A4'
        },
        selected: {
            fill: '#FF0000',
            fillOpacity: 1
        },
        selectedHover: {
            fill: '#FF0000',
            fillOpacity: 0.8
        }
    }
});

Custom Tooltips

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: 'transparent',
    series: {
        regions: [{
            values: {
                'US': 100,
                'CA': 80,
                'GB': 90
            }
        }]
    },
    onRegionTooltipShow: function(event, tooltip, code) {
        const countryName = event.target.attributes['data-name'].value;
        const value = event.target.attributes['data-value'].value;

        tooltip.html(`
            <div class="map-tooltip">
                <h6 class="mb-1">${countryName}</h6>
                <p class="mb-0">Value: ${value}</p>
                <small class="text-muted">Click for details</small>
            </div>
        `);
    }
});

Custom Styling

Bootstrap Integration

.map-tooltip {
    background: var(--bs-dark);
    color: var(--bs-light);
    padding: 0.5rem;
    border-radius: 0.375rem;
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}

.jvectormap-container {
    border-radius: 0.5rem;
    overflow: hidden;
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}

Custom Colors

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: '#f8f9fa',
    regionStyle: {
        initial: {
            fill: '#dee2e6',
            fillOpacity: 0.9,
            stroke: '#ffffff',
            strokeWidth: 1,
            strokeOpacity: 1
        },
        hover: {
            fill: '#007bff',
            fillOpacity: 0.8,
            cursor: 'pointer'
        }
    },
    series: {
        regions: [{
            values: data,
            scale: ['#e3f2fd', '#1976d2'], // Custom color scale
            normalizeFunction: 'polynomial'
        }]
    }
});

Responsive Design

Container Setup

<div class="card">
    <div class="card-header">
        <h5 class="card-title mb-0">Interactive World Map</h5>
    </div>
    <div class="card-body">
        <div class="map-container">
            <div id="world-map"></div>
        </div>
    </div>
</div>
.map-container {
    position: relative;
    width: 100%;
    height: 500px;
    overflow: hidden;
}

@media (max-width: 768px) {
    .map-container {
        height: 300px;
    }
}

Dynamic Sizing

function initMap() {
    const container = document.getElementById('world-map');
    const containerWidth = container.offsetWidth;

    new jsVectorMap({
        selector: '#world-map',
        map: 'world',
        backgroundColor: 'transparent',
        containerStyle: {
            width: '100%',
            height: '500px'
        },
        regionStyle: {
            initial: {
                fill: '#e4e4e4',
                fillOpacity: 0.9,
                stroke: 'none',
                strokeWidth: 0,
                strokeOpacity: 0
            }
        }
    });
}

// Reinitialize on window resize
window.addEventListener('resize', function() {
    setTimeout(initMap, 100);
});

Integration with Laravel

Controller Method

class MapController extends Controller
{
    public function worldData()
    {
        $data = [
            'US' => 100,
            'CA' => 80,
            'GB' => 90,
            'DE' => 70,
            'FR' => 60,
            'IT' => 50,
            'ES' => 40,
            'AU' => 30
        ];

        return response()->json($data);
    }
}

Frontend Integration

async function loadMapData() {
    try {
        const response = await fetch('/api/map-data');
        const data = await response.json();

        new jsVectorMap({
            selector: '#world-map',
            map: 'world',
            backgroundColor: 'transparent',
            series: {
                regions: [{
                    values: data,
                    scale: ['#C8EEFF', '#0071A4'],
                    normalizeFunction: 'polynomial'
                }]
            }
        });
    } catch (error) {
        console.error('Error loading map data:', error);
    }
}

// Initialize map when page loads
document.addEventListener('DOMContentLoaded', loadMapData);

Advanced Features

Markers

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: 'transparent',
    markers: [
        {
            coords: [40.7128, -74.0060],
            name: 'New York'
        },
        {
            coords: [51.5074, -0.1278],
            name: 'London'
        },
        {
            coords: [35.6762, 139.6503],
            name: 'Tokyo'
        }
    ],
    markerStyle: {
        initial: {
            fill: '#FF0000',
            stroke: '#FFFFFF',
            strokeWidth: 2,
            r: 5
        },
        hover: {
            fill: '#FF6666',
            stroke: '#FFFFFF',
            strokeWidth: 2,
            r: 7
        }
    },
    onMarkerTooltipShow: function(event, tooltip, index) {
        tooltip.html(`
            <div class="marker-tooltip">
                <h6 class="mb-0">${event.target.attributes['data-name'].value}</h6>
            </div>
        `);
    }
});

Multiple Maps on One Page

// Initialize multiple maps
document.addEventListener('DOMContentLoaded', function() {
    // World Map
    new jsVectorMap({
        selector: '#world-map',
        map: 'world',
        backgroundColor: 'transparent'
    });

    // USA Map
    new jsVectorMap({
        selector: '#usa-map',
        map: 'usa',
        backgroundColor: 'transparent'
    });

    // Europe Map
    new jsVectorMap({
        selector: '#europe-map',
        map: 'europe',
        backgroundColor: 'transparent'
    });
});

Best Practices

  1. Performance: Use appropriate map sizes for your use case
  2. Accessibility: Provide alternative text and keyboard navigation
  3. Loading States: Show loading indicators while maps initialize
  4. Error Handling: Handle cases where map data fails to load
  5. Mobile Optimization: Ensure maps work well on touch devices
  6. Data Validation: Validate data before passing to map instances

Troubleshooting

Common Issues

  1. Map Not Loading: Check that JSVectorMap CSS and JS files are loaded
  2. Styling Issues: Ensure custom CSS doesn't conflict with map styles
  3. Data Problems: Verify data format matches expected structure
  4. Performance: Use smaller map files for better performance

Debug Mode

new jsVectorMap({
    selector: '#world-map',
    map: 'world',
    backgroundColor: 'transparent',
    debug: true // Enable debug mode
});

Examples in UltraViolet

JSVectorMap is used in several places throughout UltraViolet:

  • Maps Overview: Basic map demonstrations
  • Vector Maps: Advanced examples with data visualization
  • Dashboard: Interactive maps with real-time data
  • Reports: Geographical data analysis

For more examples, check the resources/views/admin/maps/ directory.