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
- Performance: Use appropriate map sizes for your use case
- Accessibility: Provide alternative text and keyboard navigation
- Loading States: Show loading indicators while maps initialize
- Error Handling: Handle cases where map data fails to load
- Mobile Optimization: Ensure maps work well on touch devices
- Data Validation: Validate data before passing to map instances
Troubleshooting
Common Issues
- Map Not Loading: Check that JSVectorMap CSS and JS files are loaded
- Styling Issues: Ensure custom CSS doesn't conflict with map styles
- Data Problems: Verify data format matches expected structure
- 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.