UNPKG

svgmap

Version:

svgMap is a JavaScript library that lets you easily create an interactable world map comparing customizable data for each country.

1,434 lines (1,327 loc) 154 kB
/*! svgMap | https://github.com/StephanWagner/svgMap | MIT License | Copyright Stephan Wagner | https://stephanwagner.me */ // Wrapper function function svgMapWrapper(svgPanZoom) { var svgMap = function (options) { this.init(options); }; // Initialize SVG Worldmap svgMap.prototype.init = function (options) { // Default options, pass a custom options object to overwrite specific var defaultOptions = { // The element to render the map in targetElementID: '', // Minimum and maximum zoom minZoom: 1, maxZoom: 25, // Initial zoom initialZoom: 1.06, // Initial pan initialPan: { x: 0, y: 0 }, // Zoom sensitivity zoomScaleSensitivity: 0.2, // Zoom with mousewheel mouseWheelZoomEnabled: true, // Allow zooming only when one of the following keys is pressed: 'shift', 'control', 'alt' (Windows), 'command' (MacOS), 'option' (MacOS) mouseWheelZoomWithKey: false, // The message to show for non MacOS systems mouseWheelKeyMessage: 'Press the [ALT] key to zoom', // The message to show for MacOS mouseWheelKeyMessageMac: 'Press the [COMMAND] key to zoom', // Data colors colorMax: '#CC0033', colorMin: '#FFE5D9', colorNoData: '#E2E2E2', // Color attribute for setting a manual color in the data object manualColorAttribute: 'color', // The flag type can be 'image' or 'emoji' flagType: 'image', // The URL to the flags when using flag type 'image', {0} will get replaced with the lowercase country id flagURL: 'https://cdn.jsdelivr.net/gh/hjnilsson/country-flags@latest/svg/{0}.svg', // Decide whether to show the flag option or not hideFlag: false, // Whether attributes with no data should be displayed hideMissingData: false, // The default text to be shown when no data is present noDataText: 'No data available', // Set to true to open the link on mobile devices, set to false (default) to show the tooltip touchLink: false, // Set to true to show the to show a zoom reset button showZoomReset: false, // Called when a tooltip is created to custimize the tooltip content onGetTooltip: function (tooltipDiv, countryID, countryValues) { return null; }, // Country specific options countries: { // Western Sahara: Set to false to combine Morocco (MA) and Western Sahara (EH) EH: true }, // Set to true to show a drop down menu with the continents showContinentSelector: false, }; this.options = Object.assign({}, defaultOptions, options || {}); // Abort if target element not found if ( !this.options.targetElementID || !document.getElementById(this.options.targetElementID) ) { this.error('Target element not found'); } // Abort if no data if (!this.options.data) { this.error('No data'); } // Global id this.id = this.options.targetElementID; // Wrapper element this.wrapper = document.getElementById(this.options.targetElementID); this.wrapper.classList.add('svgMap-wrapper'); // Container element this.container = document.createElement('div'); this.container.classList.add('svgMap-container'); this.wrapper.appendChild(this.container); // Block scrolling when option is enabled if ( this.options.mouseWheelZoomEnabled && this.options.mouseWheelZoomWithKey ) { this.addMouseWheelZoomNotice(); this.addMouseWheelZoomWithKeyEvents(); } // Map container element this.mapContainer = document.createElement('div'); this.mapContainer.classList.add('svgMap-map-container'); this.container.appendChild(this.mapContainer); // Create the map this.createMap(); // Apply map data this.applyData(this.options.data); }; // Countries svgMap.prototype.countries = { AF: 'Afghanistan', AX: 'Åland Islands', AL: 'Albania', DZ: 'Algeria', AS: 'American Samoa', AD: 'Andorra', AO: 'Angola', AI: 'Anguilla', AQ: 'Antarctica', AG: 'Antigua and Barbuda', AR: 'Argentina', AM: 'Armenia', AW: 'Aruba', AU: 'Australia', AT: 'Austria', AZ: 'Azerbaijan', BS: 'Bahamas', BH: 'Bahrain', BD: 'Bangladesh', BB: 'Barbados', BY: 'Belarus', BE: 'Belgium', BZ: 'Belize', BJ: 'Benin', BM: 'Bermuda', BT: 'Bhutan', BO: 'Bolivia', BA: 'Bosnia and Herzegovina', BW: 'Botswana', BR: 'Brazil', IO: 'British Indian Ocean Territory', VG: 'British Virgin Islands', BN: 'Brunei Darussalam', BG: 'Bulgaria', BF: 'Burkina Faso', BI: 'Burundi', KH: 'Cambodia', CM: 'Cameroon', CA: 'Canada', CV: 'Cape Verde', BQ: 'Caribbean Netherlands', KY: 'Cayman Islands', CF: 'Central African Republic', TD: 'Chad', CL: 'Chile', CN: 'China', CX: 'Christmas Island', CC: 'Cocos Islands', CO: 'Colombia', KM: 'Comoros', CG: 'Congo', CK: 'Cook Islands', CR: 'Costa Rica', HR: 'Croatia', CU: 'Cuba', CW: 'Curaçao', CY: 'Cyprus', CZ: 'Czech Republic', CD: 'Democratic Republic of the Congo', DK: 'Denmark', DJ: 'Djibouti', DM: 'Dominica', DO: 'Dominican Republic', EC: 'Ecuador', EG: 'Egypt', SV: 'El Salvador', GQ: 'Equatorial Guinea', ER: 'Eritrea', EE: 'Estonia', ET: 'Ethiopia', FK: 'Falkland Islands', FO: 'Faroe Islands', FM: 'Federated States of Micronesia', FJ: 'Fiji', FI: 'Finland', FR: 'France', GF: 'French Guiana', PF: 'French Polynesia', TF: 'French Southern Territories', GA: 'Gabon', GM: 'Gambia', GE: 'Georgia', DE: 'Germany', GH: 'Ghana', GI: 'Gibraltar', GR: 'Greece', GL: 'Greenland', GD: 'Grenada', GP: 'Guadeloupe', GU: 'Guam', GT: 'Guatemala', GN: 'Guinea', GW: 'Guinea-Bissau', GY: 'Guyana', HT: 'Haiti', HN: 'Honduras', HK: 'Hong Kong', HU: 'Hungary', IS: 'Iceland', IN: 'India', ID: 'Indonesia', IR: 'Iran', IQ: 'Iraq', IE: 'Ireland', IM: 'Isle of Man', IL: 'Israel', IT: 'Italy', CI: 'Ivory Coast', JM: 'Jamaica', JP: 'Japan', JE: 'Jersey', JO: 'Jordan', KZ: 'Kazakhstan', KE: 'Kenya', KI: 'Kiribati', XK: 'Kosovo', KW: 'Kuwait', KG: 'Kyrgyzstan', LA: 'Laos', LV: 'Latvia', LB: 'Lebanon', LS: 'Lesotho', LR: 'Liberia', LY: 'Libya', LI: 'Liechtenstein', LT: 'Lithuania', LU: 'Luxembourg', MO: 'Macau', MK: 'Macedonia', MG: 'Madagascar', MW: 'Malawi', MY: 'Malaysia', MV: 'Maldives', ML: 'Mali', MT: 'Malta', MH: 'Marshall Islands', MQ: 'Martinique', MR: 'Mauritania', MU: 'Mauritius', YT: 'Mayotte', MX: 'Mexico', MD: 'Moldova', MC: 'Monaco', MN: 'Mongolia', ME: 'Montenegro', MS: 'Montserrat', MA: 'Morocco', MZ: 'Mozambique', MM: 'Myanmar', NA: 'Namibia', NR: 'Nauru', NP: 'Nepal', NL: 'Netherlands', NC: 'New Caledonia', NZ: 'New Zealand', NI: 'Nicaragua', NE: 'Niger', NG: 'Nigeria', NU: 'Niue', NF: 'Norfolk Island', KP: 'North Korea', MP: 'Northern Mariana Islands', NO: 'Norway', OM: 'Oman', PK: 'Pakistan', PW: 'Palau', PS: 'Palestine', PA: 'Panama', PG: 'Papua New Guinea', PY: 'Paraguay', PE: 'Peru', PH: 'Philippines', PN: 'Pitcairn Islands', PL: 'Poland', PT: 'Portugal', PR: 'Puerto Rico', QA: 'Qatar', RE: 'Reunion', RO: 'Romania', RU: 'Russia', RW: 'Rwanda', SH: 'Saint Helena', KN: 'Saint Kitts and Nevis', LC: 'Saint Lucia', PM: 'Saint Pierre and Miquelon', VC: 'Saint Vincent and the Grenadines', WS: 'Samoa', SM: 'San Marino', ST: 'São Tomé and Príncipe', SA: 'Saudi Arabia', SN: 'Senegal', RS: 'Serbia', SC: 'Seychelles', SL: 'Sierra Leone', SG: 'Singapore', SX: 'Sint Maarten', SK: 'Slovakia', SI: 'Slovenia', SB: 'Solomon Islands', SO: 'Somalia', ZA: 'South Africa', GS: 'South Georgia and the South Sandwich Islands', KR: 'South Korea', SS: 'South Sudan', ES: 'Spain', LK: 'Sri Lanka', SD: 'Sudan', SR: 'Suriname', SJ: 'Svalbard and Jan Mayen', SZ: 'Eswatini', SE: 'Sweden', CH: 'Switzerland', SY: 'Syria', TW: 'Taiwan', TJ: 'Tajikistan', TZ: 'Tanzania', TH: 'Thailand', TL: 'Timor-Leste', TG: 'Togo', TK: 'Tokelau', TO: 'Tonga', TT: 'Trinidad and Tobago', TN: 'Tunisia', TR: 'Turkey', TM: 'Turkmenistan', TC: 'Turks and Caicos Islands', TV: 'Tuvalu', UG: 'Uganda', UA: 'Ukraine', AE: 'United Arab Emirates', GB: 'United Kingdom', US: 'United States', UM: 'United States Minor Outlying Islands', VI: 'United States Virgin Islands', UY: 'Uruguay', UZ: 'Uzbekistan', VU: 'Vanuatu', VA: 'Vatican City', VE: 'Venezuela', VN: 'Vietnam', WF: 'Wallis and Futuna', EH: 'Western Sahara', YE: 'Yemen', ZM: 'Zambia', ZW: 'Zimbabwe' }; // Apply the data to the map svgMap.prototype.applyData = function (data) { var max = null; var min = null; // Get highest and lowest value Object.keys(data.values).forEach(function (countryID) { var value = parseInt(data.values[countryID][data.applyData], 10); max === null && (max = value); min === null && (min = value); value > max && (max = value); value < min && (min = value); }); data.data[data.applyData].thresholdMax && (max = Math.min(max, data.data[data.applyData].thresholdMax)); data.data[data.applyData].thresholdMin && (min = Math.max(min, data.data[data.applyData].thresholdMin)); // Loop through countries and set colors Object.keys(this.countries).forEach( function (countryID) { var element = document.getElementById( this.id + '-map-country-' + countryID ); if (!element) { return; } if (!data.values[countryID]) { element.setAttribute('fill', this.toHex(this.options.colorNoData)); return; } if (typeof data.values[countryID].color != 'undefined') { element.setAttribute('fill', data.values[countryID].color); return; } var value = Math.max( min, parseInt(data.values[countryID][data.applyData], 10) ); var ratio = Math.max(0, Math.min(1, (value - min) / (max - min))); var color = this.getColor( this.toHex(this.options.colorMax), this.toHex(this.options.colorMin), ratio || ratio === 0 ? ratio : 1 ); element.setAttribute('fill', color); }.bind(this) ); }; // Emoji flags svgMap.prototype.emojiFlags = { AF: '🇦🇫', AX: '🇦🇽', AL: '🇦🇱', DZ: '🇩🇿', AS: '🇦🇸', AD: '🇦🇩', AO: '🇦🇴', AI: '🇦🇮', AQ: '🇦🇶', AG: '🇦🇬', AR: '🇦🇷', AM: '🇦🇲', AW: '🇦🇼', AU: '🇦🇺', AT: '🇦🇹', AZ: '🇦🇿', BS: '🇧🇸', BH: '🇧🇭', BD: '🇧🇩', BB: '🇧🇧', BY: '🇧🇾', BE: '🇧🇪', BZ: '🇧🇿', BJ: '🇧🇯', BM: '🇧🇲', BT: '🇧🇹', BO: '🇧🇴', BA: '🇧🇦', BW: '🇧🇼', BR: '🇧🇷', IO: '🇮🇴', VG: '🇻🇬', BN: '🇧🇳', BG: '🇧🇬', BF: '🇧🇫', BI: '🇧🇮', KH: '🇰🇭', CM: '🇨🇲', CA: '🇨🇦', CV: '🇨🇻', BQ: '🇧🇶', KY: '🇰🇾', CF: '🇨🇫', TD: '🇹🇩', CL: '🇨🇱', CN: '🇨🇳', CX: '🇨🇽', CC: '🇨🇨', CO: '🇨🇴', KM: '🇰🇲', CG: '🇨🇬', CK: '🇨🇰', CR: '🇨🇷', HR: '🇭🇷', CU: '🇨🇺', CW: '🇨🇼', CY: '🇨🇾', CZ: '🇨🇿', CD: '🇨🇩', DK: '🇩🇰', DJ: '🇩🇯', DM: '🇩🇲', DO: '🇩🇴', EC: '🇪🇨', EG: '🇪🇬', SV: '🇸🇻', GQ: '🇬🇶', ER: '🇪🇷', EE: '🇪🇪', ET: '🇪🇹', FK: '🇫🇰', FO: '🇫🇴', FM: '🇫🇲', FJ: '🇫🇯', FI: '🇫🇮', FR: '🇫🇷', GF: '🇬🇫', PF: '🇵🇫', TF: '🇹🇫', GA: '🇬🇦', GM: '🇬🇲', GE: '🇬🇪', DE: '🇩🇪', GH: '🇬🇭', GI: '🇬🇮', GR: '🇬🇷', GL: '🇬🇱', GD: '🇬🇩', GP: '🇬🇵', GU: '🇬🇺', GT: '🇬🇹', GN: '🇬🇳', GW: '🇬🇼', GY: '🇬🇾', HT: '🇭🇹', HN: '🇭🇳', HK: '🇭🇰', HU: '🇭🇺', IS: '🇮🇸', IN: '🇮🇳', ID: '🇮🇩', IR: '🇮🇷', IQ: '🇮🇶', IE: '🇮🇪', IM: '🇮🇲', IL: '🇮🇱', IT: '🇮🇹', CI: '🇨🇮', JM: '🇯🇲', JP: '🇯🇵', JE: '🇯🇪', JO: '🇯🇴', KZ: '🇰🇿', KE: '🇰🇪', KI: '🇰🇮', XK: '🇽🇰', KW: '🇰🇼', KG: '🇰🇬', LA: '🇱🇦', LV: '🇱🇻', LB: '🇱🇧', LS: '🇱🇸', LR: '🇱🇷', LY: '🇱🇾', LI: '🇱🇮', LT: '🇱🇹', LU: '🇱🇺', MO: '🇲🇴', MK: '🇲🇰', MG: '🇲🇬', MW: '🇲🇼', MY: '🇲🇾', MV: '🇲🇻', ML: '🇲🇱', MT: '🇲🇹', MH: '🇲🇭', MQ: '🇲🇶', MR: '🇲🇷', MU: '🇲🇺', YT: '🇾🇹', MX: '🇲🇽', MD: '🇲🇩', MC: '🇲🇨', MN: '🇲🇳', ME: '🇲🇪', MS: '🇲🇸', MA: '🇲🇦', MZ: '🇲🇿', MM: '🇲🇲', NA: '🇳🇦', NR: '🇳🇷', NP: '🇳🇵', NL: '🇳🇱', NC: '🇳🇨', NZ: '🇳🇿', NI: '🇳🇮', NE: '🇳🇪', NG: '🇳🇬', NU: '🇳🇺', NF: '🇳🇫', KP: '🇰🇵', MP: '🇲🇵', NO: '🇳🇴', OM: '🇴🇲', PK: '🇵🇰', PW: '🇵🇼', PS: '🇵🇸', PA: '🇵🇦', PG: '🇵🇬', PY: '🇵🇾', PE: '🇵🇪', PH: '🇵🇭', PN: '🇵🇳', PL: '🇵🇱', PT: '🇵🇹', PR: '🇵🇷', QA: '🇶🇦', RE: '🇷🇪', RO: '🇷🇴', RU: '🇷🇺', RW: '🇷🇼', SH: '🇸🇭', KN: '🇰🇳', LC: '🇱🇨', PM: '🇵🇲', VC: '🇻🇨', WS: '🇼🇸', SM: '🇸🇲', ST: '🇸🇹', SA: '🇸🇦', SN: '🇸🇳', RS: '🇷🇸', SC: '🇸🇨', SL: '🇸🇱', SG: '🇸🇬', SX: '🇸🇽', SK: '🇸🇰', SI: '🇸🇮', SB: '🇸🇧', SO: '🇸🇴', ZA: '🇿🇦', GS: '🇬🇸', KR: '🇰🇷', SS: '🇸🇸', ES: '🇪🇸', LK: '🇱🇰', SD: '🇸🇩', SR: '🇸🇷', SJ: '🇸🇯', SZ: '🇸🇿', SE: '🇸🇪', CH: '🇨🇭', SY: '🇸🇾', TW: '🇹🇼', TJ: '🇹🇯', TZ: '🇹🇿', TH: '🇹🇭', TL: '🇹🇱', TG: '🇹🇬', TK: '🇹🇰', TO: '🇹🇴', TT: '🇹🇹', TN: '🇹🇳', TR: '🇹🇷', TM: '🇹🇲', TC: '🇹🇨', TV: '🇹🇻', UG: '🇺🇬', UA: '🇺🇦', AE: '🇦🇪', GB: '🇬🇧', US: '🇺🇸', UM: '🇺🇲', VI: '🇻🇮', UY: '🇺🇾', UZ: '🇺🇿', VU: '🇻🇺', VA: '🇻🇦', VE: '🇻🇪', VN: '🇻🇳', WF: '🇼🇫', EH: '🇪🇭', YE: '🇾🇪', ZM: '🇿🇲', ZW: '🇿🇼' }; svgMap.prototype.continents = { "EA": { "iso": "EA", "name": "World" }, "AF": { "iso": "AF", "name": "Africa", "pan": { x: 454, y: 250 }, "zoom": 1.90 }, "AS": { "iso": "AS", "name": "Asia", "pan": { x: 904, y: 80 }, "zoom": 1.8 }, "EU": { "iso": "EU", "name": "Europe", "pan": { x: 404, y: 80 }, "zoom": 5 }, "NA": { "iso": "NA", "name": "North America", "pan": { x: 104, y: 55 }, "zoom": 2.6 }, "MA": { "iso": "MA", "name": "Middle America", "pan": { x: 104, y: 200 }, "zoom": 2.6 }, "SA": { "iso": "SA", "name": "South America", "pan": { x: 104, y: 340 }, "zoom": 2.2 }, "OC": { "iso": "OC", "name": "Oceania", "pan": { x: 954, y: 350 }, "zoom": 1.90 }, } // Create the SVG map svgMap.prototype.createMap = function () { // Create the tooltip this.createTooltip(); // Create map wrappers this.mapWrapper = this.createElement( 'div', 'svgMap-map-wrapper', this.mapContainer ); this.mapImage = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ); this.mapImage.setAttribute('viewBox', '0 0 2000 1001'); this.mapImage.classList.add('svgMap-map-image'); this.mapWrapper.appendChild(this.mapImage); // Add controls var mapControlsWrapper = this.createElement( 'div', 'svgMap-map-controls-wrapper', this.mapWrapper ); var zoomContainer = this.createElement( 'div', 'svgMap-map-controls-zoom', mapControlsWrapper ); ['in', 'out', 'reset'].forEach( function (item) { if (item === 'reset' && this.options.showZoomReset || item !== 'reset') { var zoomControlName = 'zoomControl' + item.charAt(0).toUpperCase() + item.slice(1); this[zoomControlName] = this.createElement( 'button', 'svgMap-control-button svgMap-zoom-button svgMap-zoom-' + item + '-button', zoomContainer ); this[zoomControlName].type = 'button'; this[zoomControlName].addEventListener( 'click', function () { this.zoomMap(item); }.bind(this), { passive: true } ); } }.bind(this) ); // Add accessible names to zoom controls this.zoomControlIn.setAttribute('aria-label', 'Zoom in'); this.zoomControlOut.setAttribute('aria-label', 'Zoom out'); if (this.options.showContinentSelector) { // Add continent controls var mapContinentControlsWrapper = this.createElement( 'div', 'svgMap-map-continent-controls-wrapper', this.mapWrapper ); this["continentSelect"] = this.createElement( 'select', 'svgMap-continent-select', mapContinentControlsWrapper ); var that = this; Object.keys(svgMap.prototype.continents).forEach( function (item) { let element = that.createElement( 'option', 'svgMap-continent-option svgMap-continent-iso-' + svgMap.prototype.continents[item].iso, that["continentSelect"], svgMap.prototype.continents[item].name ); element.value = item } ); this.continentSelect.addEventListener( 'change', function (e) { const continent = e.target.value; if (continent) this.zoomContinent(e.target.value); }.bind(that), { passive: true } ); mapContinentControlsWrapper.setAttribute('aria-label', 'Select continent'); } // Fix countries var mapPaths = Object.assign({}, this.mapPaths); if (!this.options.countries.EH) { mapPaths.MA.d = mapPaths['MA-EH'].d; delete mapPaths.EH; } delete mapPaths['MA-EH']; // Expose tooltipMove function this.tooltipMoveEvent = function (e) { this.moveTooltip(e); }.bind(this); // Add map elements Object.keys(mapPaths).forEach( function (countryID) { var countryData = this.mapPaths[countryID]; if (!countryData.d) { return; } var countryElement = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); countryElement.setAttribute('d', countryData.d); countryElement.setAttribute( 'id', this.id + '-map-country-' + countryID ); countryElement.setAttribute('data-id', countryID); countryElement.classList.add('svgMap-country'); this.mapImage.appendChild(countryElement); // Tooltip events // Add tooltip when touch is used countryElement.addEventListener( 'touchstart', function (e) { countryElement.parentNode.appendChild(countryElement); countryElement.classList.add('svgMap-active'); var countryID = countryElement.getAttribute('data-id'); var countryLink = countryElement.getAttribute('data-link'); if (this.options.touchLink) { if (countryLink) { window.location.href = countryLink; return; } } this.setTooltipContent(this.getTooltipContent(countryID)); this.showTooltip(e); this.moveTooltip(e); countryElement.addEventListener( 'touchmove', this.tooltipMoveEvent, { passive: true } ); }.bind(this), { passive: true } ); countryElement.addEventListener( 'mouseenter', function (e) { countryElement.parentNode.appendChild(countryElement); var countryID = countryElement.getAttribute('data-id'); this.setTooltipContent(this.getTooltipContent(countryID)); this.showTooltip(e); countryElement.addEventListener( 'mousemove', this.tooltipMoveEvent, { passive: true } ); }.bind(this), { passive: true } ); if ( this.options.data.values && this.options.data.values[countryID] && this.options.data.values[countryID]['link'] ) { countryElement.setAttribute( 'data-link', this.options.data.values[countryID]['link'] ); if (this.options.data.values[countryID]['linkTarget']) { countryElement.setAttribute( 'data-link-target', this.options.data.values[countryID]['linkTarget'] ); } let dragged = false; countryElement.addEventListener('mousedown', function () { dragged = false }); countryElement.addEventListener('touchstart', function () { dragged = false }); countryElement.addEventListener('mousemove', function () { dragged = true }); countryElement.addEventListener('touchmove', function () { dragged = true }); const clickHandler = function (e) { if (dragged) { return; } const link = countryElement.getAttribute('data-link'); const target = countryElement.getAttribute('data-link-target'); if (target) { window.open(link, target); } else { window.location.href = link; } } countryElement.addEventListener('click', clickHandler); countryElement.addEventListener('touchend', clickHandler); } // Hide tooltip when mouse leaves the country area countryElement.addEventListener( 'mouseleave', function () { this.hideTooltip(); countryElement.removeEventListener( 'mousemove', this.tooltipMoveEvent, { passive: true } ); }.bind(this), { passive: true } ); // Hide tooltip when touch ends countryElement.addEventListener( 'touchend', function () { this.hideTooltip(); countryElement.classList.remove('svgMap-active'); countryElement.removeEventListener( 'touchmove', this.tooltipMoveEvent, { passive: true } ); }.bind(this), { passive: true } ); }.bind(this) ); // Expose instance var me = this; // Init pan zoom this.mapPanZoom = svgPanZoom(this.mapImage, { zoomEnabled: true, fit: true, center: true, minZoom: this.options.minZoom, maxZoom: this.options.maxZoom, zoomScaleSensitivity: this.options.zoomScaleSensitivity, controlIconsEnabled: false, mouseWheelZoomEnabled: this.options.mouseWheelZoomEnabled, preventMouseEventsDefault: true, onZoom: function () { me.setControlStatuses(); }, beforePan: function (oldPan, newPan) { var gutterWidth = me.mapWrapper.offsetWidth * 0.85; var gutterHeight = me.mapWrapper.offsetHeight * 0.85; var sizes = this.getSizes(); var leftLimit = -((sizes.viewBox.x + sizes.viewBox.width) * sizes.realZoom) + gutterWidth; var rightLimit = sizes.width - gutterWidth - sizes.viewBox.x * sizes.realZoom; var topLimit = -((sizes.viewBox.y + sizes.viewBox.height) * sizes.realZoom) + gutterHeight; var bottomLimit = sizes.height - gutterHeight - sizes.viewBox.y * sizes.realZoom; return { x: Math.max(leftLimit, Math.min(rightLimit, newPan.x)), y: Math.max(topLimit, Math.min(bottomLimit, newPan.y)) }; } }); if (this.options.initialPan.x != 0 || this.options.initialPan.y != 0) { // Init zoom and pan this.mapPanZoom.zoomAtPointBy(this.options.initialZoom, { x: this.options.initialPan.x, y: this.options.initialPan.y }); } else { // Init zoom this.mapPanZoom.zoom(this.options.initialZoom); } // Initial zoom statuses this.setControlStatuses(); }; // Create the tooltip content svgMap.prototype.getTooltipContent = function (countryID) { // Custom tooltip if (this.options.onGetTooltip) { var customDiv = this.options.onGetTooltip( this.tooltip, countryID, this.options.data.values[countryID] ); if (customDiv) { return customDiv; } } var tooltipContentWrapper = this.createElement( 'div', 'svgMap-tooltip-content-container' ); if (this.options.hideFlag === false) { // Flag var flagContainer = this.createElement( 'div', 'svgMap-tooltip-flag-container svgMap-tooltip-flag-container-' + this.options.flagType, tooltipContentWrapper ); if (this.options.flagType === 'image') { this.createElement( 'img', 'svgMap-tooltip-flag', flagContainer ).setAttribute( 'src', this.options.flagURL.replace('{0}', countryID.toLowerCase()) ); } else if (this.options.flagType === 'emoji') { flagContainer.innerHTML = this.emojiFlags[countryID]; } } // Title this.createElement( 'div', 'svgMap-tooltip-title', tooltipContentWrapper ).innerHTML = this.getCountryName(countryID); // Content var tooltipContent = this.createElement( 'div', 'svgMap-tooltip-content', tooltipContentWrapper ); if (!this.options.data.values[countryID]) { this.createElement( 'div', 'svgMap-tooltip-no-data', tooltipContent ).innerHTML = this.options.noDataText; } else { var tooltipContentTable = '<table>'; Object.keys(this.options.data.data).forEach( function (key) { var item = this.options.data.data[key]; var value = this.options.data.values[countryID][key]; if ((value !== undefined && this.options.hideMissingData === true) || this.options.hideMissingData === false) { item.floatingNumbers && (value = value.toFixed(1)); item.thousandSeparator && (value = this.numberWithCommas(value, item.thousandSeparator)); value = item.format ? item.format.replace('{0}', '<span>' + value + '</span>') : '<span>' + value + '</span>'; tooltipContentTable += '<tr><td>' + (item.name || '') + '</td><td>' + value + '</td></tr>'; } }.bind(this) ); tooltipContentTable += '</table>'; tooltipContent.innerHTML = tooltipContentTable; } return tooltipContentWrapper; }; // Set the disabled statuses for buttons svgMap.prototype.setControlStatuses = function () { this.zoomControlIn.classList.remove('svgMap-disabled'); this.zoomControlIn.setAttribute('aria-disabled', 'false'); this.zoomControlOut.classList.remove('svgMap-disabled'); this.zoomControlOut.setAttribute('aria-disabled', 'false'); if (this.options.showZoomReset) { this.zoomControlReset.classList.remove('svgMap-disabled'); this.zoomControlReset.setAttribute('aria-disabled', 'false'); } if (this.mapPanZoom.getZoom().toFixed(3) <= this.options.minZoom) { this.zoomControlOut.classList.add('svgMap-disabled'); this.zoomControlOut.setAttribute('aria-disabled', 'true'); } if (this.mapPanZoom.getZoom().toFixed(3) >= this.options.maxZoom) { this.zoomControlIn.classList.add('svgMap-disabled'); this.zoomControlIn.setAttribute('aria-disabled', 'true'); } if (this.options.showZoomReset && this.mapPanZoom.getZoom().toFixed(3) == this.options.initialZoom) { this.zoomControlReset.classList.add('svgMap-disabled'); this.zoomControlReset.setAttribute('aria-disabled', 'true'); } }; // Zoom map svgMap.prototype.zoomMap = function (direction) { if ( this[ 'zoomControl' + direction.charAt(0).toUpperCase() + direction.slice(1) ].classList.contains('svgMap-disabled') ) { return false; } if (direction === 'reset') { this.mapPanZoom.reset(); if (this.options.initialPan.x != 0 || this.options.initialPan.y != 0) { // Init zoom and pan this.mapPanZoom.zoomAtPointBy(this.options.initialZoom, { x: this.options.initialPan.x, y: this.options.initialPan.y }); } else { // Init zoom this.mapPanZoom.zoom(this.options.initialZoom); } } else { this.mapPanZoom[direction == 'in' ? 'zoomIn' : 'zoomOut'](); } }; // Zoom to Contient svgMap.prototype.zoomContinent = function (contientIso) { const continent = this.continents[contientIso]; if (continent.iso == "EA") this.mapPanZoom.reset() else if (continent.pan) { this.mapPanZoom.reset() this.mapPanZoom.zoomAtPoint(continent.zoom, continent.pan); } }; // Add elements to show the zoom with keys notice svgMap.prototype.addMouseWheelZoomNotice = function () { var noticeWrapper = document.createElement('div'); noticeWrapper.classList.add('svgMap-block-zoom-notice'); var noticeContainer = document.createElement('div'); noticeContainer.innerHTML = navigator.appVersion.indexOf('Mac') != -1 ? this.options.mouseWheelKeyMessageMac : this.options.mouseWheelKeyMessage; noticeWrapper.append(noticeContainer); this.wrapper.append(noticeWrapper); }; // Show the zoom with keys notice svgMap.prototype.showMouseWheelZoomNotice = function (duration) { if (this.mouseWheelNoticeJustHidden) { return; } this.autoHideMouseWheelNoticeTimeout && clearTimeout(this.autoHideMouseWheelNoticeTimeout); this.autoHideMouseWheelNoticeTimeout = setTimeout( function () { this.hideMouseWheelZoomNotice(); }.bind(this), duration || 2400 ); this.wrapper.classList.add('svgMap-block-zoom-notice-active'); }; // Hide the zoom with keys notice svgMap.prototype.hideMouseWheelZoomNotice = function () { this.wrapper.classList.remove('svgMap-block-zoom-notice-active'); this.autoHideMouseWheelNoticeTimeout && clearTimeout(this.autoHideMouseWheelNoticeTimeout); }; // Block shing the zoom wheel notice for some time svgMap.prototype.blockMouseWheelZoomNotice = function (duration) { this.mouseWheelNoticeJustHidden = true; this.mouseWheelNoticeJustHiddenTimeout && clearTimeout(this.mouseWheelNoticeJustHiddenTimeout); this.mouseWheelNoticeJustHiddenTimeout = setTimeout( function () { this.mouseWheelNoticeJustHidden = false; }.bind(this), duration || 600 ); }; // Add the events when you are only allowed to scrool with a key pressed svgMap.prototype.addMouseWheelZoomWithKeyEvents = function () { // Add events to wrapper this.wrapper.addEventListener( 'wheel', function (ev) { if (!document.body.classList.contains('svgMap-zoom-key-pressed')) { this.showMouseWheelZoomNotice(); } else { this.hideMouseWheelZoomNotice(); this.blockMouseWheelZoomNotice(); } }.bind(this), { passive: true } ); // Add with keydown document.addEventListener( 'keydown', function (ev) { if ( ev.key == 'Alt' || ev.key == 'Control' || ev.key == 'Meta' || ev.key == 'Shift' ) { document.body.classList.add('svgMap-zoom-key-pressed'); this.hideMouseWheelZoomNotice(); this.blockMouseWheelZoomNotice(); } }.bind(this) ); // Fallback with wheel as sometimes it wont trigger when window is out of focus this.wrapper.addEventListener('wheel', function (ev) { if (ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey) { document.body.classList.add('svgMap-zoom-key-pressed'); // TODO wont be removed when window out of focus } }); // Only add following events to the document once if (document.body.classList.contains('svgMap-key-events-added')) { return false; } document.body.classList.add('svgMap-key-events-added'); // Remove with keyup document.addEventListener('keyup', function (ev) { if ( ev.key == 'Alt' || ev.key == 'Control' || ev.key == 'Meta' || ev.key == 'Shift' ) { document.body.classList.remove('svgMap-zoom-key-pressed'); } }); }; // Map paths svgMap.prototype.mapPaths = { 'AF': { d: 'M1369.9,333.8h-5.4l-3.8-0.5l-2.5,2.9l-2.1,0.7l-1.5,1.3l-2.6-2.1l-1-5.4l-1.6-0.3v-2l-3.2-1.5l-1.7,2.3l0.2,2.6 l-0.6,0.9l-3.2-0.1l-0.9,3l-2.1-1.3l-3.3,2.1l-1.8-0.8l-4.3-1.4h-2.9l-1.6-0.2l-2.9-1.7l-0.3,2.3l-4.1,1.2l0.1,5.2l-2.5,2l-4,0.9 l-0.4,3l-3.9,0.8l-5.9-2.4l-0.5,8l-0.5,4.7l2.5,0.9l-1.6,3.5l2.7,5.1l1.1,4l4.3,1.1l1.1,4l-3.9,5.8l9.6,3.2l5.3-0.9l3.3,0.8l0.9-1.4 l3.8,0.5l6.6-2.6l-0.8-5.4l2.3-3.6h4l0.2-1.7l4-0.9l2.1,0.6l1.7-1.8l-1.1-3.8l1.5-3.8l3-1.6l-3-4.2l5.1,0.2l0.9-2.3l-0.8-2.5l2-2.7 l-1.4-3.2l-1.9-2.8l2.4-2.8l5.3-1.3l5.8-0.8l2.4-1.2l2.8-0.7L1369.9,333.8L1369.9,333.8z' }, 'AL': { d: 'M1077.5,300.5l-2,3.1l0.5,1.9l0,0l1,1l-0.5,1.9l-0.1,4.3l0.7,3l3,2.1l0.2,1.4l1,0.4l2.1-3l0.1-2.1l1.6-0.9V312 l-2.3-1.6l-0.9-2.6l0.4-2.1l0,0l-0.5-2.3l-1.3-0.6l-1.3-1.6l-1.3,0.5L1077.5,300.5L1077.5,300.5z' }, 'DZ': { d: 'M1021,336.9l-3.6,0.4l-2.2-1.5h-5.6l-4.9,2.6l-2.7-1l-8.7,0.5l-8.9,1.2l-5,2l-3.4,2.6l-5.7,1.2l-5.1,3.5l2,4.1 l0.3,3.9l1.8,6.7l1.4,1.4l-1,2.5l-7,1l-2.5,2.4l-3.1,0.5l-0.3,4.7l-6.3,2.5l-2.1,3.2L944,383l-5.4,1l-8.9,4.7l-0.1,7.5v0.4l-0.1,1.2 l20.3,15.5l18.4,13.9l18.6,13.8l1.3,3l3.4,1.8l2.6,1.1l0.1,4l6.1-0.6l7.8-2.8l15.8-12.5l18.6-12.2l-2.5-4l-4.3-2.9l-2.6,1.2l-2-3.6 l-0.2-2.7l-3.4-4.7l2.1-2.6l-0.5-4l0.6-3.5l-0.5-2.9l0.9-5.2l-0.4-3l-1.9-5.6l-2.6-11.3l-3.4-2.6v-1.5l-4.5-3.8l-0.6-4.8l3.2-3.6 l1.1-5.3l-1-6.2L1021,336.9L1021,336.9z' }, 'AD': { d: 'M985.4,301.7l0.2-0.4l-0.2-0.2l-0.7-0.2l-0.3-0.1l-0.4,0.3l-0.1,0.3l0.1,0.1v0.4l0.1,0.2h0.4L985.4,301.7 L985.4,301.7z' }, 'AO': { d: 'M1068.3,609.6l-16.6-0.1l-1.9,0.7l-1.7-0.1l-2.3,0.9l-0.5,1.2l2.8,4l1.1,4.3l1.6,6.1l-1.7,2.6l-0.3,1.3l1.3,3.8 l1.5,3.9l1.6,2.2l0.3,3.6l-0.7,4.8l-1.8,2.8l-3.3,4.2l-1.3,2.6l-1.9,5.7l-0.3,2.7l-2,5.9l-0.9,5.5l0.5,4l2.7-1.2l3.3-1l3.6,0.1 l3.2,2.9l0.9-0.4l22.5-0.3l3.7,3l13.4,0.9l10.3-2.5l-3.5-4l-3.6-5.2l0.8-20.3l11.6,0.1l-0.5-2.2l0.9-2.4l-0.9-3l0.7-3l-0.5-2 l-2.6-0.4l-3.5,1l-2.4-0.2l-1.4,0.6l0.5-7.6l-1.9-2.3l-0.3-4l0.9-3.8l-1.2-2.4v-4h-6.8l0.5-2.3h-2.9l-0.3,1.1l-3.4,0.3l-1.5,3.7 l-0.9,1.6l-3-0.9l-1.9,0.9l-3.7,0.5l-2.1-3.3l-1.3-2.1l-1.6-3.8L1068.3,609.6L1068.3,609.6z M1046.5,608.3l0.2-2.7l0.9-1.7l2-1.3 l-2-2.2l-1.8,1.1l-2.2,2.7l1.4,4.8L1046.5,608.3L1046.5,608.3z' }, 'AI': { d: 'M627.9,456.2l0.1-0.2l-0.2-0.1l-0.8,0.5v0.1L627.9,456.2z' }, 'AG': { d: 'M634.3,463.8l0.2-0.1v-0.1v-0.2l-0.1-0.1l-0.1-0.2l-0.4-0.2l-0.5,0.5v0.2l0.1,0.3l0.6,0.1L634.3,463.8L634.3,463.8z M634.5,460.3v-0.5l-0.1-0.2h-0.3l-0.1-0.1h-0.1l-0.1,0.1l0.1,0.6l0.5,0.3L634.5,460.3L634.5,460.3z' }, 'AR': { d: 'M669.8,920.7l0.9-3l-7.3-1.5l-7.7-3.6l-4.3-4.6l-3-2.8l5.9,13.5h5l2.9,0.2l3.3,2.1L669.8,920.7L669.8,920.7z M619.4,712.6l-7.4-1.5l-4,5.7l0.9,1.6l-1.1,6.6l-5.6,3.2l1.6,10.6l-0.9,2l2,2.5l-3.2,4l-2.6,5.9l-0.9,5.8l1.7,6.2l-2.1,6.5 l4.9,10.9l1.6,1.2l1.3,5.9l-1.6,6.2l1.4,5.4l-2.9,4.3l1.5,5.9l3.3,6.3l-2.5,2.4l0.3,5.7l0.7,6.4l3.3,7.6l-1.6,1.2l3.6,7.1l3.1,2.3 l-0.8,2.6l2.8,1.3l1.3,2.3l-1.8,1.1l1.8,3.7l1.1,8.2l-0.7,5.3l1.8,3.2l-0.1,3.9l-2.7,2.7l3.1,6.6l2.6,2.2l3.1-0.4l1.8,4.6l3.5,3.6 l12,0.8l4.8,0.9l2.2,0.4l-4.7-3.6l-4.1-6.3l0.9-2.9l3.5-2.5l0.5-7.2l4.7-3.5l-0.2-5.6l-5.2-1.3l-6.4-4.5l-0.1-4.7l2.9-3.1l4.7-0.1 l0.2-3.3l-1.2-6.1l2.9-3.9l4.1-1.9l-2.5-3.2l-2.2,2l-4-1.9l-2.5-6.2l1.5-1.6l5.6,2.3l5-0.9l2.5-2.2l-1.8-3.1l-0.1-4.8l-2-3.8 l5.8,0.6l10.2-1.3l6.9-3.4l3.3-8.3l-0.3-3.2l-3.9-2.8l-0.1-4.5l-7.8-5.5l-0.3-3.3l-0.4-4.2l0.9-1.4l-1.1-6.3l0.3-6.5l0.5-5.1 l5.9-8.6l5.3-6.2l3.3-2.6l4.2-3.5l-0.5-5.1l-3.1-3.7l-2.6,1.2l-0.3,5.7l-4.3,4.8l-4.2,1.1l-6.2-1l-5.7-1.8l4.2-9.6l-1.1-2.8 l-5.9-2.5l-7.2-4.7l-4.6-1L632,713.7l-1-1.3l-6.3-0.3l-1.6,5.1L619.4,712.6L619.4,712.6z' }, 'AM': { d: 'M1219,325.1l-0.9-4.4l-2.5-1.1l-2.5-1.7l1-2l-3.1-2.2l0.7-1.5l-2.2-1.1l-1.4-1.7l-6.9,1l1.3,2.2v3.1l4.2,1.5 l2.4,1.9l1-0.2l1.8,1.7h2.3l0.2,1l2.8,3.7L1219,325.1L1219,325.1z' }, 'AW': { d: 'M586.6,492.9l-0.1-0.1l-0.3-0.6l-0.3-0.3l-0.1,0.1l-0.1,0.3l0.3,0.3l0.3,0.4l0.3,0.1L586.6,492.9L586.6,492.9z' }, 'AU': { d: 'M1726.7,832l-3-0.5l-1.9,2.9l-0.6,5.4l-2.1,4l-0.5,5.3l3,0.2l0.8,0.3l6.6-4.3l0.6,1.7l4-4.9l3.2-2.2l4.5-7.3 l-2.8-0.5l-4.8,1.2l-3.4,0.9L1726.7,832L1726.7,832z M1776.8,659.7l0.5-2.3l0.1-3.6l-1.6-3.2l0.1-2.7l-1.3-0.8l0.1-3.9l-1.2-3.2 l-2.3,2.4l-0.4,1.8l-1.5,3.5l-1.8,3.4l0.6,2.1l-1.2,1.3l-1.5,4.8l0.1,3.7l-0.7,1.8l0.3,3.1l-2.6,5l-1.3,3.5l-1.7,2.9l-1.7,3.4 l-4.1,2.1l-4.9-2.1l-0.5-2l-2.5-1.6h-1.6l-3.3-3.8l-2.5-2.2l-3.9-2l-3.9-3.5l-0.1-1.8l2.5-3.1l2.1-3.2l-0.3-2.6l1.9-0.2l2.5-2.5 l2-3.4l-2.2-3.2l-1.5,1.2l-2-0.5l-3.5,1.8l-3.2-2l-1.7,0.7l-4.5-1.6l-2.7-2.7l-3.5-1.5l-3.1,0.9l3.9,2.1l-0.3,3.2l-4.8,1.2l-2.8-0.7 l-3.6,2.2l-2.9,3.7l0.6,1.5l-2.7,1.7l-3.4,5.1l0.6,3.5l-3.4-0.6h-3.5l-2.5-3.8l-3.7-2.9l-2.8,0.8l-2.6,0.9l-0.3,1.6l-2.4-0.7 l-0.3,1.8l-3,1.1l-1.7,2.5l-3.5,3.1l-1.4,4.8l-2.3-1.3l-2.2,3.1l1.5,3l-2.6,1.2l-1.4-5.5l-4.8,5.4l-0.8,3.5l-0.7,2.5l-3.8,3.3 l-2,3.4l-3.5,2.8l-6.1,1.9l-3.1-0.2l-1.5,0.6l-1.1,1.4l-3.5,0.7l-4.7,2.4l-1.4-0.8l-2.6,0.5l-4.6,2.3l-3.2,2.7l-4.8,2.1l-3.1,4.4 l0.4-4.8l-3.1,4.6l-0.1,3.7l-1.3,3.2l-1.5,1.5l-1.3,3.7l0.9,1.9l0.1,2l1.6,5l-0.7,3.3l-1-2.5l-2.3-1.8l0.4,5.9l-1.7-2.8l0.1,2.8 l1.8,5l-0.6,5l1.7,2.5l-0.4,1.9l0.9,4.1l-1.3,3.6l-0.3,3.6l0.7,6.5l-0.7,3.7l-2.2,4.4l-0.6,2.3l-1.5,1.5l-2.9,0.8l-1.5,3.7l2.4,1.2 l4,4.1h3.6l3.8,0.3l3.3-2.1l3.4-1.8l1.4,0.3l4.5-3.4l3.8-0.3l4.1-0.7l4.2,1.2l3.6-0.6l4.6-0.2l3-2.6l2.3-3.3l5.2-1.5l6.9-3.2l5,0.4 l6.9-2.1l7.8-2.3l9.8-0.6l4,3.1l3.7,0.2l5.3,3.8l-1.6,1.5l1.8,2.4l1.3,4.6l-1.6,3.4l2.9,2.6l4.3-5.1l4.3-2.1l6.7-5.5l-1.6,4.7 l-3.4,3.2l-2.5,3.7l-4.4,3.5l5.2-1.2l4.7-4.4l-0.9,4.8l-3.2,3.1l4.7,0.8l1.3,2.6l-0.4,3.3l-1.5,4.9l1.4,4l4,1.9l2.8,0.4l2.4,1 l3.5,1.8l7.2-4.7l3.5-1.2l-2.7,3.4l2.6,1.1l2.7,2.8l4.7-2.7l3.8-2.5l6.3-2.7l6-0.2l4.2-2.3l0.9-2l3-4.5l3.9-4.8l3.6-3.2l4.4-5.6 l3.3-3.1l4.4-5l5.4-3.1l5-5.8l3.1-4.5l1.4-3.6l3.8-5.7l2.1-2.9l2.5-5.7l-0.7-5.4l1.7-3.9l1.1-3.7v-5.1l-2.8-5.1l-1.9-2.5l-2.9-3.9 l0.7-6.7l-1.5,1l-1.6-2.8l-2.5,1.4l-0.6-6.9l-2.2-4l1-1.5l-3.1-2.8l-3.2-3l-5.3-3.3l-0.9-4.3l1.3-3.3l-0.4-5.5l-1.3-0.7l-0.2-3.2 l-0.2-5.5l1.1-2.8l-2.3-2.5l-1.4-2.7l-3.9,2.4L1776.8,659.7L1776.8,659.7z' }, 'AT': { d: 'M1060.2,264l-2.3-1.2l-2.3,0.3l-4-1.9l-1.7,0.5l-2.6,2.5l-3.8-2l-1.5,2.9l-1.7,0.8l1,4l-0.4,1.1l-1.7-1.3l-2.4-0.2 l-3.4,1.2l-4.4-0.3l-0.6,1.6l-2.6-1.7l-1.5,0.3l0.2,1.1l-0.7,1.6l2.3,1.1l2.6,0.2l3.1,0.9l0.5-1.2l4.8-1.1l1.3,2.2l7.2,1.6l4.2,0.4 l2.4-1.4l4.3-0.1l0.9-1.1l1.3-4l-1.1-1.3h2.8l0.2-2.6l-0.7-2.1L1060.2,264L1060.2,264z' }, 'AZ': { d: 'M1210.1,318.9l-1,0.2l1.2,2.4l3.2,2.9l3.7,0.9l-2.8-3.7l-0.2-1h-2.3L1210.1,318.9L1210.1,318.9z M1220.5,309.6 l-4.3-3.8l-1.5-0.2l-1.1,0.9l3.2,3.4l-0.6,0.7l-2.8-0.4l-4.2-1.8l-1.1,1l1.4,1.7l2.2,1.1l-0.7,1.5l3.1,2.2l-1,2l2.5,1.7l2.5,1.1 l0.9,4.4l5.3-4.7l1.9-0.5l1.9,1.9l-1.2,3.1l3.8,3.4l1.3-0.3l-0.8-3.2l1.7-1.5l0.4-2.2l-0.1-5l4.2-0.5l-2-1.7l-2.5-0.2l-3.5-4.5 l-3.4-3.2l0,0l-2.6,2.5l-0.5,1.5L1220.5,309.6L1220.5,309.6z' }, 'BS': { d: 'M574.4,437.3l0.2-0.6l-0.3-0.1l-0.5,0.7l-0.6,0.3h-0.3l-0.7-0.3h-0.5l-0.4,0.5l-0.6,0.1l0.1,0.1v0.2l-0.2,0.3v0.2 l0.1,0.3l1.5-0.1l1.3-0.2l0.7-0.9L574.4,437.3z M575.2,435.3l-0.4-0.3l-0.4,0.3l0.1,0.3L575.2,435.3L575.2,435.3z M575.2,429.5 l-0.4-0.2l-0.3,0.5l0.3,0.1l0.7-0.1l0.5,0.1l0.5,0.4l0.3-0.2l-0.1-0.1l-0.4-0.3l-0.6-0.1h-0.2L575.2,429.5L575.2,429.5z M568.6,430.8l0.7-0.6l0.7-0.3l0.9-1.1l-0.1-0.9l0.2-0.4l-0.6,0.1l-0.1,0.3l-0.1,0.3l0.3,0.4v0.2l-0.2,0.4l-0.3,0.1l-0.1,0.2 l-0.3,0.1l-0.4,0.5l-0.8,0.6l-0.2,0.3L568.6,430.8L568.6,430.8z M569.8,427.6l-0.6-0.2L569,427l-0.4-0.1l-0.1,0.2v0.2l0.1,0.4 l0.2-0.1l0.8,0.4l0.4-0.3L569.8,427.6z M565.7,426.5v-0.7l-0.4-0.5l-0.6-0.4l-0.1-1.2l-0.3-0.7l-0.2-0.6l-0.4-0.8v0.5l0.1,0.1 l0.1,0.6l0.4,0.9l0.1,0.4l-0.1,0.4l-0.4,0.1l-0.1,0.2l0.5,0.3l0.8,0.3l0.5,1.3L565.7,426.5L565.7,426.5z M561.6,423l-0.5-0.3 l-0.2-0.3l-0.7-0.7l-0.3-0.1l-0.2,0.4l0.4,0.1l0.9,0.7l0.4,0.2L561.6,423L561.6,423z M568.9,419l-0.1-0.3h-0.1l-0.3,0.1l-0.3,0.9 h0.3L568.9,419L568.9,419z M551.3,417.9l-0.2-0.3l-0.3,0.2h-0.5l-0.2,0.1h-0.4l-0.3,0.2l0.4,0.8l0.3,0.3l0.1,1l0.2,0.1l-0.1,0.7 l1.1,0.1l0.4-0.8V420v-0.1v-0.2v-0.2v-0.9l-0.3-0.5l-0.4,0.6l-0.4-0.3l0.6-0.4L551.3,417.9L551.3,417.9z M564.2,418.2l-1-1.4v-0.2 l-0.5-1.5l-0.3-0.1l-0.1,0.1l-0.1,0.2l0.4,0.4v0.4l0.3,0.2l0.4,1.1l0.4,0.4l-0.1,0.3l-0.4,0.3l-0.1,0.2h0.1l0.6-0.1h0.4L564.2,418.2 L564.2,418.2z M553.7,413l0.5-0.2l0,0l-0.3-0.2h-0.7l-0.4,0.1l-0.2,0.2l0.1,0.1l0.4,0.1L553.7,413L553.7,413z M551.3,415l-0.5-0.6 l-0.3-0.9l-0.2-0.4l0.1-0.5l-0.3-0.4l-0.6-0.4l-0.3,0.1l0.1,1.1l-0.2,0.6l-0.8,1.1l0.1,0.4l0,0l0.1,0.2l-0.5,0.4v-0.3l-0.6,0.1 l0.3,0.5l0.6,0.4l0.3,0.1l0.3-0.2v0.5l0.3,0.4l0.1,0.4l0.3-0.3l0.6-0.2l0.2-0.2l0.7-0.4v-0.2l0.1-0.6L551.3,415L551.3,415z M558,410 l-0.3-0.5l-0.1,0.1l-0.1,0.4l-0.3,0.4l0.5-0.1l0.4,0.1l0.6,0.5l0.7,0.2l0.3,0.6l0.6,0.6v0.6l-0.4,0.6l-0.1,0.7l-0.6,0.1l0.1,0.1 l0.3,0.3l0.1,0.4l0.2,0.2v-0.7l0.3-0.8l0.4-1.3l-0.1-0.3l-0.3-0.3l-0.7-0.9l-0.7-0.3L558,410L558,410z M549.2,402.1l-0.5-0.4 l-0.2,0.4v0.1l-0.1,0.3l-0.5,0.4l-0.5,0.1l-0.7-0.6l-0.2-0.1l0.8,1.1l0.3,0.1h0.4l0.9-0.3l1.6-0.5l1.7-0.2l0.1-0.2l-0.1-0.3 l-0.8,0.2l-1-0.1l-0.2,0.2h-0.4L549.2,402.1z M555.3,407.3l0.2-0.3l0.4-1.8l0.8-0.6l0.1-1.2l-0.5-0.5l-0.4-0.2l-0.1-0.2l0.1-0.2 l-0.2-0.1l-0.3-0.2l-0.4-0.6l-0.4-0.4l-0.7-0.1l-0.6-0.1l-0.4-0.1l-0.5,0.3h0.8l1.5,0.3l0.7,1.5l0.5,0.4l0.1,0.4l-0.2,0.4v0.4 l-0.3,0.5l-0.1,0.8l-0.3,0.4l-0.7,0.5l0.4,0.2l0.3,0.6L555.3,407.3L555.3,407.3z' }, 'BH': { d: 'M1253,408.3l0.7-3l-0.5-0.9l-1.6,1.2l0.6,0.9l-0.2,0.7L1253,408.3z' }, 'BD': { d: 'M1486.5,431.9l-4.5-10.1l-1.5,0.1l-0.2,4l-3.5-3.3l1.1-3.6l2.4-0.4l1.6-5.3l-3.4-1.1l-5,0.1l-5.4-0.9l-1.2-4.4 l-2.7-0.4l-4.8-2.7l-1.2,4.3l4.6,3.4l-3.1,2.4l-0.8,2.3l3.7,1.7l-0.4,3.8l2.6,4.8l1.6,5.2l2.2,0.6l1.7,0.7l0.6-1.2l2.5,1.3l1.3-3.5 l-0.9-2.6l5.1,0.2l2.8,3.7l1.5,3.1l0.8,3.2l2,3.3l-1.1-5.1l2.1,1L1486.5,431.9L1486.5,431.9z' }, 'BB': { d: 'M644.9,488.9l0.4-0.4l-0.3-0.3l-0.6-0.8l-0.3,0.1v1l0.1,0.3l0.5,0.3L644.9,488.9L644.9,488.9z' }, 'BY': { d: 'M1112.8,219.4l-5.2-1.5l-4.6,2.3l-2.6,1l0.9,2.6l-3.5,2l-0.5,3.4l-4.8,2.2h-4.6l0.6,2.7l1.7,2.3l0.3,2.4l-2.7,1.2 l1.9,2.9l0.5,2.7l2.2-0.3l2.4-1.6l3.7-0.2l5,0.5l5.6,1.5l3.8,0.1l2,0.9l1.6-1.1l1.5,1.5l4.3-0.3l2,0.6l-0.2-3.1l1.2-1.4l4.1-0.3l0,0 l-2-3.9l-1.5-2l0.8-0.6l3.9,0.2l1.6-1.3l-1.7-1.6l-3.4-1.1l0.1-1.1l-2.2-1.1l-3.7-3.9l0.6-1.6l-1-2.9l-4.8-1.4l-2.3,0.7 L1112.8,219.4L1112.8,219.4z' }, 'BE': { d: 'M1000.7,246.2l-4.4,1.3l-3.6-0.5l0,0l-3.8,1.2l0.7,2.2l2.2,0.1l2.4,2.4l3.4,2.9l2.5-0.4l4.4,2.8l0.4-3.5l1.3-0.2 l0.4-4.2l-2.8-1.4L1000.7,246.2L1000.7,246.2z' }, 'BZ': { d: 'M482.5,471.1l1.4-2.2l1-0.2l1.3-1.7l1-3.2l-0.3-0.6l0.9-2.3l-0.4-1l1.3-2.7l0.3-1.8h-1.1l0.1-0.9h-1l-2.5,3.9 l-0.9-0.8l-0.7,0.3l-0.1,1l-0.7,5l-1.2,7.2L482.5,471.1L482.5,471.1z' }, 'BJ': { d: 'M996.9,498l-4.3-3.7h-2l-1.9,1.9l-1.2,1.9l-2.7,0.6l-1.2,2.8l-1.9,0.7l-0.7,3.3l1.7,1.9l2,2.3l0.2,3.1l1.1,1.3 l-0.2,14.6l1.4,4.4l4.6-0.8l0.3-10.2L992,518l1-4l1.7-1.9l2.7-4l-0.6-1.7l1.1-2.5l-1.2-3.8L996.9,498L996.9,498z' }, 'BM': { d: 'M630.2,366.8l0.4-0.6h-0.1l-0.5,0.5l-0.6,0.2l0.1,0.1h0.1L630.2,366.8z' }, 'BT': { d: 'M1474.7,395.5l-2.7-1.8l-2.9-0.1l-4.2-1.5l-2.6,1.6l-2.6,4.8l0.3,1.2l5.5,2.5l3.2-1l4.7,0.4l4.4-0.2l-0.4-3.9 L1474.7,395.5L1474.7,395.5z' }, 'BO': { d: 'M655.7,700.5l1.6-1.3l-0.8-3.6l1.3-2.8l0.5-5l-1.6-4l-3.2-1.7l-0.8-2.6l0.6-3.6l-10.7-0.3l-2.7-7.4l1.6-0.1 l-0.3-2.8l-1.2-1.8l-0.5-3.7l-3.3-1.9l-3.5,0.1l-2.5-1.9l-3.8-1.2l-2.4-2.4l-6.3-1l-6.4-5.7l0.3-4.3l-0.9-2.5l0.4-4.7l-7.3,1.1 l-2.8,2.3l-4.8,2.6l-1.1,1.9l-2.9,0.2l-4.2-0.6l5.5,10.3l-1.1,2.1l0.1,4.5l0.3,5.4l-1.9,3.2l1.2,2.4l-1.1,2.1l2.8,5.3L591,684 l3.1,4.3l1.2,4.6l3.2,2.7l-1.1,6.2l3.7,7.1l3.1,8.8l3.8-0.9l4-5.7l7.4,1.5l3.7,4.6l1.6-5.1l6.3,0.3l1,1.3l1.5-7.6l-0.2-3.4l2.1-5.6 l9.5-1.9l5.1,0.1l5.4,3.3L655.7,700.5L655.7,700.5z' }, 'BA': { d: 'M1062.2,284.9l-2.3,0.1l-1,1.3l-1.9-1.4l-0.9,2.5l2.7,2.9l1.3,1.9l2.5,2.3l2,1.4l2.2,2.5l4.7,2.4l0.4-3.4l1.5-1.4 l0.9-0.6l1.2-0.3l0.5-2.9l-2.7-2.3l1-2.7h-1.8l0,0l-2.4-1.4l-3.5,0.1L1062.2,284.9L1062.2,284.9z' }, 'BW': { d: 'M1116.7,685l-1-0.5l-3.2,1.5h-1.6l-3.7,2.5l-2-2.6l-8.6,2.2l-4.1,0.2l-0.9,22.7l-5.4,0.2l-0.6,18.5l1.4,1l3,6.1 l-0.7,3.8l1.1,2.3l4-0.7l2.8-2.8l2.7-1.9l1.5-3.1l2.7-1.5l2.3,0.8l2.5,1.8l4.4,0.3l3.6-1.5l0.6-2l1.2-3l3-0.5l1.7-2.4l2-4.3l5.2-4.7 l8-4.7l-3.4-2.9l-4.2-0.9l-1.5-4.1l0.1-2.2l-2.3-0.7l-6-7l-1.6-3.7l-1.1-1.1L1116.7,685L1116.7,685z' }, 'BR': { d: 'M659,560.1l-1.4,0.2l-3.1-0.5l-1.8,1.7l-2.6,1.1l-1.7,0.2l-0.7,1.3l-2.7-0.3l-3.5-3l-0.3-2.9l-1.4-3.3l1-5.4 l1.6-2.2l-1.2-3l-1.9-0.9l0.8-2.8l-1.3-1.5l-2.9,0.3l0.7,1.8l-2.1,2.4l-6.4,2.4l-4,1l-1.7,1.5l-4.4-1.6l-4.2-0.8l-1,0.6l2.4,1.6 l-0.3,4.3l0.7,4l4.8,0.5l0.3,1.4l-4.1,1.8l-0.7,2.7l-2.3,1l-4.2,1.5l-1.1,1.9l-4.4,0.5l-3-3.4l-1.1,0.8l-1-3.8l-1.6-2l-1.9,2.2 l-10.9-0.1v3.9l3.3,0.7l-0.2,2.4l-1.1-0.6l-3.2,1v4.6l2.5,2.4l0.9,3.6l-0.1,2.8l-2.2,17.4l-5.1-0.3l-0.7,1l-4.6,1.2l-6.2,4.3l-0.4,3 l-1.3,2.2l0.7,3.4l-3.3,1.9l0.1,2.7L562,620l2.6,5.8l3.3,3.8l-1,2.8l3.7,0.3l2.3,3.4l4.9,0.2l4.4-3.8l0.2,9.7l2.6,0.7l3-1.1l4.2,0.6 l2.9-0.2l1.1-1.9l4.8-2.6l2.8-2.3l7.3-1.1l-0.4,4.7l0.9,2.5l-0.3,4.3l6.4,5.7l6.3,1l2.4,2.4l3.8,1.2l2.5,1.9l3.5-0.1l3.3,1.9 l0.5,3.7l1.2,1.8l0.3,2.8l-1.6,0.1l2.7,7.4l10.7,0.3l-0.6,3.6l0.8,2.6l3.2,1.7l1.6,4l-0.5,5l-1.3,2.8l0.8,3.6l-1.6,1.3l1.9,3.6 l0.4,8.6l6,1.2l2.1-1.2l3.9,1.7l1.2,1.9l1,5.8l0.9,2.5l2,0.3l2-1.1l2.1,1.2l0.3,3.5l-0.3,3.8l-0.7,3.6l2.6-1.2l3.1,3.7l0.5,5.1 l-4.2,3.5l-3.3,2.6l-5.3,6.2l-5.9,8.6l3.4-0.7l6.2,4.9l1.9-0.2l6.2,4.1l4.8,3.5l3.8,4.3l-1.9,3l2.1,3.7l2.9-3.7l1.5-6l3.2-3l3.9-5 l4.5-11.2l3.4-3.5l0.8-3.1l0.3-6.4l-1.3-3.5l0.3-4.8l4.1-6.3l6-5.1l6-1.8l3.6-2.9l8.5-2.4h5.9l1.1-3.8l4.2-2.8l0.6-6.5l5.1-8.3 l0.5-8.5l1.6-2.6l0.3-4.1l1.1-9.9l-1-11.9l1.4-4.7l1.4-0.1l3.9-5.5l3.3-7.2l7.7-8.8l2.7-4.2l2-10.5l-1-3.9l-2-8.1l-2.1-2l-4.8-0.2 l-4.3-1.9l-7.3-7.1l-8.4-5.3l-8.4,0.3l-10.9-3.4l-6.5,2l0.8-3.5l-2.7-3.8l-9.4-3.8l-7.1-2.3l-4.2,4.1l-0.3-6.3l-9.9-1l-1.7-2 l4.2-5.2l-0.1-4.4l-3-1l-3-11.2l-1.3-3.5l-1.9,0.3l-3.5,5.8l-1.8,4.7l-2.1,2.4l-2.7,0.5l-0.8-1.8l-1.2-0.3l-1.8,1.8l-2.4-1.3 l-3.2-1.4l-2.7,0.7l-2.3-0.6l-0.5,1.8l0.9,1.3l-0.5,1.3L659,560.1L659,560.1z' }, 'VG': { d: 'M619.2,455.1l0.3-0.2l-0.2-0.1h-0.4l-0.3,0.2l0.1,0.1H619.2L619.2,455.1z M620.3,454.7l0.4-0.4l-0.5,0.1l-0.2,0.2 l0.1,0.1h0.1L620.3,454.7L620.3,454.7z M621.1,452.9h-0.2h-0.5l0,0l0.1,0.1h0.3l0.3,0.1l0,0L621.1,452.9L621.1,452.9z' }, 'BN': { d: 'M1617.8,543.4l2.7,3.3l1.1-2.2l2.7,0.2l0.1-4.1l0.1-3.1l-4.6,3.5L1617.8,543.4L1617.8,543.4z' }, 'BG': { d: 'M1121.6,294.3l-3-0.7l-4-2.2l-5.8,1.4l-2.3,1.6l-7.5-0.3l-4-1l-1.9,0.5l-1.8-2.6l-1.1,1.4l0.7,2.3l2.8,2.6l-1.7,1.9 l-0.7,2l0.6,0.7l-0.7,0.9l2.8,2l0.8,4.1l3.8,0.2l3.9-1.7l3.9,2.1l4.6-0.6l-0.3-3l5-2l4.5,0.8l-2.1-3.5l1.3-4.4L1121.6,294.3 L1121.6,294.3z' }, 'BF': { d: 'M978.8,477.2h-3.6l-1.4-1.2l-3,0.9l-5.2,2.6l-1.1,2l-4.3,2.9l-0.8,1.6l-2.3,1.3l-2.7-0.9l-1.6,1.6l-0.8,4.4 l-4.5,5.2l0.2,2.2l-1.6,2.7l0.4,3.7l2.5,1.4l1,2.1l2.5,1.3l1.9-1.6l2.7-0.2l3.8,1.6l-0.8-4.8l0.2-3.6l9.7-0.3l2.4,0.5l1.8-1l2.6,0.5 l4.9,0.1l1.9-0.7l1.2-2.8l2.7-0.6l1.2-1.9l0.1-4.4l-6.4-1.4l-0.2-3.1l-3.1-4.1l-0.8-2.9L978.8,477.2L978.8,477.2z' }, 'BI': { d: 'M1148.2,590l-0.3-2.5l0,0l-3-0.4l-1.7,3.6l-3.5-0.5l1.4,2.9l0.1,1.1l2,6.1l-0.1,0.3l0.6-0.1l2.1-2.3l2.2-3.3 l1.4-1.4v-2L1148.2,590L1148.2,590z' }, 'KH': { d: 'M1574.8,481.8l-5.2-2.3l-2,4.3l-4.9-2.4l-5.3-1l-7.1,1.3l-3,5.2l2.1,7.7l3.4,6.6l2.6,3.3l4.7,0.9l4.7-2.5l5.8-0.5 l-2.8-3.8l8.9-4.9l-0.1-7.7L1574.8,481.8L1574.8,481.8z' }, 'CM': { d: 'M1060.1,502.9l0.2-4.3l-0.5-4.2l-2.2-4.1l-1.6,0.4l-0.2,2l2.3,2.6l-0.6,1.1l-0.3,2.1l-4.6,5l-1.5,4l-0.7,3.3 l-1.2,1.4l-1.1,4.5l-3,2.6l-0.8,3.2l-1.2,2.6l-0.5,2.6l-3.9,2.2l-3.2-2.6l-2.1,0.1l-3.3,3.7l-1.6,0.1l-2.7,6.1l-1.4,4.5v1.8l1.4,0.9 l1.1,2.8l2.6,1.1l2.2,4.2l-0.8,5l9.2,0.2l2.6-0.4l3.4,0.8l3.4-0.8l0.7,0.3l7.1,0.3l4.5,1.7l4.5,1.5l0.4-3.5l-0.6-1.8l-0.3-2.9 l-2.6-2.1l-2.1-3.2l-0.5-2.3l-2.6-3.3l0.4-1.