UNPKG

mapwhizz

Version:

A reusable and customizable SVG map component for visualizing country-based data.

135 lines (113 loc) 3.81 kB
// Start Class MapWhizz export default class MapWhizz { constructor(container, data) { this.container = container; this.data = data; } mount() { console.log('MapWhizz mounted', this.container, this.data); } mount() { try { const parser = new DOMParser(); const svgDoc = parser.parseFromString(this.mapData, 'image/svg+xml'); this.svgElement = svgDoc.documentElement; this.container.innerHTML = ''; // Clear previous content this.container.appendChild(this.svgElement); this.calculateValueRange(); this.addStyles(); this.applyColorsAndInteractions(); } catch (error) { console.error('Error loading SVG:', error); } } calculateValueRange() { this.minValue = Infinity; this.maxValue = -Infinity; this.data.forEach(({ value }) => { this.minValue = Math.min(this.minValue, value); this.maxValue = Math.max(this.maxValue, value); }); } getColorForValue(value) { const percentage = (value - this.minValue) / (this.maxValue - this.minValue); const startColor = [240, 249, 255]; // Light blue const endColor = [24, 72, 176]; // Dark blue const r = Math.round( startColor[0] + percentage * (endColor[0] - startColor[0]) ); const g = Math.round( startColor[1] + percentage * (endColor[1] - startColor[1]) ); const b = Math.round( startColor[2] + percentage * (endColor[2] - startColor[2]) ); return `rgb(${r}, ${g}, ${b})`; } addStyles() { const style = document.createElement('style'); style.textContent = ` path { transition: all 0.3s ease; stroke: #fff; stroke-width: 1; fill: #ccc; } path:hover { fill: rgb(0, 0, 255) !important; stroke-width: 2; cursor: pointer; } `; document.head.appendChild(style); } applyColorsAndInteractions() { const countryDataMap = new Map( this.data.map((item) => [item.country, item]) ); this.svgElement.querySelectorAll('path').forEach((path) => { const country = path.getAttribute('title'); const countryData = countryDataMap.get(country); if (countryData) { path.style.fill = this.getColorForValue(countryData.value); this.addHoverInteraction(path, country, countryData); } }); } addHoverInteraction(path, country, countryData) { path.addEventListener('mouseover', (event) => { const tooltip = this.createTooltip(`${country}: ${countryData.value}`); document.body.appendChild(tooltip); const moveTooltip = (e) => { tooltip.style.left = `${e.pageX + 10}px`; tooltip.style.top = `${e.pageY + 10}px`; }; document.addEventListener('mousemove', moveTooltip); path.addEventListener('mouseout', () => { tooltip.remove(); document.removeEventListener('mousemove', moveTooltip); }); }); } createTooltip(text) { const tooltip = document.createElement('div'); tooltip.style.position = 'absolute'; tooltip.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; tooltip.style.color = '#fff'; tooltip.style.padding = '5px 10px'; tooltip.style.borderRadius = '4px'; tooltip.style.pointerEvents = 'none'; tooltip.style.fontSize = '12px'; tooltip.style.zIndex = '1000'; tooltip.textContent = text; return tooltip; } } // UMD Export (Works with ES6, CommonJS, and <script> tag) if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { module.exports = MapWhizz; } else { window.MapWhizz = MapWhizz; } // export default MapWhizz;