The source of World's administrative divisions.
This is a module designed for:
Each time you want to display borders - use the regions, Luke.
Runs on top of information from OpenStreetMap, Wikipedia, GeoNames, eSosedi and some other sources.
Created for and used by esosedi.org project - one of largest cartographical site in the World.
import osme from 'osme';
or
<script src="https://unpkg.com/osme"></script>
// use window.osme
There is only 2 primary commands:
Plus we include build-in wrappers for Yandex Maps API, Google Maps API and Leaflet.
osme.toLeaflet(geoJson)
All collections will have interface of .add .remove .setStyles .addEvent .removeEvent.
Result it very simple - you can display any continent, country or state on a map.
The module consists in two parts, and this part is a client side.
It does not contain any data, always striming it from the server side at data.esosedi.org.
Server-side also implements online navigator
via database to help you find proper place.
So, you can load:
world
- all countries of the World.number
- as a OpenStreetMap RelationID. Ie - you can get contour of USA using US
or 148838
, there is no difference.And check /examples folder!
import osmeRegions from 'osme';
osme.geoJSON('FR').then( geojson => osme.toGoogle(geojson).add(map));
A bit bigger one:
// ask for some region
osme.geoJSON('US'/*addr*/, {lang: 'de'}, function (data) {
// data is pure GEOJSON
// you can create some helpers
var yandexGeoObjectColletionWrapper = osme.toYandex(data);
// or
var googleDataWrapper = osme.toGoogle(data);
// or
var leafletDataWrapper = osme.toLeaflet(data);
// call .add to add data into the map
yandexGeoObjectColletionWrapper.add(map);
// call .remove to remove
googleDataWrapper.remove();
// call setStyles to setup styles
leafletDataWrapper.setStyles(jsonFeatureIn => {
return styleOptions
});
// And you also can control events.
*.addEvent(event,function(feature, apiType, apiObject, apiEvent){});
*.removeEvent();
})
// PS: OR you can use geoJSON as geoJSON. With out helpers
new L.geoJson(data).addTo(map);
osme.geoJSON(addr, options, callback)
Where:
addr
is OSM RelationId, ISO3166-2 code(US/DE/GB or RU-MOS/US-TX etc, or world's region name
options
is a object of { lang, quality, type, nocache, postFilter, recombine, scheme }. All are optional.
- lang - prefered language (en,de,ru)
- quality – set 0 to get geomentry for fullHD resolution. -1,0,+1,+2 for /4, x1, x4, x16 quality.
- type - null|'coast'.
- null to get `raw` `maritime` administrative borders, including terrotorial water.
- "coast", to cut off coast lines.
- nocache - turns of internal client-side cache
- postFilter, recombine, scheme - to be used only by advanced users.
If you dont know relationId(addr
) for region you need, you can:
Type coast will return information you want - pretty borders. Very hi-detailed borders. Here is comparison between borders for Greece with and without maritime. Greece Difference - 154kb versus 251.
Information available for ~300k regions in 3 languages(en, de, ru) and some secret modes.
This module uses CORS to transport JSON via different hosts.
You can store geojson produced by this module, or cache packed json files from orinal data endpoint.
Just change data-endpoint by executing osme.setHost
command.
Data format is quite simple and compact. It is look like topojson, but more "binary" and contains data like schemes etc. After all you will get standard geoJSON. You can use it by your own risk.
More Examples:
// request Moscow
osme.geoJSON('RU-MOW', {lang: 'ru'}, function (data) {
var collection = osme.toYandex(data, ymaps);
collection.add(geoMap);
geoMap.setBounds(collection.collection.getBounds(), {duration: 300});
var strokeColors = [
'#000',
'#F0F',
'#00F',
'#0FF',
];
var meta = data.metaData,
maxLevel = meta.levels[1] + 1;
// colorize the collection
collection.setStyles(function (object, yobject) {
var level = object.properties.level;
return ({
zIndex: level,
zIndexHover: level,
strokeWidth: Math.max(1, level == 2 ? 2 : (maxLevel - level)),
strokeColor: strokeColors[maxLevel - level] || '#000',
fillColor: '#FFE2',
});
});
You can do anything like country coloring (http://jsfiddle.net/9o9ak7fb/18/), or making "old" Moscow (http://jsfiddle.net/9o9ak7fb/17/). OSMe provide geo data, you provide logic.
var countryColors={
'CA': "F00",
'IN': "0F0",
'US': "00F",
'RU': "F0F"
};
function setColors(collection, countryColors){
// You know this function
collection.setStyles(function (object) {
// get ISO counry code and color it
var iso = (object.properties.properties.iso3166 ||'').toUpperCase(),
color=countryColors[iso];
return ({
strokeWidth: 1,
strokeColor: color?'#000':"666",
fillColor: color || 'EEE',
visible: !!color
});
});
}
//...
osme.geoJSON('world',{}).then(data => {
const collection = osme.toGoogle(data);
setColors(collection, countryColors);
collection.add(map);
});
//any event - click, dblclick and so on.
const event = collection.addEvent('dblclick', function (object, type, target, event) {
// object - object itself
// type – [eventName, provider('yandex','google')]
// target – Maps API`s feature (polygon)
// event – original event
event.preventDefault();
});
collection.removeEvent(event);
And what about boundary dispute? Crimea, Kosovo, etc..
Recall strange parameter in options, field named recombine
. This is not about boundaries, this is about recombination.
It is almost as language - en-US, or en-GB..
See disputed-borders.html in /examples.
Recombination allow you to create new geometry by combination of others.
For example something from internal cuisine - this code included in world.json file, and executed automatically
{
disputedBorders: {
ru: {
60199/*UA*/: 'return region.hasParent(60199) && region.osmId != 72639 && region.osmId != 1574364 && region.osmId!=421866;',
60189/*RU*/: 'return !region.hasParent(60189) && (region.osmId == 60189 || region.osmId == 72639 || region.osmId == 1574364)',
}
},
postFilter: 'return !region.hasParent(60199);', //remove UA*
}
What this function do - it generates Ukraine without Crimea, or Russia with.
You can set options.recombine to a string ('ru' in this example) to select desired scheme, or set new scheme object.
By the same way you can join SJ to NO or GF to FR (one will understand).
You can create Merica by joining US to CA and MX or create EuroUnion.
The difference between recombination and just displaying everything you need -
the result of recombination is borderless
. You will get not a pack of shapes, but BIG one.
Recombination can be used to join any set of regions in one. This is usefull in many cases.
osme.geoJSON('349035', {lang: 'en'}, function (data, pureData) {
var coords=osme.recombine(pureData, { // yes, you can use pure data
filter: function (region) {
// somethere in Province of Barcelona (349035) and Barcelona(2417889) or adjacent
// remember - you have to discard #349035 or you got duplicate.
return region.hasParent(349035) && (region.hasBorderWith(2417889) || region.osmId == 2417889);
}
});
for(var j in coords.coordinates) {
var region = new ymaps.GeoObject({
geometry: {
type: 'Polygon',
fillRule: 'nonZero',
coordinates: osme.flipCoordinate([coords.coordinates[j]])
}
}, {
opacity: 0.8,
fillColor: 'FEE',
strokeColor: 'F00',
strokeWidth: 2,
pixelRendering: 'static',
draggable: true
});
geoMap.geoObjects.add(region);
}
}
And you got mini Barcelona
Where is also exists options.scheme - yet another recombination function. It also sometimes exists in source geoJSON file. The goal still simple - some regions lays on the top of other, and do not have adjacent borders - Kiev, for example, and Kiev province. Scheme just adds "hole" to province.
You dont need to understand all of this - just use.
contain errors
, holes in data and mistakes.Cheers, Kashey.