| 1 |
(function () { |
| 2 |
var AM5 = [ |
| 3 |
'https://cdn.amcharts.com/lib/5/index.js', |
| 4 |
'https://cdn.amcharts.com/lib/5/map.js', |
| 5 |
'https://cdn.amcharts.com/lib/5/geodata/worldLow.js', |
| 6 |
'https://cdn.amcharts.com/lib/5/themes/Animated.js' |
| 7 |
]; |
| 8 |
|
| 9 |
function loadScriptsSequential(urls, cb) { |
| 10 |
if (!urls.length) { cb(); return; } |
| 11 |
var s = document.createElement('script'); |
| 12 |
s.src = urls[0]; |
| 13 |
s.onload = function () { loadScriptsSequential(urls.slice(1), cb); }; |
| 14 |
s.onerror = function () { loadScriptsSequential(urls.slice(1), cb); }; |
| 15 |
document.head.appendChild(s); |
| 16 |
} |
| 17 |
|
| 18 |
function hexToInt(hex) { |
| 19 |
var v = (hex || '#aaaaaa').replace('#', ''); |
| 20 |
if (v.length === 3) v = v[0]+v[0]+v[1]+v[1]+v[2]+v[2]; |
| 21 |
return parseInt(v, 16); |
| 22 |
} |
| 23 |
|
| 24 |
function lerp(a, b, t) { |
| 25 |
return Math.round(a + (b - a) * t); |
| 26 |
} |
| 27 |
|
| 28 |
function gradientColor(lowHex, highHex, t) { |
| 29 |
var lc = [ |
| 30 |
parseInt(lowHex.replace('#','').substr(0,2),16), |
| 31 |
parseInt(lowHex.replace('#','').substr(2,2),16), |
| 32 |
parseInt(lowHex.replace('#','').substr(4,2),16), |
| 33 |
]; |
| 34 |
var hc = [ |
| 35 |
parseInt(highHex.replace('#','').substr(0,2),16), |
| 36 |
parseInt(highHex.replace('#','').substr(2,2),16), |
| 37 |
parseInt(highHex.replace('#','').substr(4,2),16), |
| 38 |
]; |
| 39 |
var r = lerp(lc[0],hc[0],t), g = lerp(lc[1],hc[1],t), b = lerp(lc[2],hc[2],t); |
| 40 |
return '#' + ('0'+r.toString(16)).slice(-2) + ('0'+g.toString(16)).slice(-2) + ('0'+b.toString(16)).slice(-2); |
| 41 |
} |
| 42 |
|
| 43 |
function initMap(holder) { |
| 44 |
var countries, opts; |
| 45 |
try { countries = JSON.parse(holder.getAttribute('data-countries') || '[]'); } catch(e){ return; } |
| 46 |
try { opts = JSON.parse(holder.getAttribute('data-opts') || '{}'); } catch(e){ opts={}; } |
| 47 |
|
| 48 |
var am5 = window.am5; |
| 49 |
var am5map = window.am5map; |
| 50 |
var am5geo = window.am5geodata_worldLow; |
| 51 |
var am5themes= window.am5themes_Animated; |
| 52 |
|
| 53 |
if (!am5 || !am5map || !am5geo) return; |
| 54 |
|
| 55 |
/* Build lookup */ |
| 56 |
var countryMap = {}; |
| 57 |
var values = []; |
| 58 |
countries.forEach(function(c){ |
| 59 |
countryMap[c.code] = c; |
| 60 |
values.push(c.value || 0); |
| 61 |
}); |
| 62 |
var minVal = Math.min.apply(null, values) || 0; |
| 63 |
var maxVal = Math.max.apply(null, values) || 1; |
| 64 |
|
| 65 |
/* Create root */ |
| 66 |
holder.style.minHeight = (opts.mapHeight || 480) + 'px'; |
| 67 |
var root = am5.Root.new(holder); |
| 68 |
if (am5themes) root.setThemes([am5themes.new(root)]); |
| 69 |
|
| 70 |
var chart = root.container.children.push( |
| 71 |
am5map.MapChart.new(root, { |
| 72 |
panX: 'rotateX', |
| 73 |
projection: am5map[opts.projection || 'geoNaturalEarth1'] ? am5map[opts.projection || 'geoNaturalEarth1']() : am5map.geoNaturalEarth1(), |
| 74 |
background: am5.Rectangle.new(root, { fill: am5.color(opts.mapBg || '#f0f4f8') }) |
| 75 |
}) |
| 76 |
); |
| 77 |
|
| 78 |
var polygonSeries = chart.series.push( |
| 79 |
am5map.MapPolygonSeries.new(root, { |
| 80 |
geoJSON: am5geo, |
| 81 |
}) |
| 82 |
); |
| 83 |
|
| 84 |
polygonSeries.mapPolygons.template.setAll({ |
| 85 |
tooltipText: opts.showTooltips !== false ? '{name}' : '', |
| 86 |
interactive: true, |
| 87 |
fill: am5.color(opts.defaultFill || '#e5e7eb'), |
| 88 |
stroke: am5.color(opts.borderColor || '#fff'), |
| 89 |
strokeWidth: 0.8, |
| 90 |
}); |
| 91 |
|
| 92 |
polygonSeries.mapPolygons.template.states.create('hover', { |
| 93 |
fill: am5.color(opts.hoverFill || '#ede9fe'), |
| 94 |
}); |
| 95 |
|
| 96 |
/* Colour countries by data */ |
| 97 |
polygonSeries.events.on('datavalidated', function () { |
| 98 |
polygonSeries.mapPolygons.each(function (polygon) { |
| 99 |
var id = polygon.dataItem && polygon.dataItem.get('id'); |
| 100 |
var code = id ? id.replace('AM-','').replace(/^id-/,'').toUpperCase() : ''; |
| 101 |
var country = countryMap[code]; |
| 102 |
|
| 103 |
if (country) { |
| 104 |
var color = opts.defaultFill || '#e5e7eb'; |
| 105 |
if (opts.colorMode === 'custom' && country.color) { |
| 106 |
color = country.color; |
| 107 |
} else if (opts.colorMode === 'uniform') { |
| 108 |
color = opts.highColor || '#5b21b6'; |
| 109 |
} else { |
| 110 |
/* gradient */ |
| 111 |
var t = maxVal > minVal ? (country.value - minVal) / (maxVal - minVal) : 1; |
| 112 |
color = gradientColor(opts.lowColor||'#c4b5fd', opts.highColor||'#5b21b6', t); |
| 113 |
} |
| 114 |
polygon.set('fill', am5.color(color)); |
| 115 |
|
| 116 |
if (opts.showTooltips !== false) { |
| 117 |
var label = (opts.legendTitle || '') + ': ' + country.value; |
| 118 |
polygon.set('tooltipText', country.name + '\n' + label); |
| 119 |
} |
| 120 |
|
| 121 |
if (country.url) { |
| 122 |
polygon.events.on('click', function() { |
| 123 |
window.open(country.url, '_blank'); |
| 124 |
}); |
| 125 |
polygon.set('cursorOverStyle', 'pointer'); |
| 126 |
} |
| 127 |
} |
| 128 |
}); |
| 129 |
}); |
| 130 |
|
| 131 |
/* Legend */ |
| 132 |
if (opts.showLegend) { |
| 133 |
var legendHolder = holder.parentElement && holder.parentElement.querySelector('.bkbg-wm-legend'); |
| 134 |
if (legendHolder) { |
| 135 |
legendHolder.style.display = 'flex'; |
| 136 |
var bar = legendHolder.querySelector('.bkbg-wm-legend-bar'); |
| 137 |
if (bar) { |
| 138 |
bar.style.background = 'linear-gradient(to right, '+(opts.lowColor||'#c4b5fd')+', '+(opts.highColor||'#5b21b6')+')'; |
| 139 |
} |
| 140 |
} |
| 141 |
} |
| 142 |
|
| 143 |
holder._am5Root = root; |
| 144 |
} |
| 145 |
|
| 146 |
function init() { |
| 147 |
var holders = document.querySelectorAll('.bkbg-wm-map-holder[data-countries]'); |
| 148 |
if (!holders.length) return; |
| 149 |
|
| 150 |
loadScriptsSequential(AM5, function () { |
| 151 |
holders.forEach(function (holder) { |
| 152 |
var io = new IntersectionObserver(function(entries, obs){ |
| 153 |
if (entries[0].isIntersecting) { |
| 154 |
obs.disconnect(); |
| 155 |
initMap(holder); |
| 156 |
} |
| 157 |
}, { threshold: 0.1 }); |
| 158 |
io.observe(holder); |
| 159 |
}); |
| 160 |
}); |
| 161 |
} |
| 162 |
|
| 163 |
if (document.readyState !== 'loading') { init(); } |
| 164 |
else { document.addEventListener('DOMContentLoaded', init); } |
| 165 |
})(); |
| 166 |
|