Compare commits
No commits in common. "maplibre" and "master" have entirely different histories.
16 changed files with 274 additions and 1180 deletions
|
|
@ -1,13 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>World Map with Countries</title>
|
|
||||||
<meta http-equiv="Keywords" content="Lists"/>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
|
||||||
<link rel="shortcut icon" type="image/png" href="../../../source/UI/themes/oxlight/png/icon16.png"/>
|
|
||||||
<script type="text/javascript" src="../../../dev/Ox.js"></script>
|
|
||||||
<script type="text/javascript" src="js/example.js"></script>
|
|
||||||
<script>window.addEventListener('message', function(e) { e.origin == window.location.origin && eval('(' + e.data + ')'); });</script>
|
|
||||||
</head>
|
|
||||||
<body></body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
/*
|
|
||||||
In this example, we use Ox.MapEditor
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
Ox.load(['UI', 'Geo'], function() {
|
|
||||||
var $storage = Ox.localStorage("map_editor")
|
|
||||||
var places = $storage('places') || []
|
|
||||||
var placesAPI = Ox.api(places, {
|
|
||||||
geo: true,
|
|
||||||
sort: '-area',
|
|
||||||
cache: true,
|
|
||||||
})
|
|
||||||
var $map = Ox.MapEditor({
|
|
||||||
addPlace: function(place, callback) {
|
|
||||||
place = Ox.clone(place)
|
|
||||||
place.id = Ox.encodeBase26((places.length ? Ox.max(places.map(p => Ox.decodeBase26(p.id))) : 0) + 1)
|
|
||||||
place.editable = true;
|
|
||||||
console.log("addPlace", place.id, place)
|
|
||||||
places.push(place)
|
|
||||||
$storage("places", places)
|
|
||||||
placesAPI.update(places)
|
|
||||||
setTimeout(() => {
|
|
||||||
Ox.Request.clearCache();
|
|
||||||
callback({
|
|
||||||
status: {
|
|
||||||
code: 200
|
|
||||||
},
|
|
||||||
data: place
|
|
||||||
})
|
|
||||||
}, 200)
|
|
||||||
},
|
|
||||||
editPlace: function(place, callback) {
|
|
||||||
place = Ox.clone(place)
|
|
||||||
places.forEach(p => {
|
|
||||||
if (p.id == place.id) {
|
|
||||||
Object.assign(p, place);
|
|
||||||
place = p
|
|
||||||
}
|
|
||||||
})
|
|
||||||
$storage("places", places)
|
|
||||||
placesAPI.update(places)
|
|
||||||
setTimeout(() => {
|
|
||||||
Ox.Request.clearCache();
|
|
||||||
callback({
|
|
||||||
status: {
|
|
||||||
code: 200
|
|
||||||
},
|
|
||||||
data: place
|
|
||||||
})
|
|
||||||
}, 200)
|
|
||||||
},
|
|
||||||
getMatches: function(names, callback) {
|
|
||||||
console.log("getMatches", names)
|
|
||||||
callback(23);
|
|
||||||
},
|
|
||||||
hasMatches: true, // FIXME: getMatches is enough
|
|
||||||
height: 800,
|
|
||||||
mode: 'add', // 'define',
|
|
||||||
names: null,
|
|
||||||
places: placesAPI,
|
|
||||||
removePlace: function(place, callback) {
|
|
||||||
console.log("removePlace", place.id, places)
|
|
||||||
places = places.filter(p => { return p.id != place.id })
|
|
||||||
console.log("new places", places)
|
|
||||||
$storage("places", places)
|
|
||||||
placesAPI.update(places)
|
|
||||||
setTimeout(() => {
|
|
||||||
Ox.Request.clearCache();
|
|
||||||
callback({
|
|
||||||
status: {
|
|
||||||
code: 200
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}, 200)
|
|
||||||
},
|
|
||||||
selected: '',
|
|
||||||
showControls: false,
|
|
||||||
showLabels: false,
|
|
||||||
showTypes: true,
|
|
||||||
width: 600
|
|
||||||
})
|
|
||||||
.appendTo(Ox.$body);
|
|
||||||
|
|
||||||
Ox.$window.bind({resize: $map.resizeMap});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<meta http-equiv="Keywords" content="Lists"/>
|
<meta http-equiv="Keywords" content="Lists"/>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
<link rel="shortcut icon" type="image/png" href="../../../source/UI/themes/oxlight/png/icon16.png"/>
|
<link rel="shortcut icon" type="image/png" href="../../../source/UI/themes/oxlight/png/icon16.png"/>
|
||||||
<script type="text/javascript" src="../../../dev/Ox.js"></script>
|
<script type="text/javascript" src="../../../min/Ox.js"></script>
|
||||||
<script type="text/javascript" src="js/example.js"></script>
|
<script type="text/javascript" src="js/example.js"></script>
|
||||||
<script>window.addEventListener('message', function(e) { e.origin == window.location.origin && eval('(' + e.data + ')'); });</script>
|
<script>window.addEventListener('message', function(e) { e.origin == window.location.origin && eval('(' + e.data + ')'); });</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
||||||
|
|
@ -1800,7 +1800,6 @@ Maps
|
||||||
.OxMap .OxLabel.OxMapControl.OxMapScale {
|
.OxMap .OxLabel.OxMapControl.OxMapScale {
|
||||||
right: 4px;
|
right: 4px;
|
||||||
bottom: 19px;
|
bottom: 19px;
|
||||||
line-height: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.OxMap .OxPlaceControl.OxPlaceFlag {
|
.OxMap .OxPlaceControl.OxPlaceFlag {
|
||||||
|
|
@ -1822,7 +1821,6 @@ Maps
|
||||||
top: 4px;
|
top: 4px;
|
||||||
width: 136px;
|
width: 136px;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
line-height: 1;
|
|
||||||
}
|
}
|
||||||
.OxMap .OxPlaceControl.OxPlaceDeselectButton {
|
.OxMap .OxPlaceControl.OxPlaceDeselectButton {
|
||||||
right: 4px;
|
right: 4px;
|
||||||
|
|
@ -2971,20 +2969,3 @@ Miscellaneous
|
||||||
.OxTooltip > div {
|
.OxTooltip > div {
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
================================================================================
|
|
||||||
MapLibre GL cleanups
|
|
||||||
================================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
.maplibregl-popup-anchor-bottom .maplibregl-popup-tip {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-popup-content {
|
|
||||||
padding: 0px !important;
|
|
||||||
border-radius: 5px;
|
|
||||||
top: 50px;
|
|
||||||
left: -4px;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,6 @@ Ox.Map = function(options, self) {
|
||||||
return place.name || '<span class="OxLight">Unnamed</span>';
|
return place.name || '<span class="OxLight">Unnamed</span>';
|
||||||
},
|
},
|
||||||
maxMarkers: 100,
|
maxMarkers: 100,
|
||||||
nominatim: 'https://nominatim.openstreetmap.org',
|
|
||||||
places: null,
|
places: null,
|
||||||
selected: '',
|
selected: '',
|
||||||
showControls: false,
|
showControls: false,
|
||||||
|
|
@ -107,7 +106,6 @@ Ox.Map = function(options, self) {
|
||||||
showStatusbar: false,
|
showStatusbar: false,
|
||||||
showToolbar: false,
|
showToolbar: false,
|
||||||
showZoombar: false,
|
showZoombar: false,
|
||||||
style: 'https://tiles.openfreemap.org/styles/liberty',
|
|
||||||
zoomOnlyWhenFocused: false
|
zoomOnlyWhenFocused: false
|
||||||
// fixme: width, height
|
// fixme: width, height
|
||||||
})
|
})
|
||||||
|
|
@ -145,7 +143,7 @@ Ox.Map = function(options, self) {
|
||||||
self.map.fitBounds(mapBounds);
|
self.map.fitBounds(mapBounds);
|
||||||
} else {
|
} else {
|
||||||
self.map.setZoom(self.minZoom);
|
self.map.setZoom(self.minZoom);
|
||||||
self.map.setCenter(new maplibregl.LngLat(0, 0));
|
self.map.setCenter(new google.maps.LatLng(0, 0));
|
||||||
}
|
}
|
||||||
// fixme: the following is just a guess
|
// fixme: the following is just a guess
|
||||||
self.boundsChanged = true;
|
self.boundsChanged = true;
|
||||||
|
|
@ -511,27 +509,23 @@ Ox.Map = function(options, self) {
|
||||||
$placeControl.css({opacity: 0}).hide();
|
$placeControl.css({opacity: 0}).hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (window.maplibregl) {
|
if (window.google) {
|
||||||
// timeout needed so that the map is in the DOM
|
// timeout needed so that the map is in the DOM
|
||||||
setTimeout(initMap);
|
setTimeout(initMap);
|
||||||
|
} else if (window.googleCallback) {
|
||||||
|
(function interval() {
|
||||||
|
isLoaded() ? initMap() : setTimeout(interval, 100);
|
||||||
|
}());
|
||||||
} else {
|
} else {
|
||||||
Ox.getStylesheet([
|
window.googleCallback = function() {
|
||||||
Ox.PATH + 'UI/maplibre-gl/maplibre-gl.css',
|
delete window.googleCallback;
|
||||||
Ox.PATH + 'UI/maplibre-gl/maplibre-gl-geocoder.css'
|
initMap();
|
||||||
], () => {})
|
};
|
||||||
$.getScript([
|
$.getScript(
|
||||||
Ox.PATH + 'UI/maplibre-gl/maplibre-gl.js',
|
document.location.protocol
|
||||||
Ox.PATH + 'UI/maplibre-gl/maplibre-gl-geocoder.min.js',
|
+ '//maps.google.com/maps/api/js?callback=googleCallback&sensor=false'
|
||||||
], initMap)
|
+ (Ox.Map.GoogleApiKey ? '&key=' + Ox.Map.GoogleApiKey : '')
|
||||||
}
|
);
|
||||||
|
|
||||||
function equalBonds(a, b) {
|
|
||||||
return (
|
|
||||||
a._sw.lat == b._sw.lat &&
|
|
||||||
a._sw.lng == b._sw.lng &&
|
|
||||||
a._ne.lat == b._ne.lat &&
|
|
||||||
a._ne.lng == b._ne.lng
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPlaceToMap(place) {
|
function addPlaceToMap(place) {
|
||||||
|
|
@ -541,11 +535,11 @@ Ox.Map = function(options, self) {
|
||||||
if (!place) {
|
if (!place) {
|
||||||
var bounds = self.map.getBounds(),
|
var bounds = self.map.getBounds(),
|
||||||
center = self.map.getCenter(),
|
center = self.map.getCenter(),
|
||||||
southwest = new maplibregl.LngLatBounds(
|
southwest = new google.maps.LatLngBounds(
|
||||||
bounds._sw, center
|
bounds.getSouthWest(), center
|
||||||
).getCenter(),
|
).getCenter(),
|
||||||
northeast = new maplibregl.LngLatBounds(
|
northeast = new google.maps.LatLngBounds(
|
||||||
center, bounds._ne
|
center, bounds.getNorthEast()
|
||||||
).getCenter(),
|
).getCenter(),
|
||||||
place = new Ox.MapPlace({
|
place = new Ox.MapPlace({
|
||||||
alternativeNames: [],
|
alternativeNames: [],
|
||||||
|
|
@ -556,14 +550,14 @@ Ox.Map = function(options, self) {
|
||||||
map: that,
|
map: that,
|
||||||
name: '',
|
name: '',
|
||||||
type: 'feature',
|
type: 'feature',
|
||||||
south: southwest.lat,
|
south: southwest.lat(),
|
||||||
west: southwest.lng,
|
west: southwest.lng(),
|
||||||
north: northeast.lat,
|
north: northeast.lat(),
|
||||||
east: northeast.lng
|
east: northeast.lng()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Ox.forEach(self.places, function(p, i) {
|
Ox.forEach(self.places, function(p, i) {
|
||||||
if (equalBonds(place.bounds, p.bounds)) {
|
if (place.bounds.equals(p.bounds)) {
|
||||||
place = p;
|
place = p;
|
||||||
exists = true;
|
exists = true;
|
||||||
return false; // break
|
return false; // break
|
||||||
|
|
@ -595,23 +589,17 @@ Ox.Map = function(options, self) {
|
||||||
self.boundsChanged = true;
|
self.boundsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toSpan(bounds) {
|
|
||||||
return {
|
|
||||||
lat: bounds._ne.lat - bounds._sw.lat,
|
|
||||||
lng: bounds._ne.lng - bounds._sw.lng,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function canContain(outerBounds, innerBounds) {
|
function canContain(outerBounds, innerBounds) {
|
||||||
// checks if outerBounds _can_ contain innerBounds
|
// checks if outerBounds _can_ contain innerBounds
|
||||||
var outerSpan = toSpan(outerBounds),
|
var outerSpan = outerBounds.toSpan(),
|
||||||
innerSpan = toSpan(innerBounds);
|
innerSpan = innerBounds.toSpan();
|
||||||
return outerSpan.lat > innerSpan.lat &&
|
return outerSpan.lat() > innerSpan.lat() &&
|
||||||
outerSpan.lng > innerSpan.lng;
|
outerSpan.lng() > innerSpan.lng();
|
||||||
}
|
}
|
||||||
|
|
||||||
function centerChanged() {
|
function centerChanged() {
|
||||||
that.tooltip.remove()
|
var tooltip = $('.OxMapMarkerTooltip');
|
||||||
|
tooltip.length && Ox.$elements[$(tooltip[0]).data('oxid')].hide();
|
||||||
self.center = self.map.getCenter();
|
self.center = self.map.getCenter();
|
||||||
self.centerChanged = true;
|
self.centerChanged = true;
|
||||||
}
|
}
|
||||||
|
|
@ -621,21 +609,9 @@ Ox.Map = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickMap(event) {
|
function clickMap(event) {
|
||||||
// Check if click hit any rectangle fill layers (which have rectangle click handlers)
|
|
||||||
var features = self.map.queryRenderedFeatures(event.point, {
|
|
||||||
layers: self.map.getStyle().layers
|
|
||||||
.filter(layer => layer.id.includes('-fill'))
|
|
||||||
.map(layer => layer.id)
|
|
||||||
});
|
|
||||||
|
|
||||||
// If we clicked on a rectangle, don't process map click
|
|
||||||
if (features.length > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var place = getSelectedPlace();
|
var place = getSelectedPlace();
|
||||||
if (self.options.clickable/* && !editing()*/) {
|
if (self.options.clickable/* && !editing()*/) {
|
||||||
getPlaceByLatLng(event.lngLat, self.map.getBounds(), function(place) {
|
getPlaceByLatLng(event.latLng, self.map.getBounds(), function(place) {
|
||||||
if (place) {
|
if (place) {
|
||||||
addPlaceToMap(place);
|
addPlaceToMap(place);
|
||||||
//selectPlace(place.id);
|
//selectPlace(place.id);
|
||||||
|
|
@ -680,7 +656,7 @@ Ox.Map = function(options, self) {
|
||||||
|
|
||||||
function crossesDateline() {
|
function crossesDateline() {
|
||||||
var bounds = self.map.getBounds();
|
var bounds = self.map.getBounds();
|
||||||
return bounds._sw.lng > bounds._ne.lng;
|
return bounds.getSouthWest().lng() > bounds.getNorthEast().lng();
|
||||||
}
|
}
|
||||||
|
|
||||||
function editing() {
|
function editing() {
|
||||||
|
|
@ -705,9 +681,9 @@ Ox.Map = function(options, self) {
|
||||||
// get initial map bounds
|
// get initial map bounds
|
||||||
self.options.places({}, function(result) {
|
self.options.places({}, function(result) {
|
||||||
var area = result.data.area;
|
var area = result.data.area;
|
||||||
callback(new maplibregl.LngLatBounds(
|
callback(new google.maps.LatLngBounds(
|
||||||
new maplibregl.LngLat(area.west, area.south),
|
new google.maps.LatLng(area.south, area.west),
|
||||||
new maplibregl.LngLat(area.east, area.north)
|
new google.maps.LatLng(area.north, area.east)
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -719,28 +695,24 @@ Ox.Map = function(options, self) {
|
||||||
- self.options.showZoombar * 16;
|
- self.options.showZoombar * 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMapType() {
|
||||||
|
return self.options.showLabels ? 'HYBRID' : 'SATELLITE'
|
||||||
|
}
|
||||||
|
|
||||||
function getMaxZoom(point, callback) {
|
function getMaxZoom(point, callback) {
|
||||||
if (arguments.length == 1) {
|
if (arguments.length == 1) {
|
||||||
callback = point;
|
callback = point;
|
||||||
point = self.map.getCenter();
|
point = self.map.getCenter();
|
||||||
}
|
}
|
||||||
// fixme, why is getMaxZoom off by one?
|
|
||||||
let maxZoom = self.map.getMaxZoom()
|
|
||||||
setTimeout(() => {
|
|
||||||
callback(maxZoom)
|
|
||||||
})
|
|
||||||
/*
|
|
||||||
self.maxZoomService.getMaxZoomAtLatLng(point, function(data) {
|
self.maxZoomService.getMaxZoomAtLatLng(point, function(data) {
|
||||||
callback(data.status == 'OK' ? data.zoom : null);
|
callback(data.status == 'OK' ? data.zoom : null);
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMetersPerPixel() {
|
function getMetersPerPixel() {
|
||||||
// m/px = m/deg * deg/px
|
// m/px = m/deg * deg/px
|
||||||
const degreesPerPixel = 360 / (self.tileSize * Math.pow(2, self.map.getZoom()));
|
var degreesPerPixel = 360 / (self.tileSize * Math.pow(2, self.map.getZoom()));
|
||||||
const center = self.map.getCenter();
|
return Ox.getMetersPerDegree(self.map.getCenter().lat()) * degreesPerPixel;
|
||||||
return Ox.getMetersPerDegree(center.lat) * degreesPerPixel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMinZoom() {
|
function getMinZoom() {
|
||||||
|
|
@ -762,40 +734,61 @@ Ox.Map = function(options, self) {
|
||||||
: Ox.getObjectById(self.places, id);
|
: Ox.getObjectById(self.places, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getPlaceByLatLng(latlng, bounds, callback) {
|
function getPlaceByLatLng(latlng, bounds, callback) {
|
||||||
// gets the place at latlng appropriate for current zoom level
|
// gets the largest place at latlng that would fit in bounds
|
||||||
var callback = arguments.length == 3 ? callback : bounds,
|
var callback = arguments.length == 3 ? callback : bounds,
|
||||||
bounds = arguments.length == 3 ? bounds : null;
|
bounds = arguments.length == 3 ? bounds : null;
|
||||||
self.$loadingIcon && self.$loadingIcon.start();
|
self.$loadingIcon && self.$loadingIcon.start();
|
||||||
var results = await reverseGeocode(latlng);
|
self.geocoder.geocode({
|
||||||
|
latLng: latlng
|
||||||
|
}, function(results, status) {
|
||||||
self.$loadingIcon && self.$loadingIcon.stop();
|
self.$loadingIcon && self.$loadingIcon.stop();
|
||||||
|
if (status == google.maps.GeocoderStatus.OK) {
|
||||||
if (results.features.length) {
|
if (bounds) {
|
||||||
// We only have one result based on current zoom level
|
Ox.forEach(results.reverse(), function(result, i) {
|
||||||
var feature = results.features[0];
|
if (
|
||||||
callback(new Ox.MapPlace(parseGeodata(feature)));
|
i == results.length - 1 ||
|
||||||
|
canContain(bounds, result.geometry.bounds || result.geometry.viewport)
|
||||||
triggerGeocodeEvent({
|
) {
|
||||||
latLng: latlng,
|
callback(new Ox.MapPlace(parseGeodata(results[i])));
|
||||||
results: results.features
|
return false; // break
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Ox.Log('Map', 'geocode failed: no results');
|
callback(new Ox.MapPlace(parseGeodata(results[0])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
status == google.maps.GeocoderStatus.OK ||
|
||||||
|
status == google.maps.GeocoderStatus.ZERO_RESULTS
|
||||||
|
) {
|
||||||
|
triggerGeocodeEvent({
|
||||||
|
latLng: latlng,
|
||||||
|
results: results
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Ox.Log('Map', 'geocode failed:', status);
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPlaceByName(name, callback) {
|
function getPlaceByName(name, callback) {
|
||||||
self.$loadingIcon && self.$loadingIcon.start();
|
self.$loadingIcon && self.$loadingIcon.start();
|
||||||
forwardGeocode({
|
self.geocoder.geocode({
|
||||||
query: name
|
address: name
|
||||||
}).then(function(results) {
|
}, function(results, status) {
|
||||||
self.$loadingIcon && self.$loadingIcon.stop();
|
self.$loadingIcon && self.$loadingIcon.stop();
|
||||||
if (results.features.length) {
|
if (status == google.maps.GeocoderStatus.OK) {
|
||||||
callback(new Ox.MapPlace(parseGeodata(results.features[0])));
|
callback(new Ox.MapPlace(parseGeodata(results[0])));
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
status == google.maps.GeocoderStatus.OK
|
||||||
|
&& status != google.maps.GeocoderStatus.ZERO_RESULTS
|
||||||
|
) {
|
||||||
triggerGeocodeEvent({
|
triggerGeocodeEvent({
|
||||||
address: name,
|
address: name,
|
||||||
results: results.features
|
results: results
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Ox.Log('Map', 'geocode failed:', status);
|
Ox.Log('Map', 'geocode failed:', status);
|
||||||
|
|
@ -838,192 +831,36 @@ Ox.Map = function(options, self) {
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function bbox2bounds(bbox) {
|
|
||||||
return new maplibregl.LngLatBounds(
|
|
||||||
new maplibregl.LngLat(bbox[0], bbox[1]),
|
|
||||||
new maplibregl.LngLat(bbox[2], bbox[3])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function converNominatimFeature(feature) {
|
|
||||||
const center = [
|
|
||||||
feature.bbox[0] +
|
|
||||||
(feature.bbox[2] - feature.bbox[0]) / 2,
|
|
||||||
feature.bbox[1] +
|
|
||||||
(feature.bbox[3] - feature.bbox[1]) / 2
|
|
||||||
];
|
|
||||||
const polygon = {
|
|
||||||
type: 'Feature',
|
|
||||||
geometry: {
|
|
||||||
type: 'Polygon',
|
|
||||||
coordinates: [
|
|
||||||
[feature.bbox[0], feature.bbox[1]],
|
|
||||||
[feature.bbox[1], feature.bbox[2]],
|
|
||||||
[feature.bbox[2], feature.bbox[3]],
|
|
||||||
[feature.bbox[0], feature.bbox[3]],
|
|
||||||
]
|
|
||||||
},
|
|
||||||
bounds: bbox2bounds(feature.bbox),
|
|
||||||
place_name: feature.properties.display_name,
|
|
||||||
properties: feature.properties,
|
|
||||||
text: feature.properties.display_name,
|
|
||||||
address_components: [
|
|
||||||
{
|
|
||||||
long_name: feature.properties.display_name,
|
|
||||||
short_name: feature.properties.display_name,
|
|
||||||
types: ['place']
|
|
||||||
}
|
|
||||||
],
|
|
||||||
place_type: ['place'],
|
|
||||||
};
|
|
||||||
return polygon
|
|
||||||
}
|
|
||||||
|
|
||||||
async function reverseGeocode(config) {
|
|
||||||
const features = [];
|
|
||||||
|
|
||||||
// Use current map zoom level directly as Nominatim zoom level
|
|
||||||
const currentMapZoom = Math.round(self.map.getZoom());
|
|
||||||
// FIXME: map to nominatim zoom levels:
|
|
||||||
// https://nominatim.org/release-docs/develop/api/Reverse/
|
|
||||||
// zoom address detail
|
|
||||||
// 3 country
|
|
||||||
// 5 state
|
|
||||||
// 8 county
|
|
||||||
// 10 city
|
|
||||||
// 12 town / borough
|
|
||||||
// 13 village / suburb
|
|
||||||
// 14 neighbourhood
|
|
||||||
// 15 any settlement
|
|
||||||
// 16 major streets
|
|
||||||
// 17 major and minor streets
|
|
||||||
// 18 building
|
|
||||||
//
|
|
||||||
console.log('Reverse geocoding: using map zoom =', currentMapZoom, 'for Nominatim zoom');
|
|
||||||
let request = `${self.options.nominatim}/reverse?lat=${
|
|
||||||
config.lat
|
|
||||||
}&lon=${
|
|
||||||
config.lng
|
|
||||||
}&format=geojson&polygon_geojson=0&addressdetails=1&extratags=1&accept-language=en`;
|
|
||||||
request += `&zoom=${currentMapZoom}`
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(request);
|
|
||||||
const geojson = await response.json();
|
|
||||||
|
|
||||||
if (geojson.features && geojson.features.length > 0) {
|
|
||||||
const feature = converNominatimFeature(geojson.features[0]);
|
|
||||||
feature.zoom = currentMapZoom;
|
|
||||||
features.push(feature);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to reverseGeocode with error: ${e}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
features
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async function forwardGeocode(config) {
|
|
||||||
const features = [];
|
|
||||||
const request = `${self.options.nominatim}/search?q=${
|
|
||||||
config.query
|
|
||||||
}&format=geojson&polygon_geojson=0&addressdetails=1&accept-language=en`;
|
|
||||||
try {
|
|
||||||
const response = await fetch(request);
|
|
||||||
const geojson = await response.json();
|
|
||||||
for (const feature of geojson.features) {
|
|
||||||
features.push(converNominatimFeature(feature));
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to forwardGeocode with error: ${e}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
features
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function initMap() {
|
function initMap() {
|
||||||
|
|
||||||
getMapBounds(function(mapBounds) {
|
getMapBounds(function(mapBounds) {
|
||||||
|
|
||||||
//Ox.Log('Map', 'init', mapBounds._sw, mapBounds._ne, mapBounds.getCenter())
|
//Ox.Log('Map', 'init', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter())
|
||||||
|
|
||||||
//self.elevationService = new google.maps.ElevationService();
|
self.elevationService = new google.maps.ElevationService();
|
||||||
//self.maxZoomService = new google.maps.MaxZoomService();
|
self.geocoder = new google.maps.Geocoder();
|
||||||
//
|
self.maxZoomService = new google.maps.MaxZoomService();
|
||||||
|
|
||||||
self.center = mapBounds ? mapBounds.getCenter() : new maplibregl.LngLat(0, 0);
|
self.center = mapBounds ? mapBounds.getCenter() : new google.maps.LatLng(0, 0);
|
||||||
self.zoom = self.minZoom;
|
self.zoom = self.minZoom;
|
||||||
|
that.map = self.map = new google.maps.Map(self.$map[0], {
|
||||||
self.sateliteStyle = {
|
|
||||||
'version': 8,
|
|
||||||
'sources': {
|
|
||||||
'raster-tiles': {
|
|
||||||
'type': 'raster',
|
|
||||||
'tiles': [
|
|
||||||
'https://mt0.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
|
|
||||||
'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
|
|
||||||
'https://mt2.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
|
|
||||||
'https://mt3.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
|
|
||||||
],
|
|
||||||
'tileSize': 256,
|
|
||||||
'attribution':
|
|
||||||
'FIXME',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'layers': [
|
|
||||||
{
|
|
||||||
'id': 'simple-tiles',
|
|
||||||
'type': 'raster',
|
|
||||||
'source': 'raster-tiles',
|
|
||||||
'roundZoom': true,
|
|
||||||
'minzoom': 0,
|
|
||||||
'maxzoom': 22
|
|
||||||
},
|
|
||||||
]
|
|
||||||
};
|
|
||||||
window.map = that.map = self.map = new maplibregl.Map({
|
|
||||||
container: self.$map[0],
|
|
||||||
center: self.center,
|
center: self.center,
|
||||||
style: self.options.showLabels ? self.options.style : self.sateliteStyle,
|
disableDefaultUI: true,
|
||||||
//noClear: true,
|
disableDoubleClickZoom: true,
|
||||||
//scrollwheel: !self.options.zoomOnlyWhenFocused,
|
mapTypeId: google.maps.MapTypeId[getMapType()],
|
||||||
|
noClear: true,
|
||||||
|
scrollwheel: !self.options.zoomOnlyWhenFocused,
|
||||||
zoom: self.zoom
|
zoom: self.zoom
|
||||||
})
|
|
||||||
self.geocoder = new MaplibreGeocoder({
|
|
||||||
forwardGeocode: forwardGeocode,
|
|
||||||
reverseGeocode: reverseGeocode,
|
|
||||||
})
|
|
||||||
/*
|
|
||||||
map.addControl(self.geocoder, {
|
|
||||||
maplibregl
|
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
that.map.on('click', clickMap)
|
|
||||||
that.map.on('zoom', zoomChanged)
|
|
||||||
that.map.on('idle', mapChanged)
|
|
||||||
that.map.on('moveend', boundsChanged)
|
|
||||||
that.map.on('dragend', boundsChanged)
|
|
||||||
that.map.on('zoomend', boundsChanged)
|
|
||||||
/*
|
|
||||||
that.map.on('resize', () => {
|
|
||||||
that.resizeMap()
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
google.maps.event.addListener(self.map, 'bounds_changed', boundsChanged);
|
google.maps.event.addListener(self.map, 'bounds_changed', boundsChanged);
|
||||||
google.maps.event.addListener(self.map, 'center_changed', centerChanged);
|
google.maps.event.addListener(self.map, 'center_changed', centerChanged);
|
||||||
google.maps.event.addListener(self.map, 'click', clickMap);
|
google.maps.event.addListener(self.map, 'click', clickMap);
|
||||||
google.maps.event.addListener(self.map, 'idle', mapChanged);
|
google.maps.event.addListener(self.map, 'idle', mapChanged);
|
||||||
google.maps.event.addListener(self.map, 'zoom_changed', zoomChanged);
|
google.maps.event.addListener(self.map, 'zoom_changed', zoomChanged);
|
||||||
google.maps.event.trigger(self.map, 'resize');
|
google.maps.event.trigger(self.map, 'resize');
|
||||||
*/
|
|
||||||
|
|
||||||
// needed to get mouse x/y coordinates on marker mouseover,
|
// needed to get mouse x/y coordinates on marker mouseover,
|
||||||
// see http://code.google.com/p/gmaps-api-issues/issues/detail?id=2342
|
// see http://code.google.com/p/gmaps-api-issues/issues/detail?id=2342
|
||||||
/*
|
|
||||||
that.overlayView = new google.maps.OverlayView();
|
that.overlayView = new google.maps.OverlayView();
|
||||||
that.overlayView.setMap(self.map);
|
that.overlayView.setMap(self.map);
|
||||||
that.overlayView.draw = function () {
|
that.overlayView.draw = function () {
|
||||||
|
|
@ -1033,9 +870,7 @@ Ox.Map = function(options, self) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
that.overlayView.draw();
|
that.overlayView.draw();
|
||||||
*/
|
|
||||||
|
|
||||||
that.map.on('load', () => {
|
|
||||||
Ox.forEach(self.$controls, function($control) {
|
Ox.forEach(self.$controls, function($control) {
|
||||||
$control.appendTo(self.$map);
|
$control.appendTo(self.$map);
|
||||||
});
|
});
|
||||||
|
|
@ -1056,7 +891,6 @@ Ox.Map = function(options, self) {
|
||||||
self.map.setZoom(self.minZoom);
|
self.map.setZoom(self.minZoom);
|
||||||
} else {
|
} else {
|
||||||
self.map.fitBounds(mapBounds);
|
self.map.fitBounds(mapBounds);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (self.map.getZoom() < self.minZoom) {
|
if (self.map.getZoom() < self.minZoom) {
|
||||||
|
|
@ -1065,23 +899,23 @@ Ox.Map = function(options, self) {
|
||||||
}
|
}
|
||||||
updateFormElements();
|
updateFormElements();
|
||||||
|
|
||||||
that.resizeMap()
|
|
||||||
self.loaded = true;
|
self.loaded = true;
|
||||||
self.boundsChanged = true;
|
|
||||||
that.triggerEvent('load');
|
that.triggerEvent('load');
|
||||||
})
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEmpty(bounds) {
|
function isEmpty(bounds) {
|
||||||
return bounds._sw.lat == bounds._ne.lat
|
// Google's bounds.isEmpty() is not reliable
|
||||||
&& bounds._sw.lng == bounds._ne.lng;
|
var southWest = bounds.getSouthWest(),
|
||||||
|
northEast = bounds.getNorthEast();
|
||||||
|
return southWest.lat() == northEast.lat()
|
||||||
|
&& southWest.lng() == northEast.lng();
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLoaded() {
|
function isLoaded() {
|
||||||
return window.maplibregl && window.maplibregl.maps && window.maplibregl.LngLat;
|
return window.google && window.google.maps && window.google.maps.LatLng;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapChanged() {
|
function mapChanged() {
|
||||||
|
|
@ -1093,11 +927,12 @@ Ox.Map = function(options, self) {
|
||||||
self.boundsChanged = false;
|
self.boundsChanged = false;
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var south = bounds._sw.lat,
|
var southWest = bounds.getSouthWest(),
|
||||||
west = bounds._sw.lng,
|
northEast = bounds.getNorthEast(),
|
||||||
north = bounds._ne.lat,
|
south = southWest.lat(),
|
||||||
east = bounds._ne.lng;
|
west = southWest.lng(),
|
||||||
|
north = northEast.lat(),
|
||||||
|
east = northEast.lng();
|
||||||
self.options.places({
|
self.options.places({
|
||||||
keys: self.placeKeys,
|
keys: self.placeKeys,
|
||||||
query: {
|
query: {
|
||||||
|
|
@ -1164,8 +999,7 @@ Ox.Map = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function pan(x, y) {
|
function pan(x, y) {
|
||||||
console.log(x, y, self.$map.width())
|
self.map.panBy(x * self.$map.width() / 2, y * self.$map.height() / 2);
|
||||||
self.map.panBy([x * self.$map.width() / 2, y * self.$map.height() / 2]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function panToPlace() {
|
function panToPlace() {
|
||||||
|
|
@ -1181,24 +1015,22 @@ Ox.Map = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseGeodata(data) {
|
function parseGeodata(data) {
|
||||||
console.log("parseGeodata", data)
|
var bounds = data.geometry.bounds || data.geometry.viewport,
|
||||||
// FIXME: data is geojson Feature with Polygon geometry now
|
northEast = bounds.getNorthEast(),
|
||||||
var bounds = data.bounds,
|
southWest = bounds.getSouthWest(),
|
||||||
northEast = bounds._ne,
|
|
||||||
southWest = bounds._sw,
|
|
||||||
place = {
|
place = {
|
||||||
alternativeNames: [],
|
alternativeNames: [],
|
||||||
components: data.address_components,
|
components: data.address_components,
|
||||||
countryCode: getCountryCode(data.address_components),
|
countryCode: getCountryCode(data.address_components),
|
||||||
east: northEast.lng,
|
east: northEast.lng(),
|
||||||
editable: self.options.editable,
|
editable: self.options.editable,
|
||||||
fullGeoname: getFullGeoname(data.address_components),
|
fullGeoname: getFullGeoname(data.address_components),
|
||||||
id: '_' + Ox.encodeBase32(Ox.uid()),
|
id: '_' + Ox.encodeBase32(Ox.uid()),
|
||||||
map: that,
|
map: that,
|
||||||
north: northEast.lat,
|
north: northEast.lat(),
|
||||||
south: southWest.lat,
|
south: southWest.lat(),
|
||||||
type: getType(data.address_components[0].types, data),
|
type: getType(data.address_components[0].types),
|
||||||
west: southWest.lng
|
west: southWest.lng()
|
||||||
};
|
};
|
||||||
place.geoname = data.formatted_address || place.fullGeoname;
|
place.geoname = data.formatted_address || place.fullGeoname;
|
||||||
place.name = (place.geoname || place.fullGeoname).split(', ')[0];
|
place.name = (place.geoname || place.fullGeoname).split(', ')[0];
|
||||||
|
|
@ -1230,34 +1062,19 @@ Ox.Map = function(options, self) {
|
||||||
) ? name : null;
|
) ? name : null;
|
||||||
}).join(', ');
|
}).join(', ');
|
||||||
}
|
}
|
||||||
function getType(types, data) {
|
function getType(types) {
|
||||||
// see https://developers.google.com/maps/documentation/javascript/geocoding#GeocodingAddressTypes
|
// see https://developers.google.com/maps/documentation/javascript/geocoding#GeocodingAddressTypes
|
||||||
types.unshift(data.properties.addresstype)
|
|
||||||
console.log(types)
|
|
||||||
|
|
||||||
|
|
||||||
var strings = {
|
var strings = {
|
||||||
'country': ['country'],
|
'country': ['country'],
|
||||||
'region': [
|
'region': ['administrative_area', 'colloquial_area'],
|
||||||
'administrative_area', 'colloquial_area',
|
'city': ['locality'],
|
||||||
'state', 'county', 'region'
|
'borough': ['neighborhood', 'postal_code', 'sublocality'],
|
||||||
],
|
|
||||||
'city': [
|
|
||||||
'locality', 'city', 'town', 'village'
|
|
||||||
],
|
|
||||||
'borough': [
|
|
||||||
'neighborhood', 'postal_code', 'sublocality', 'suburb', 'borough',
|
|
||||||
'neighbourhood',
|
|
||||||
|
|
||||||
],
|
|
||||||
'street': [
|
'street': [
|
||||||
'intersection', 'route',
|
'intersection', 'route',
|
||||||
'street_address', 'street_number',
|
'street_address', 'street_number'
|
||||||
'road',
|
|
||||||
],
|
],
|
||||||
'building': [
|
'building': [
|
||||||
'airport', 'floor', 'premise', 'room', 'subpremise',
|
'airport', 'floor', 'premise', 'room', 'subpremise'
|
||||||
'building',
|
|
||||||
],
|
],
|
||||||
'feature': ['natural_feature', 'park']
|
'feature': ['natural_feature', 'park']
|
||||||
},
|
},
|
||||||
|
|
@ -1509,7 +1326,7 @@ Ox.Map = function(options, self) {
|
||||||
|
|
||||||
function toggleLabels() {
|
function toggleLabels() {
|
||||||
self.options.showLabels = !self.options.showLabels;
|
self.options.showLabels = !self.options.showLabels;
|
||||||
self.map.setStyle(self.options.showLabels ? self.options.style : self.sateliteStyle)
|
self.map.setMapTypeId(google.maps.MapTypeId[getMapType()]);
|
||||||
that.triggerEvent('togglelabels', {
|
that.triggerEvent('togglelabels', {
|
||||||
visible: self.options.showLabels
|
visible: self.options.showLabels
|
||||||
});
|
});
|
||||||
|
|
@ -1519,12 +1336,10 @@ Ox.Map = function(options, self) {
|
||||||
// someone may want to cache google geocode data, so we fire an event.
|
// someone may want to cache google geocode data, so we fire an event.
|
||||||
// google puts functions like lat or lng on the objects' prototypes,
|
// google puts functions like lat or lng on the objects' prototypes,
|
||||||
// so we create properly named properties, for json encoding
|
// so we create properly named properties, for json encoding
|
||||||
console.log(data)
|
|
||||||
/*
|
|
||||||
if (data.latLng) {
|
if (data.latLng) {
|
||||||
data.latLng = {
|
data.latLng = {
|
||||||
lat: data.latLng.lat,
|
lat: data.latLng.lat(),
|
||||||
lng: data.latLng.lng
|
lng: data.latLng.lng()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.results.forEach(function(result) {
|
data.results.forEach(function(result) {
|
||||||
|
|
@ -1532,24 +1347,23 @@ Ox.Map = function(options, self) {
|
||||||
if (result.geometry[key]) {
|
if (result.geometry[key]) {
|
||||||
result.geometry[key] = {
|
result.geometry[key] = {
|
||||||
northEast: {
|
northEast: {
|
||||||
lat: result.geometry[key]._ne.lat,
|
lat: result.geometry[key].getNorthEast().lat(),
|
||||||
lng: result.geometry[key]._ne.lng
|
lng: result.geometry[key].getNorthEast().lng()
|
||||||
},
|
},
|
||||||
southWest: {
|
southWest: {
|
||||||
lat: result.geometry[key]._sw.lat,
|
lat: result.geometry[key].getSouthWest().lat(),
|
||||||
lng: result.geometry[key]._sw.lng
|
lng: result.geometry[key].getSouthWest().lng()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (result.geometry.location) {
|
if (result.geometry.location) {
|
||||||
result.geometry.location = {
|
result.geometry.location = {
|
||||||
lat: result.geometry.location.lat,
|
lat: result.geometry.location.lat(),
|
||||||
lng: result.geometry.location.lng
|
lng: result.geometry.location.lng()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
that.triggerEvent('geocode', data);
|
that.triggerEvent('geocode', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1588,7 +1402,7 @@ Ox.Map = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function zoomChanged() {
|
function zoomChanged() {
|
||||||
var zoom = parseInt(self.map.getZoom());
|
var zoom = self.map.getZoom();
|
||||||
if (zoom < self.minZoom) {
|
if (zoom < self.minZoom) {
|
||||||
self.map.setZoom(self.minZoom);
|
self.map.setZoom(self.minZoom);
|
||||||
} else if (self.maxZoom && zoom > self.maxZoom) {
|
} else if (self.maxZoom && zoom > self.maxZoom) {
|
||||||
|
|
@ -1629,7 +1443,8 @@ Ox.Map = function(options, self) {
|
||||||
lng <n> Longitude
|
lng <n> Longitude
|
||||||
@*/
|
@*/
|
||||||
that.getCenter = function() {
|
that.getCenter = function() {
|
||||||
return self.map.getCenter();
|
var center = self.map.getCenter();
|
||||||
|
return {lat: center.lat(), lng: center.lng()};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
|
|
@ -1729,7 +1544,7 @@ Ox.Map = function(options, self) {
|
||||||
});
|
});
|
||||||
updateFormElements();
|
updateFormElements();
|
||||||
Ox.Log('Map', 'triggering google maps resize event, height', self.options.height)
|
Ox.Log('Map', 'triggering google maps resize event, height', self.options.height)
|
||||||
self.map.triggerRepaint()
|
google.maps.event.trigger(self.map, 'resize');
|
||||||
// self.map.setCenter(center);
|
// self.map.setCenter(center);
|
||||||
}
|
}
|
||||||
return that;
|
return that;
|
||||||
|
|
@ -1743,7 +1558,7 @@ Ox.Map = function(options, self) {
|
||||||
lng <n> Longitude
|
lng <n> Longitude
|
||||||
@*/
|
@*/
|
||||||
that.setCenter = function(center) {
|
that.setCenter = function(center) {
|
||||||
self.map.setCenter(new maplibregl.LngLat(center.lng, center.lat));
|
self.map.setCenter(new google.maps.LatLng(center.lat, center.lng));
|
||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,15 +46,6 @@ Ox.MapEditor = function(options, self) {
|
||||||
self.$list.size();
|
self.$list.size();
|
||||||
self.$map.resizeMap();
|
self.$map.resizeMap();
|
||||||
},
|
},
|
||||||
places: function() {
|
|
||||||
self.isAsync = Ox.isFunction(self.options.places);
|
|
||||||
self.$list.options({
|
|
||||||
items: self.isAsync ? self.options.places : Ox.clone(self.options.places)
|
|
||||||
})
|
|
||||||
self.$map.options({
|
|
||||||
places: self.options.places
|
|
||||||
})
|
|
||||||
},
|
|
||||||
selected: function() {
|
selected: function() {
|
||||||
self.$list.options({selected: self.options.selected});
|
self.$list.options({selected: self.options.selected});
|
||||||
},
|
},
|
||||||
|
|
@ -337,7 +328,7 @@ Ox.MapEditor = function(options, self) {
|
||||||
columns: self.columns,
|
columns: self.columns,
|
||||||
columnsRemovable: true,
|
columnsRemovable: true,
|
||||||
columnsVisible: true,
|
columnsVisible: true,
|
||||||
items: self.isAsync ? self.options.places : Ox.clone(self.options.places),
|
items: Ox.clone(self.options.places),
|
||||||
//items: self.options.places,
|
//items: self.options.places,
|
||||||
// area needed for icon, geoname needed for flag
|
// area needed for icon, geoname needed for flag
|
||||||
keys: ['area', 'geoname', 'matches'],
|
keys: ['area', 'geoname', 'matches'],
|
||||||
|
|
|
||||||
|
|
@ -42,32 +42,16 @@ Ox.MapMarker = function(options) {
|
||||||
Ox.forEach(options, function(val, key) {
|
Ox.forEach(options, function(val, key) {
|
||||||
that[key] = val;
|
that[key] = val;
|
||||||
});
|
});
|
||||||
setColor()
|
that.marker = new google.maps.Marker({
|
||||||
setSize()
|
|
||||||
const element = document.createElement('div')
|
|
||||||
element.style.border = '2px solid black'
|
|
||||||
element.style.borderRadius = '50px'
|
|
||||||
element.style.backgroundColor = '#' + Ox.toHex(that.color)
|
|
||||||
element.style.width = element.style.height = that.size + 'px'
|
|
||||||
that.marker = new maplibregl.Marker({
|
|
||||||
raiseOnDrag: false,
|
raiseOnDrag: false,
|
||||||
element: element,
|
shape: {coords: [8, 8, 8], type: 'circle'}
|
||||||
//shape: {coords: [8, 8, 8], type: 'circle'},
|
|
||||||
//title: that.place.name,
|
//title: that.place.name,
|
||||||
//zIndex: 1000
|
//zIndex: 1000
|
||||||
});
|
});
|
||||||
that.tooltip = new maplibregl.Popup({
|
|
||||||
closeButton: false,
|
|
||||||
closeOnClick: false,
|
|
||||||
className: 'tooltip'
|
|
||||||
});
|
|
||||||
that.tooltip.addClass
|
|
||||||
|
|
||||||
setOptions();
|
setOptions();
|
||||||
|
|
||||||
function click(event) {
|
function click() {
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
var key = that.map.getKey(),
|
var key = that.map.getKey(),
|
||||||
place, bounds, southWest, northEast;
|
place, bounds, southWest, northEast;
|
||||||
if (!that.place.selected) {
|
if (!that.place.selected) {
|
||||||
|
|
@ -78,9 +62,9 @@ Ox.MapMarker = function(options) {
|
||||||
place = that.map.getSelectedPlace();
|
place = that.map.getSelectedPlace();
|
||||||
}
|
}
|
||||||
if (place) {
|
if (place) {
|
||||||
bounds = new maplibregl.LngLatBounds(
|
bounds = new google.maps.LatLngBounds(
|
||||||
new maplibregl.LngLatBounds(place.west, place.south),
|
new google.maps.LatLng(place.south, place.west),
|
||||||
new maplibregl.LngLatBounds(place.east, place.north)
|
new google.maps.LatLng(place.north, place.east)
|
||||||
);
|
);
|
||||||
bounds = bounds.union(that.place.bounds);
|
bounds = bounds.union(that.place.bounds);
|
||||||
southWest = bounds.getSouthWest();
|
southWest = bounds.getSouthWest();
|
||||||
|
|
@ -95,10 +79,10 @@ Ox.MapMarker = function(options) {
|
||||||
map: that.map,
|
map: that.map,
|
||||||
name: '',
|
name: '',
|
||||||
type: 'feature',
|
type: 'feature',
|
||||||
south: southWest.lat,
|
south: southWest.lat(),
|
||||||
west: southWest.lng,
|
west: southWest.lng(),
|
||||||
north: northEast.lat,
|
north: northEast.lat(),
|
||||||
east: northEast.lng
|
east: northEast.lng()
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
that.map.options({selected: that.place.id});
|
that.map.options({selected: that.place.id});
|
||||||
|
|
@ -121,15 +105,13 @@ Ox.MapMarker = function(options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function drag(e) {
|
function drag(e) {
|
||||||
// In MapLibre GL, get current position from marker directly
|
|
||||||
var lngLat = that.marker.getLngLat();
|
|
||||||
var northSouth = (that.place.north - that.place.south) / 2,
|
var northSouth = (that.place.north - that.place.south) / 2,
|
||||||
lat = Ox.limit(
|
lat = Ox.limit(
|
||||||
lngLat.lat,
|
e.latLng.lat(),
|
||||||
Ox.MIN_LATITUDE + northSouth,
|
Ox.MIN_LATITUDE + northSouth,
|
||||||
Ox.MAX_LATITUDE - northSouth
|
Ox.MAX_LATITUDE - northSouth
|
||||||
),
|
),
|
||||||
lng = lngLat.lng,
|
lng = e.latLng.lng(),
|
||||||
span = Math.min(
|
span = Math.min(
|
||||||
that.place.sizeEastWest * Ox.getDegreesPerMeter(lat) / 2, 179.99999999
|
that.place.sizeEastWest * Ox.getDegreesPerMeter(lat) / 2, 179.99999999
|
||||||
),
|
),
|
||||||
|
|
@ -145,7 +127,9 @@ Ox.MapMarker = function(options) {
|
||||||
}
|
}
|
||||||
Ox.Log('Map', 'west', that.place.west, 'east', that.place.east, 'span', span);
|
Ox.Log('Map', 'west', that.place.west, 'east', that.place.east, 'span', span);
|
||||||
that.place.update();
|
that.place.update();
|
||||||
that.marker.setLngLat(that.place.center)
|
that.marker.setOptions({
|
||||||
|
position: that.place.center
|
||||||
|
});
|
||||||
that.place.rectangle.update();
|
that.place.rectangle.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,30 +181,35 @@ Ox.MapMarker = function(options) {
|
||||||
c.context.strokeStyle = 'rgb(' + border.join(', ') + ')';
|
c.context.strokeStyle = 'rgb(' + border.join(', ') + ')';
|
||||||
c.context.arc(r, r, r - 1, 0, 360);
|
c.context.arc(r, r, r - 1, 0, 360);
|
||||||
c.context.stroke();
|
c.context.stroke();
|
||||||
callback(new maplibregl.MarkerImage(
|
callback(new google.maps.MarkerImage(
|
||||||
c.canvas.toDataURL(),
|
c.canvas.toDataURL(),
|
||||||
new maplibregl.Size(options.size, options.size),
|
new google.maps.Size(options.size, options.size),
|
||||||
new maplibregl.Point(0, 0),
|
new google.maps.Point(0, 0),
|
||||||
new maplibregl.Point(r, r)
|
new google.maps.Point(r, r)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseover(e) {
|
function mouseover(e) {
|
||||||
that.tooltip.setLngLat(that.place.center).setHTML(
|
var offset = that.map.offset(),
|
||||||
'<div style="display: flex; gap: 8px; margin: 2px 2px"><img src="' + Ox.getFlagByGeoname(that.place.geoname, 16)
|
xy = that.map.overlayView.getProjection()
|
||||||
+ '" style="border-radius: 4px;margin: auto"/>'
|
.fromLatLngToContainerPixel(e.latLng);
|
||||||
+ '<div style="font-size: 9px;">'
|
that.tooltip.show(
|
||||||
+ that.map.options('markerTooltip')(that.place) + '</div></div>'
|
offset.left + Math.round(xy.x) - 4,
|
||||||
).addTo(that.map.map);
|
offset.top + Math.round(xy.y) + 20
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseout() {
|
function mouseout() {
|
||||||
that.tooltip.remove();
|
that.tooltip.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setColor() {
|
function setOptions() {
|
||||||
var color = that.map.options('markerColor');
|
// workaround to prevent marker from appearing twice
|
||||||
|
// after setting draggable from true to false (google maps bug)
|
||||||
|
var fix = that.marker.getDraggable() && !that.place.editing,
|
||||||
|
color = that.map.options('markerColor'),
|
||||||
|
size = that.map.options('markerSize');
|
||||||
//Ox.Log('Map', 'setOptions, that.map: ', that.map)
|
//Ox.Log('Map', 'setOptions, that.map: ', that.map)
|
||||||
if (color == 'auto') {
|
if (color == 'auto') {
|
||||||
that.color = typeColor[that.place.type] || typeColor['mapPlaceFeatureColor'];
|
that.color = typeColor[that.place.type] || typeColor['mapPlaceFeatureColor'];
|
||||||
|
|
@ -229,10 +218,6 @@ Ox.MapMarker = function(options) {
|
||||||
} else {
|
} else {
|
||||||
that.color = color(that.place);
|
that.color = color(that.place);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function setSize() {
|
|
||||||
var size = that.map.options('markerSize');
|
|
||||||
if (size == 'auto') {
|
if (size == 'auto') {
|
||||||
that.size = 8;
|
that.size = 8;
|
||||||
Ox.forEach(areaSize, function(size, area) {
|
Ox.forEach(areaSize, function(size, area) {
|
||||||
|
|
@ -247,57 +232,50 @@ Ox.MapMarker = function(options) {
|
||||||
} else {
|
} else {
|
||||||
that.size = size(that.place);
|
that.size = size(that.place);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function setOptions() {
|
|
||||||
// workaround to prevent marker from appearing twice
|
|
||||||
// after setting draggable from true to false (google maps bug)
|
|
||||||
var fix = false, // that.marker.getDraggable() && !that.place.editing,
|
|
||||||
size = that.map.options('markerSize');
|
|
||||||
//Ox.Log('Map', 'setOptions, that.map: ', that.map)
|
|
||||||
setColor()
|
|
||||||
setSize()
|
|
||||||
/* fixme, some of those can be set some not
|
|
||||||
that.marker.setOptions({
|
that.marker.setOptions({
|
||||||
// fixme: cursor remains pointer
|
// fixme: cursor remains pointer
|
||||||
cursor: that.place.editing ? 'move' : 'pointer',
|
cursor: that.place.editing ? 'move' : 'pointer',
|
||||||
draggable: that.place.editing,
|
draggable: that.place.editing,
|
||||||
element: Ox.MapMarkerImage({
|
icon: Ox.MapMarkerImage({
|
||||||
color: that.color,
|
color: that.color,
|
||||||
mode: that.place.editing ? 'editing' :
|
mode: that.place.editing ? 'editing' :
|
||||||
that.place.selected ? 'selected' : 'normal',
|
that.place.selected ? 'selected' : 'normal',
|
||||||
size: that.size,
|
size: that.size,
|
||||||
type: that.place.id[0] == '_' ? 'result' : 'place'
|
type: that.place.id[0] == '_' ? 'result' : 'place'
|
||||||
}),
|
}),
|
||||||
})
|
position: that.place.center
|
||||||
*/
|
});
|
||||||
//that.marker._color = that.color;
|
|
||||||
that.marker._element.style.cursor = that.place.editing ? 'move' : 'pointer';
|
|
||||||
that.marker._element.height = that.marker._element.width = that.size + 'px'
|
|
||||||
that.marker.setDraggable(that.place.editing);
|
|
||||||
that.marker.setLngLat(that.place.center);
|
|
||||||
if (fix) {
|
if (fix) {
|
||||||
that.marker.setVisible(false);
|
that.marker.setVisible(false);
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
that.marker.setVisible(true);
|
that.marker.setVisible(true);
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
setTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setTooltip() {
|
||||||
|
that.tooltip && that.tooltip.remove();
|
||||||
|
that.tooltip = Ox.Tooltip({
|
||||||
|
title: '<img src="'
|
||||||
|
+ Ox.getFlagByGeoname(that.place.geoname, 16)
|
||||||
|
+ '" style="float: left; width: 16px; height: 16px; margin: 1px 0 1px -1px; border-radius: 4px"/>'
|
||||||
|
+ '<div style="float: left; margin: 4px -1px 0 4px; font-size: 9px;">'
|
||||||
|
+ that.map.options('markerTooltip')(that.place) + '</div>'
|
||||||
|
})
|
||||||
|
.addClass('OxMapMarkerTooltip');
|
||||||
|
}
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
add <f> add to map
|
add <f> add to map
|
||||||
() -> <f> add to map, returns MapMarker
|
() -> <f> add to map, returns MapMarker
|
||||||
@*/
|
@*/
|
||||||
that.add = function() {
|
that.add = function() {
|
||||||
that.marker.addTo(that.map.map);
|
that.marker.setMap(that.map.map);
|
||||||
const element = that.marker.getElement()
|
google.maps.event.addListener(that.marker, 'click', click);
|
||||||
if(element) {
|
google.maps.event.addListener(that.marker, 'dblclick', dblclick);
|
||||||
element.addEventListener('click', click)
|
google.maps.event.addListener(that.marker, 'mouseover', mouseover);
|
||||||
element.addEventListener('dblclick', dblclick)
|
google.maps.event.addListener(that.marker, 'mouseout', mouseout);
|
||||||
element.addEventListener('mouseover', mouseover)
|
|
||||||
element.addEventListener('mouseout', mouseout)
|
|
||||||
}
|
|
||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -307,9 +285,9 @@ Ox.MapMarker = function(options) {
|
||||||
@*/
|
@*/
|
||||||
that.edit = function() {
|
that.edit = function() {
|
||||||
setOptions();
|
setOptions();
|
||||||
that.marker.on('dragstart', dragstart);
|
google.maps.event.addListener(that.marker, 'dragstart', dragstart);
|
||||||
that.marker.on('drag', drag);
|
google.maps.event.addListener(that.marker, 'drag', drag);
|
||||||
that.marker.on('dragend', dragend);
|
google.maps.event.addListener(that.marker, 'dragend', dragend);
|
||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -318,12 +296,8 @@ Ox.MapMarker = function(options) {
|
||||||
() -> <f> remove marker from map, returns MapMarker
|
() -> <f> remove marker from map, returns MapMarker
|
||||||
@*/
|
@*/
|
||||||
that.remove = function() {
|
that.remove = function() {
|
||||||
that.marker.remove();
|
that.marker.setMap(null);
|
||||||
//that.marker.off('dragstart');
|
google.maps.event.clearListeners(that.marker);
|
||||||
//that.marker.off('drag');
|
|
||||||
//that.marker.off('dragend');
|
|
||||||
//fixme does this work to remove all events?
|
|
||||||
that.marker.off();
|
|
||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -332,9 +306,9 @@ Ox.MapMarker = function(options) {
|
||||||
() -> <f> clear edit listeners, returns MapMarker
|
() -> <f> clear edit listeners, returns MapMarker
|
||||||
@*/
|
@*/
|
||||||
that.submit = function() {
|
that.submit = function() {
|
||||||
that.marker.off('dragstart');
|
google.maps.event.clearListeners(that.marker, 'dragstart');
|
||||||
that.marker.off('drag');
|
google.maps.event.clearListeners(that.marker, 'drag');
|
||||||
that.marker.off('dragend');
|
google.maps.event.clearListeners(that.marker, 'dragend');
|
||||||
return that;
|
return that;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ Ox.MapMarkerImage = (function() {
|
||||||
themeData = Ox.Theme.getThemeData();
|
themeData = Ox.Theme.getThemeData();
|
||||||
|
|
||||||
if (!cache[index]) {
|
if (!cache[index]) {
|
||||||
var color = options.rectangle ? [255, 255, 255, 1]
|
var color = options.rectangle ? [0, 0, 0, 0]
|
||||||
: options.color.concat(
|
: options.color.concat(
|
||||||
[options.type == 'place' ? 0.75 : 0.25]
|
[options.type == 'place' ? 0.75 : 0.25]
|
||||||
),
|
),
|
||||||
|
|
@ -50,10 +50,12 @@ Ox.MapMarkerImage = (function() {
|
||||||
c.context.strokeStyle = 'rgba(' + border.join(', ') + ')';
|
c.context.strokeStyle = 'rgba(' + border.join(', ') + ')';
|
||||||
c.context.arc(r, r, r - 1, 0, 360);
|
c.context.arc(r, r, r - 1, 0, 360);
|
||||||
c.context.stroke();
|
c.context.stroke();
|
||||||
cache[index] = document.createElement('img')
|
cache[index] = new google.maps.MarkerImage(
|
||||||
cache[index].src = c.canvas.toDataURL()
|
c.canvas.toDataURL(),
|
||||||
cache[index].width = options.size
|
new google.maps.Size(options.size, options.size),
|
||||||
cache[index].height = options.size
|
new google.maps.Point(0, 0),
|
||||||
|
new google.maps.Point(r, r)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache[index];
|
return cache[index];
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ Ox.MapPlace = function(options) {
|
||||||
|
|
||||||
options = Ox.extend({
|
options = Ox.extend({
|
||||||
east: 0,
|
east: 0,
|
||||||
editable: true,
|
|
||||||
editing: false,
|
editing: false,
|
||||||
geoname: '',
|
geoname: '',
|
||||||
map: null,
|
map: null,
|
||||||
|
|
@ -45,24 +44,21 @@ Ox.MapPlace = function(options) {
|
||||||
update();
|
update();
|
||||||
|
|
||||||
function update(updateMarker) {
|
function update(updateMarker) {
|
||||||
if (that.west > that.east) {
|
|
||||||
that.east += 360;
|
|
||||||
}
|
|
||||||
that.points = {
|
that.points = {
|
||||||
ne: new maplibregl.LngLat(that.east, that.north),
|
ne: new google.maps.LatLng(that.north, that.east),
|
||||||
sw: new maplibregl.LngLat(that.west, that.south)
|
sw: new google.maps.LatLng(that.south, that.west)
|
||||||
};
|
};
|
||||||
that.bounds = new maplibregl.LngLatBounds(that.points.sw, that.points.ne);
|
that.bounds = new google.maps.LatLngBounds(that.points.sw, that.points.ne);
|
||||||
that.center = that.bounds.getCenter();
|
that.center = that.bounds.getCenter();
|
||||||
that.lat = that.center.lat;
|
that.lat = that.center.lat();
|
||||||
that.lng = that.center.lng;
|
that.lng = that.center.lng();
|
||||||
Ox.extend(that.points, {
|
Ox.extend(that.points, {
|
||||||
e: new maplibregl.LngLat(that.east, that.lat),
|
e: new google.maps.LatLng(that.lat, that.east),
|
||||||
s: new maplibregl.LngLat(that.lng, that.south),
|
s: new google.maps.LatLng(that.south, that.lng),
|
||||||
se: new maplibregl.LngLat(that.east, that.south),
|
se: new google.maps.LatLng(that.south, that.east),
|
||||||
n: new maplibregl.LngLat(that.lng, that.north),
|
n: new google.maps.LatLng(that.north, that.lng),
|
||||||
nw: new maplibregl.LngLat(that.west, that.north),
|
nw: new google.maps.LatLng(that.north, that.west),
|
||||||
w: new maplibregl.LngLat(that.west, that.lat)
|
w: new google.maps.LatLng(that.lat, that.west)
|
||||||
});
|
});
|
||||||
// fixme: use bounds.toSpan()
|
// fixme: use bounds.toSpan()
|
||||||
that.sizeNorthSouth = (that.north - that.south)
|
that.sizeNorthSouth = (that.north - that.south)
|
||||||
|
|
@ -83,9 +79,8 @@ Ox.MapPlace = function(options) {
|
||||||
place: that
|
place: that
|
||||||
});
|
});
|
||||||
} else if (updateMarker) {
|
} else if (updateMarker) {
|
||||||
console.log("fixme update marker")
|
that.marker.update();
|
||||||
//that.marker.update();
|
that.rectangle.update();
|
||||||
//that.rectangle.update();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,178 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
class MapLibreRectangle {
|
|
||||||
constructor(options = {}) {
|
|
||||||
this.id = options.id || 'rectangle-' + Ox.uid();
|
|
||||||
this.bounds = options.bounds;
|
|
||||||
this.draggable = options.draggable || false;
|
|
||||||
this.onclick = options.onclick || null
|
|
||||||
}
|
|
||||||
|
|
||||||
_createRectangle() {
|
|
||||||
const coords = this._getPolygonCoordinates();
|
|
||||||
|
|
||||||
const rectangleGeoJSON = {
|
|
||||||
type: 'Feature',
|
|
||||||
geometry: {
|
|
||||||
type: 'Polygon',
|
|
||||||
coordinates: [coords]
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
id: this.id
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var sourceId = `${this.id}-rectangles`
|
|
||||||
this.source = this.map.getSource(sourceId)
|
|
||||||
if (!this.source) {
|
|
||||||
this.map.addSource(sourceId, {
|
|
||||||
type: 'geojson',
|
|
||||||
data: {
|
|
||||||
type: 'FeatureCollection',
|
|
||||||
features: []
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.source = this.map.getSource(sourceId)
|
|
||||||
|
|
||||||
// Add fill layer
|
|
||||||
var layerId = `${this.id}-fill`
|
|
||||||
if (!this.map.getLayer(layerId)) {
|
|
||||||
this.map.addLayer({
|
|
||||||
id: layerId,
|
|
||||||
type: 'fill',
|
|
||||||
source: sourceId,
|
|
||||||
paint: {
|
|
||||||
'fill-color': '#088',
|
|
||||||
'fill-opacity': 0.3
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add outline layer
|
|
||||||
var layerId = `${this.id}-outline`
|
|
||||||
if (!this.map.getLayer(layerId)) {
|
|
||||||
this.map.addLayer({
|
|
||||||
id: layerId,
|
|
||||||
type: 'line',
|
|
||||||
source: sourceId,
|
|
||||||
paint: {
|
|
||||||
'line-color': '#000',
|
|
||||||
'line-width': 2
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
this.source._data.features.push(rectangleGeoJSON)
|
|
||||||
this.source.setData(this.source._data)
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
_getPolygonCoordinates() {
|
|
||||||
const sw = this.bounds._sw;
|
|
||||||
const ne = this.bounds._ne;
|
|
||||||
|
|
||||||
return [
|
|
||||||
[sw.lng, ne.lat], // NW
|
|
||||||
[ne.lng, ne.lat], // NE
|
|
||||||
[ne.lng, sw.lat], // SE
|
|
||||||
[sw.lng, sw.lat], // SW
|
|
||||||
[sw.lng, ne.lat] // Close polygon
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
setBounds(bounds) {
|
|
||||||
this.bounds = bounds;
|
|
||||||
const coords = this._getPolygonCoordinates();
|
|
||||||
const updatedData = {
|
|
||||||
type: 'Feature',
|
|
||||||
geometry: {
|
|
||||||
type: 'Polygon',
|
|
||||||
coordinates: [coords]
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
id: this.id
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var updated = false;
|
|
||||||
this.source._data.features.forEach(feature => {
|
|
||||||
if (feature.properties.id == this.id) {
|
|
||||||
feature.geometry = updatedData.geometry
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (!updated) {
|
|
||||||
this.source._data.features.push(updatedData)
|
|
||||||
}
|
|
||||||
this.source.setData(this.source._data)
|
|
||||||
}
|
|
||||||
|
|
||||||
getBounds() {
|
|
||||||
return this.bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
_enableDragging() {
|
|
||||||
let isDragging = false;
|
|
||||||
let startPos;
|
|
||||||
|
|
||||||
this.map.on('mousedown', `${this.id}-fill`, (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
isDragging = true;
|
|
||||||
startPos = e.lngLat;
|
|
||||||
this.map.getCanvas().style.cursor = 'grabbing';
|
|
||||||
});
|
|
||||||
|
|
||||||
this.map.on('mousemove', (e) => {
|
|
||||||
if (!isDragging) return;
|
|
||||||
|
|
||||||
const dx = e.lngLat.lng - startPos.lng;
|
|
||||||
const dy = e.lngLat.lat - startPos.lat;
|
|
||||||
|
|
||||||
const sw = [this.bounds[0][0] + dx, this.bounds[0][1] + dy];
|
|
||||||
const ne = [this.bounds[1][0] + dx, this.bounds[1][1] + dy];
|
|
||||||
|
|
||||||
this.setBounds([sw, ne]);
|
|
||||||
startPos = e.lngLat;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.map.on('mouseup', () => {
|
|
||||||
if (isDragging) {
|
|
||||||
isDragging = false;
|
|
||||||
this.map.getCanvas().style.cursor = '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_enableClicking() {
|
|
||||||
this.map.on('click', `${this.id}-fill`, e => {
|
|
||||||
console.log('click', e)
|
|
||||||
if (this.onclick) {
|
|
||||||
e.preventDefault()
|
|
||||||
//e.stopPropagation()
|
|
||||||
this.onclick(e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
remove() {
|
|
||||||
this.source._data.features = this.source._data.features.filter(feature => {
|
|
||||||
return feature.properties.id != this.id
|
|
||||||
})
|
|
||||||
this.source.setData(this.source._data)
|
|
||||||
}
|
|
||||||
|
|
||||||
add() {
|
|
||||||
this.setBounds(this.bounds)
|
|
||||||
}
|
|
||||||
|
|
||||||
addTo(map) {
|
|
||||||
this.map = map;
|
|
||||||
this._createRectangle();
|
|
||||||
if (this.draggable) this._enableDragging();
|
|
||||||
this._enableClicking();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.MapRectangle <f> MapRectangle Object
|
Ox.MapRectangle <f> MapRectangle Object
|
||||||
(options) -> <o> MapRectangle Object
|
(options) -> <o> MapRectangle Object
|
||||||
|
|
@ -198,23 +25,14 @@ Ox.MapRectangle = function(options) {
|
||||||
/*@
|
/*@
|
||||||
rectangle <f> google.maps.Rectangle
|
rectangle <f> google.maps.Rectangle
|
||||||
@*/
|
@*/
|
||||||
/*
|
|
||||||
that.rectangle = new google.maps.Rectangle({
|
that.rectangle = new google.maps.Rectangle({
|
||||||
clickable: true,
|
clickable: true,
|
||||||
bounds: that.place.bounds
|
bounds: that.place.bounds
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
that.rectangle = new MapLibreRectangle({
|
|
||||||
bounds: that.place.bounds,
|
|
||||||
});
|
|
||||||
that.rectangle.addTo(that.map.map);
|
|
||||||
that.rectangle.onclick = click
|
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
markers <a> array of markers (only corners for rectangle resizing)
|
markers <a> array of markers
|
||||||
@*/
|
@*/
|
||||||
var cornerPositions = ['ne', 'nw', 'se', 'sw'];
|
that.markers = Ox.map(that.place.points, function(point, position) {
|
||||||
that.markers = cornerPositions.map(function(position) {
|
|
||||||
return new Ox.MapRectangleMarker({
|
return new Ox.MapRectangleMarker({
|
||||||
map: that.map,
|
map: that.map,
|
||||||
place: that.place,
|
place: that.place,
|
||||||
|
|
@ -224,7 +42,7 @@ Ox.MapRectangle = function(options) {
|
||||||
|
|
||||||
setOptions();
|
setOptions();
|
||||||
|
|
||||||
function click(e) {
|
function click() {
|
||||||
if (
|
if (
|
||||||
that.map.options('editable')
|
that.map.options('editable')
|
||||||
&& that.place.editable
|
&& that.place.editable
|
||||||
|
|
@ -246,7 +64,6 @@ Ox.MapRectangle = function(options) {
|
||||||
? 'mapPlaceEditingBorder'
|
? 'mapPlaceEditingBorder'
|
||||||
: 'mapPlaceSelectedBorder'
|
: 'mapPlaceSelectedBorder'
|
||||||
]);
|
]);
|
||||||
/*
|
|
||||||
that.rectangle.setOptions({
|
that.rectangle.setOptions({
|
||||||
bounds: that.place.bounds,
|
bounds: that.place.bounds,
|
||||||
fillColor: color,
|
fillColor: color,
|
||||||
|
|
@ -255,24 +72,14 @@ Ox.MapRectangle = function(options) {
|
||||||
strokeOpacity: that.place.id[0] == '_' ? 0.5 : 1,
|
strokeOpacity: that.place.id[0] == '_' ? 0.5 : 1,
|
||||||
strokeWeight: 2
|
strokeWeight: 2
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
/*
|
|
||||||
console.log("fixme", {
|
|
||||||
bounds: that.place.bounds,
|
|
||||||
fillColor: color,
|
|
||||||
fillOpacity: that.place.editing ? 0.1 : 0,
|
|
||||||
strokeColor: color,
|
|
||||||
strokeOpacity: that.place.id[0] == '_' ? 0.5 : 1,
|
|
||||||
strokeWeight: 2
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
add <f> add
|
add <f> add
|
||||||
@*/
|
@*/
|
||||||
that.add = function() {
|
that.add = function() {
|
||||||
that.rectangle.add()
|
that.rectangle.setMap(that.map.map);
|
||||||
|
google.maps.event.addListener(that.rectangle, 'click', click);
|
||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -292,7 +99,8 @@ Ox.MapRectangle = function(options) {
|
||||||
remove <f> remove
|
remove <f> remove
|
||||||
@*/
|
@*/
|
||||||
that.remove = function() {
|
that.remove = function() {
|
||||||
that.rectangle.remove();
|
that.rectangle.setMap(null);
|
||||||
|
google.maps.event.clearListeners(that.rectangle);
|
||||||
return that;
|
return that;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,8 +121,6 @@ Ox.MapRectangle = function(options) {
|
||||||
that.update = function() {
|
that.update = function() {
|
||||||
Ox.Log('Map', 'UPDATE...')
|
Ox.Log('Map', 'UPDATE...')
|
||||||
setOptions();
|
setOptions();
|
||||||
// Update the visual rectangle bounds
|
|
||||||
that.rectangle.setBounds(that.place.bounds);
|
|
||||||
Ox.forEach(that.markers, function(marker) {
|
Ox.forEach(that.markers, function(marker) {
|
||||||
marker.update();
|
marker.update();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ Ox.MapRectangleMarker = function(options) {
|
||||||
that[key] = val;
|
that[key] = val;
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
that.markerImage = new google.maps.MarkerImage
|
that.markerImage = new google.maps.MarkerImage
|
||||||
that.marker = new google.maps.Marker({
|
that.marker = new google.maps.Marker({
|
||||||
cursor: that.position + '-resize',
|
cursor: that.position + '-resize',
|
||||||
|
|
@ -36,39 +35,20 @@ Ox.MapRectangleMarker = function(options) {
|
||||||
position: that.place.points[that.position],
|
position: that.place.points[that.position],
|
||||||
raiseOnDrag: false
|
raiseOnDrag: false
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
// Create a simple DOM element for the corner handle
|
|
||||||
var element = document.createElement('div');
|
|
||||||
element.style.width = '8px';
|
|
||||||
element.style.height = '8px';
|
|
||||||
element.style.backgroundColor = 'white';
|
|
||||||
element.style.border = '2px solid black';
|
|
||||||
element.style.borderRadius = '2px';
|
|
||||||
element.style.cursor = that.position + '-resize';
|
|
||||||
element.style.boxSizing = 'border-box';
|
|
||||||
|
|
||||||
that.marker = new maplibregl.Marker({
|
|
||||||
draggable: true,
|
|
||||||
element: element,
|
|
||||||
});
|
|
||||||
that.marker.setLngLat(that.place.points[that.position])
|
|
||||||
|
|
||||||
function dragstart(e) {
|
function dragstart(e) {
|
||||||
Ox.$body.addClass('OxDragging');
|
Ox.$body.addClass('OxDragging');
|
||||||
// In MapLibre GL, get position from marker directly
|
|
||||||
var lngLat = that.marker.getLngLat();
|
|
||||||
that.drag = {
|
that.drag = {
|
||||||
lat: lngLat.lat,
|
lat: e.latLng.lat(),
|
||||||
lng: lngLat.lng
|
lng: e.latLng.lng()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function drag(e) {
|
function drag(e) {
|
||||||
// fixme: implement shift+drag (center stays the same)
|
// fixme: implement shift+drag (center stays the same)
|
||||||
// In MapLibre GL, get current position from marker directly
|
Ox.Log('Map', e.pixel.x, e.pixel.y)
|
||||||
var lngLat = that.marker.getLngLat();
|
var lat = Ox.limit(e.latLng.lat(), Ox.MIN_LATITUDE, Ox.MAX_LATITUDE),
|
||||||
var lat = Ox.limit(lngLat.lat, Ox.MIN_LATITUDE, Ox.MAX_LATITUDE),
|
lng = e.latLng.lng();
|
||||||
lng = lngLat.lng;
|
|
||||||
that.drag = {
|
that.drag = {
|
||||||
lat: lat,
|
lat: lat,
|
||||||
lng: lng
|
lng: lng
|
||||||
|
|
@ -110,33 +90,32 @@ Ox.MapRectangleMarker = function(options) {
|
||||||
add <f> add
|
add <f> add
|
||||||
@*/
|
@*/
|
||||||
that.add = function() {
|
that.add = function() {
|
||||||
that.marker.addTo(that.map.map);
|
that.marker.setMap(that.map.map);
|
||||||
that.marker.on('dragstart', dragstart);
|
google.maps.event.addListener(that.marker, 'dragstart', dragstart);
|
||||||
that.marker.on('drag', drag);
|
google.maps.event.addListener(that.marker, 'drag', drag);
|
||||||
that.marker.on('dragend', dragend);
|
google.maps.event.addListener(that.marker, 'dragend', dragend);
|
||||||
return that;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
remove <f> remove
|
remove <f> remove
|
||||||
@*/
|
@*/
|
||||||
that.remove = function() {
|
that.remove = function() {
|
||||||
// Clean up MapLibre events
|
that.marker.setMap(null);
|
||||||
that.marker.off('dragstart');
|
google.maps.event.clearListeners(that.marker);
|
||||||
that.marker.off('drag');
|
|
||||||
that.marker.off('dragend');
|
|
||||||
// Remove marker from map
|
|
||||||
that.marker.remove();
|
|
||||||
return that;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
update <f> update
|
update <f> update
|
||||||
@*/
|
@*/
|
||||||
that.update = function() {
|
that.update = function() {
|
||||||
// Just update position - visual stays the same during editing
|
that.marker.setOptions({
|
||||||
that.marker.setLngLat(that.place.points[that.position]);
|
icon: Ox.MapMarkerImage({
|
||||||
return that;
|
mode: 'editing',
|
||||||
|
rectangle: true,
|
||||||
|
type: that.place.id[0] == '_' ? 'result' : 'place'
|
||||||
|
}),
|
||||||
|
position: that.place.points[that.position]
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
|
|
|
||||||
|
|
@ -1,284 +0,0 @@
|
||||||
/* Basics */
|
|
||||||
.maplibregl-ctrl-geocoder,
|
|
||||||
.maplibregl-ctrl-geocoder *,
|
|
||||||
.maplibregl-ctrl-geocoder *:after,
|
|
||||||
.maplibregl-ctrl-geocoder *:before {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder {
|
|
||||||
font-size: 18px;
|
|
||||||
line-height: 24px;
|
|
||||||
font-family: "Open Sans", "Helvetica Neue", Arial, Helvetica, sans-serif;
|
|
||||||
position: relative;
|
|
||||||
background-color: #fff;
|
|
||||||
width: 100%;
|
|
||||||
min-width: 240px;
|
|
||||||
z-index: 1;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition: width 0.25s, min-width 0.25s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--input {
|
|
||||||
font: inherit;
|
|
||||||
width: 100%;
|
|
||||||
border: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
margin: 0;
|
|
||||||
height: 50px;
|
|
||||||
color: #404040; /* fallback */
|
|
||||||
color: rgba(0, 0, 0, 0.75);
|
|
||||||
padding: 6px 45px;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--input::-ms-clear {
|
|
||||||
display: none; /* hide input clear button in IE */
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--input:focus {
|
|
||||||
color: #404040; /* fallback */
|
|
||||||
color: rgba(0, 0, 0, 0.75);
|
|
||||||
outline: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
outline: thin dotted;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder .maplibregl-ctrl-geocoder--pin-right > * {
|
|
||||||
z-index: 2;
|
|
||||||
position: absolute;
|
|
||||||
right: 8px;
|
|
||||||
top: 7px;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder,
|
|
||||||
.maplibregl-ctrl-geocoder .suggestions {
|
|
||||||
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Collapsed */
|
|
||||||
.maplibregl-ctrl-geocoder.maplibregl-ctrl-geocoder--collapsed {
|
|
||||||
width: 50px;
|
|
||||||
min-width: 50px;
|
|
||||||
transition: width 0.25s, min-width 0.25s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Suggestions */
|
|
||||||
.maplibregl-ctrl-geocoder .suggestions {
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 4px;
|
|
||||||
left: 0;
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
top: 110%; /* fallback */
|
|
||||||
top: calc(100% + 6px);
|
|
||||||
z-index: 1000;
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-bottom-left .suggestions,
|
|
||||||
.maplibregl-ctrl-bottom-right .suggestions {
|
|
||||||
top: auto;
|
|
||||||
bottom: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder .suggestions > li > a {
|
|
||||||
cursor: default;
|
|
||||||
display: block;
|
|
||||||
padding: 6px 12px;
|
|
||||||
color: #404040;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder .suggestions > .active > a,
|
|
||||||
.maplibregl-ctrl-geocoder .suggestions > li > a:hover {
|
|
||||||
color: #404040;
|
|
||||||
background-color: #f3f3f3;
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--suggestion {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibre-ctrl-geocoder--suggestion-icon {
|
|
||||||
min-width: 30px;
|
|
||||||
min-height: 24px;
|
|
||||||
max-width: 30px;
|
|
||||||
max-height: 24px;
|
|
||||||
padding-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--suggestion-info {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--suggestion-match {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--suggestion-title,
|
|
||||||
.maplibregl-ctrl-geocoder--suggestion-address {
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--result {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibre-ctrl-geocoder--result-icon {
|
|
||||||
min-width: 30px;
|
|
||||||
min-height: 24px;
|
|
||||||
max-width: 30px;
|
|
||||||
max-height: 24px;
|
|
||||||
padding-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--result-title {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--result-title,
|
|
||||||
.maplibregl-ctrl-geocoder--result-address {
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Icons */
|
|
||||||
.maplibregl-ctrl-geocoder--icon {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
speak: none;
|
|
||||||
fill: #757575;
|
|
||||||
top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--icon-search {
|
|
||||||
position: absolute;
|
|
||||||
top: 13px;
|
|
||||||
left: 12px;
|
|
||||||
width: 23px;
|
|
||||||
height: 23px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--button {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
background: #fff;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--icon-close {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
margin-top: 8px;
|
|
||||||
margin-right: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--button:hover .maplibregl-ctrl-geocoder--icon-close {
|
|
||||||
fill: #909090;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--icon-loading {
|
|
||||||
width: 26px;
|
|
||||||
height: 26px;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-right: 0px;
|
|
||||||
-moz-animation: rotate 0.8s infinite cubic-bezier(0.45, 0.05, 0.55, 0.95);
|
|
||||||
-webkit-animation: rotate 0.8s infinite cubic-bezier(0.45, 0.05, 0.55, 0.95);
|
|
||||||
animation: rotate 0.8s infinite cubic-bezier(0.45, 0.05, 0.55, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animation */
|
|
||||||
@-webkit-keyframes rotate {
|
|
||||||
from {
|
|
||||||
-webkit-transform: rotate(0);
|
|
||||||
transform: rotate(0);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
-webkit-transform: rotate(360deg);
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes rotate {
|
|
||||||
from {
|
|
||||||
-webkit-transform: rotate(0);
|
|
||||||
transform: rotate(0);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
-webkit-transform: rotate(360deg);
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Media queries*/
|
|
||||||
@media screen and (min-width: 640px) {
|
|
||||||
.maplibregl-ctrl-geocoder.maplibregl-ctrl-geocoder--collapsed {
|
|
||||||
width: 36px;
|
|
||||||
min-width: 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder {
|
|
||||||
width: 33.3333%;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 20px;
|
|
||||||
max-width: 360px;
|
|
||||||
}
|
|
||||||
.maplibregl-ctrl-geocoder .suggestions {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--icon {
|
|
||||||
top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--icon-close {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
margin-top: 3px;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--icon-search {
|
|
||||||
left: 7px;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--input {
|
|
||||||
height: 36px;
|
|
||||||
padding: 6px 35px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-geocoder--icon-loading {
|
|
||||||
width: 26px;
|
|
||||||
height: 26px;
|
|
||||||
margin-top: -2px;
|
|
||||||
margin-right: -5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibre-gl-geocoder--error {
|
|
||||||
color: #909090;
|
|
||||||
padding: 6px 12px;
|
|
||||||
font-size: 16px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -92,15 +92,13 @@ def build_oxjs(downloads=False, geo=False):
|
||||||
|
|
||||||
# copy & link
|
# copy & link
|
||||||
ui_files = {'dev': [], 'min': []}
|
ui_files = {'dev': [], 'min': []}
|
||||||
css_files = ['maplibre-gl.css', 'maplibre-gl-geocoder.css']
|
|
||||||
for path, dirnames, filenames in os.walk(source_path):
|
for path, dirnames, filenames in os.walk(source_path):
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
if '_' not in path and filename[0] not in '._' \
|
if '_' not in path and filename[0] not in '._' \
|
||||||
and not filename.endswith('~') \
|
and not filename.endswith('~') \
|
||||||
|
and not filename.endswith('.css') \
|
||||||
and '/UI/svg' not in path \
|
and '/UI/svg' not in path \
|
||||||
and (geo or '/Geo/' not in path):
|
and (geo or '/Geo/' not in path):
|
||||||
if filename.endswith('.css') and filename not in css_files:
|
|
||||||
continue
|
|
||||||
# write copies in min path
|
# write copies in min path
|
||||||
source = os.path.join(path, filename)
|
source = os.path.join(path, filename)
|
||||||
is_jquery = re.search(r'^jquery-[\d\.]+\.js$', filename)
|
is_jquery = re.search(r'^jquery-[\d\.]+\.js$', filename)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue