Merge pull request #366 from Freika/feature/scratch_map

Scratch map
This commit is contained in:
Evgenii Burmakin 2024-11-01 18:18:40 +01:00 committed by GitHub
commit cf5ebae5ae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 591 additions and 4 deletions

View file

@ -1 +1 @@
0.15.11
0.15.12

View file

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
# 0.15.12 - 2024-11-01
### Added
- Scratch map. You can enable it in the map controls. The scratch map highlight countries you've visited. The scratch map is working properly only if you have your points reverse geocoded.
# 0.15.11 - 2024-10-29
### Added

File diff suppressed because one or more lines are too long

View file

@ -8,8 +8,8 @@ class MapController < ApplicationController
@countries_and_cities = CountriesAndCities.new(@points).call
@coordinates =
@points.pluck(:latitude, :longitude, :battery, :altitude, :timestamp, :velocity, :id)
.map { [_1.to_f, _2.to_f, _3.to_s, _4.to_s, _5.to_s, _6.to_s, _7.to_s] }
@points.pluck(:latitude, :longitude, :battery, :altitude, :timestamp, :velocity, :id, :country)
.map { [_1.to_f, _2.to_f, _3.to_s, _4.to_s, _5.to_s, _6.to_s, _7.to_s, _8.to_s] }
@distance = distance
@start_at = Time.zone.at(start_at)
@end_at = Time.zone.at(end_at)

View file

@ -21,6 +21,7 @@ import { esriWorldStreetMapLayer } from "../maps/layers";
import { esriWorldTopoMapLayer } from "../maps/layers";
import { esriWorldImageryMapLayer } from "../maps/layers";
import { esriWorldGrayCanvasMapLayer } from "../maps/layers";
import { countryCodesMap } from "../maps/country_codes";
import "leaflet-draw";
@ -41,6 +42,7 @@ export default class extends Controller {
this.routeOpacity = parseFloat(this.userSettings.route_opacity) || 0.6;
this.distanceUnit = this.element.dataset.distance_unit || "km";
this.pointsRenderingMode = this.userSettings.points_rendering_mode || "raw";
this.countryCodesMap = countryCodesMap();
this.center = this.markers[this.markers.length - 1] || [52.514568, 13.350111];
@ -61,6 +63,7 @@ export default class extends Controller {
this.heatmapLayer = L.heatLayer(this.heatmapMarkers, { radius: 20 }).addTo(this.map);
this.fogOverlay = L.layerGroup(); // Initialize fog layer
this.areasLayer = L.layerGroup(); // Initialize areas layer
this.setupScratchLayer(this.countryCodesMap);
if (!this.settingsButtonAdded) {
this.addSettingsButton();
@ -71,6 +74,7 @@ export default class extends Controller {
Polylines: this.polylinesLayer,
Heatmap: this.heatmapLayer,
"Fog of War": this.fogOverlay,
"Scratch map": this.scratchLayer,
Areas: this.areasLayer // Add the areas layer to the controls
};
@ -140,6 +144,68 @@ export default class extends Controller {
this.map.remove();
}
async setupScratchLayer(countryCodesMap) {
this.scratchLayer = L.geoJSON(null, {
style: {
fillColor: '#FFD700',
fillOpacity: 0.3,
color: '#FFA500',
weight: 1
}
})
try {
// Up-to-date version can be found on Github:
// https://raw.githubusercontent.com/datasets/geo-countries/master/data/countries.geojson
const response = await fetch('/countries.geojson', {
headers: {
'Accept': 'application/geo+json,application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const worldData = await response.json();
const visitedCountries = this.getVisitedCountries(countryCodesMap)
const filteredFeatures = worldData.features.filter(feature =>
visitedCountries.includes(feature.properties.ISO_A2)
)
this.scratchLayer.addData({
type: 'FeatureCollection',
features: filteredFeatures
})
} catch (error) {
console.error('Error loading GeoJSON:', error);
}
}
getVisitedCountries(countryCodesMap) {
if (!this.markers) return [];
return [...new Set(
this.markers
.filter(marker => marker[7]) // Ensure country exists
.map(marker => {
// Convert country name to ISO code, or return the original if not found
return countryCodesMap[marker[7]] || marker[7];
})
)];
}
// Optional: Add methods to handle user interactions
toggleScratchLayer() {
if (this.map.hasLayer(this.scratchLayer)) {
this.map.removeLayer(this.scratchLayer)
} else {
this.scratchLayer.addTo(this.map)
}
}
baseMaps() {
let selectedLayerName = this.userSettings.preferred_map_layer || "OpenStreetMap";

View file

@ -0,0 +1,246 @@
export function countryCodesMap() {
return {
"Afghanistan": "AF",
"Aland Islands": "AX",
"Albania": "AL",
"Algeria": "DZ",
"AmericanSamoa": "AS",
"Andorra": "AD",
"Angola": "AO",
"Anguilla": "AI",
"Antarctica": "AQ",
"Antigua and Barbuda": "AG",
"Argentina": "AR",
"Armenia": "AM",
"Aruba": "AW",
"Australia": "AU",
"Austria": "AT",
"Azerbaijan": "AZ",
"Bahamas": "BS",
"Bahrain": "BH",
"Bangladesh": "BD",
"Barbados": "BB",
"Belarus": "BY",
"Belgium": "BE",
"Belize": "BZ",
"Benin": "BJ",
"Bermuda": "BM",
"Bhutan": "BT",
"Bolivia, Plurinational State of": "BO",
"Bosnia and Herzegovina": "BA",
"Botswana": "BW",
"Brazil": "BR",
"British Indian Ocean Territory": "IO",
"Brunei Darussalam": "BN",
"Bulgaria": "BG",
"Burkina Faso": "BF",
"Burundi": "BI",
"Cambodia": "KH",
"Cameroon": "CM",
"Canada": "CA",
"Cape Verde": "CV",
"Cayman Islands": "KY",
"Central African Republic": "CF",
"Chad": "TD",
"Chile": "CL",
"China": "CN",
"Christmas Island": "CX",
"Cocos (Keeling) Islands": "CC",
"Colombia": "CO",
"Comoros": "KM",
"Congo": "CG",
"Congo, The Democratic Republic of the Congo": "CD",
"Cook Islands": "CK",
"Costa Rica": "CR",
"Cote d'Ivoire": "CI",
"Croatia": "HR",
"Cuba": "CU",
"Cyprus": "CY",
"Czech Republic": "CZ",
"Denmark": "DK",
"Djibouti": "DJ",
"Dominica": "DM",
"Dominican Republic": "DO",
"Ecuador": "EC",
"Egypt": "EG",
"El Salvador": "SV",
"Equatorial Guinea": "GQ",
"Eritrea": "ER",
"Estonia": "EE",
"Ethiopia": "ET",
"Falkland Islands (Malvinas)": "FK",
"Faroe Islands": "FO",
"Fiji": "FJ",
"Finland": "FI",
"France": "FR",
"French Guiana": "GF",
"French Polynesia": "PF",
"Gabon": "GA",
"Gambia": "GM",
"Georgia": "GE",
"Germany": "DE",
"Ghana": "GH",
"Gibraltar": "GI",
"Greece": "GR",
"Greenland": "GL",
"Grenada": "GD",
"Guadeloupe": "GP",
"Guam": "GU",
"Guatemala": "GT",
"Guernsey": "GG",
"Guinea": "GN",
"Guinea-Bissau": "GW",
"Guyana": "GY",
"Haiti": "HT",
"Holy See (Vatican City State)": "VA",
"Honduras": "HN",
"Hong Kong": "HK",
"Hungary": "HU",
"Iceland": "IS",
"India": "IN",
"Indonesia": "ID",
"Iran, Islamic Republic of Persian Gulf": "IR",
"Iraq": "IQ",
"Ireland": "IE",
"Isle of Man": "IM",
"Israel": "IL",
"Italy": "IT",
"Jamaica": "JM",
"Japan": "JP",
"Jersey": "JE",
"Jordan": "JO",
"Kazakhstan": "KZ",
"Kenya": "KE",
"Kiribati": "KI",
"Korea, Democratic People's Republic of Korea": "KP",
"Korea, Republic of South Korea": "KR",
"Kuwait": "KW",
"Kyrgyzstan": "KG",
"Laos": "LA",
"Latvia": "LV",
"Lebanon": "LB",
"Lesotho": "LS",
"Liberia": "LR",
"Libyan Arab Jamahiriya": "LY",
"Liechtenstein": "LI",
"Lithuania": "LT",
"Luxembourg": "LU",
"Macao": "MO",
"Macedonia": "MK",
"Madagascar": "MG",
"Malawi": "MW",
"Malaysia": "MY",
"Maldives": "MV",
"Mali": "ML",
"Malta": "MT",
"Marshall Islands": "MH",
"Martinique": "MQ",
"Mauritania": "MR",
"Mauritius": "MU",
"Mayotte": "YT",
"Mexico": "MX",
"Micronesia, Federated States of Micronesia": "FM",
"Moldova": "MD",
"Monaco": "MC",
"Mongolia": "MN",
"Montenegro": "ME",
"Montserrat": "MS",
"Morocco": "MA",
"Mozambique": "MZ",
"Myanmar": "MM",
"Namibia": "NA",
"Nauru": "NR",
"Nepal": "NP",
"Netherlands": "NL",
"Netherlands Antilles": "AN",
"New Caledonia": "NC",
"New Zealand": "NZ",
"Nicaragua": "NI",
"Niger": "NE",
"Nigeria": "NG",
"Niue": "NU",
"Norfolk Island": "NF",
"Northern Mariana Islands": "MP",
"Norway": "NO",
"Oman": "OM",
"Pakistan": "PK",
"Palau": "PW",
"Palestinian Territory, Occupied": "PS",
"Panama": "PA",
"Papua New Guinea": "PG",
"Paraguay": "PY",
"Peru": "PE",
"Philippines": "PH",
"Pitcairn": "PN",
"Poland": "PL",
"Portugal": "PT",
"Puerto Rico": "PR",
"Qatar": "QA",
"Romania": "RO",
"Russia": "RU",
"Rwanda": "RW",
"Reunion": "RE",
"Saint Barthelemy": "BL",
"Saint Helena, Ascension and Tristan Da Cunha": "SH",
"Saint Kitts and Nevis": "KN",
"Saint Lucia": "LC",
"Saint Martin": "MF",
"Saint Pierre and Miquelon": "PM",
"Saint Vincent and the Grenadines": "VC",
"Samoa": "WS",
"San Marino": "SM",
"Sao Tome and Principe": "ST",
"Saudi Arabia": "SA",
"Senegal": "SN",
"Serbia": "RS",
"Seychelles": "SC",
"Sierra Leone": "SL",
"Singapore": "SG",
"Slovakia": "SK",
"Slovenia": "SI",
"Solomon Islands": "SB",
"Somalia": "SO",
"South Africa": "ZA",
"South Sudan": "SS",
"South Georgia and the South Sandwich Islands": "GS",
"Spain": "ES",
"Sri Lanka": "LK",
"Sudan": "SD",
"Suriname": "SR",
"Svalbard and Jan Mayen": "SJ",
"Swaziland": "SZ",
"Sweden": "SE",
"Switzerland": "CH",
"Syrian Arab Republic": "SY",
"Taiwan": "TW",
"Tajikistan": "TJ",
"Tanzania, United Republic of Tanzania": "TZ",
"Thailand": "TH",
"Timor-Leste": "TL",
"Togo": "TG",
"Tokelau": "TK",
"Tonga": "TO",
"Trinidad and Tobago": "TT",
"Tunisia": "TN",
"Turkey": "TR",
"Turkmenistan": "TM",
"Turks and Caicos Islands": "TC",
"Tuvalu": "TV",
"Uganda": "UG",
"Ukraine": "UA",
"United Arab Emirates": "AE",
"United Kingdom": "GB",
"United States": "US",
"Uruguay": "UY",
"Uzbekistan": "UZ",
"Vanuatu": "VU",
"Venezuela, Bolivarian Republic of Venezuela": "VE",
"Vietnam": "VN",
"Virgin Islands, British": "VG",
"Virgin Islands, U.S.": "VI",
"Wallis and Futuna": "WF",
"Yemen": "YE",
"Zambia": "ZM",
"Zimbabwe": "ZW"
}
}

View file

@ -6,6 +6,7 @@ export function createMarkersArray(markersData, userSettings) {
} else {
return markersData.map((marker) => {
const [lat, lon] = marker;
const popupContent = createPopupContent(marker, userSettings.timezone, userSettings.distanceUnit);
return L.circleMarker([lat, lon], { radius: 4 }).bindPopup(popupContent);
});

View file

@ -64,6 +64,10 @@ Rails.application.configure do
# Suppress logger output for asset requests.
config.assets.quiet = true
config.assets.content_type = {
geojson: 'application/geo+json'
}
# Raises error for missing translations.
# config.i18n.raise_on_missing_translations = true

View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
Mime::Type.register 'application/geo+json', :geojson

261
public/countries.geojson Normal file

File diff suppressed because one or more lines are too long