I am have a vuejs/nuxtjs application using the gmap-vue package which is a fork of vue-google-maps. I have followed the drawing manager with slot example which is working as shown on the document, good times!
But...
I would like to do two more things
Save the data that I added to the map, how do I access it?
How to load geojson onto the map and then edit it.
Examle below:
More information from further investigation.
I am trying to build up data in the form of geojson
let shapes = [];
for(let shape in this.shapes){
let tmp = {
"type": "Feature",
"properties": {
"id": this.shapes[shape].id || null,
"zIndex": this.shapes[shape].zIndex || null
},
"geometry": {
"type": this.shapes[shape].type,
"coordinates": // where to find shape coordinates?
}
};
shapes.push(tmp)
}
console.log(JSON.stringify(shapes));
displays the following in the console.log
[
{
"type":"Feature",
"properties":{
"id":null,
"zIndex":null
},
"geometry":{
"type":"polygon",
"coordinates": // where to find coordinates?
}
}
]
console.log[this.shapes[shape]];
returns
{__ob__: Observer}
overlay: (...)
type: (...)
How can I access the coordinates?
For anyone else looking for an answer, I hope this helps you out.
const newShapes = [];
this.shapes.forEach((shape) => {
const coords = [];
shape.overlay.latLngs.getArray().forEach((latLng) => {
coords.push([latLng.lat, latLng.lng]);
});
newShapes.push({
type: 'Feature',
geometry: {
type: shape.type,
coordinates: coords,
},
});
});
As shown here: https://diegoazh.github.io/gmap-vue/#getting-a-map-reference
this.$refs.mapRef.$mapPromise.then((map) => {
map.panTo({lat: 1.38, lng: 103.80})
})
is working pretty great.
<gmap-drawing-manager ref="drawingRef">
and
<gmap-drawing-manager :shapes="shapes" ref="drawingRef">
allows to access the same information with this.shapes!
Related
After figuring out how to deal with TypeScript and use-supercluster library I have "made it work" until I got a new problem: I get an empty array whenever I use useSuperCluster() function.
I am following the creator's guide so I can handle my own project.
This is what I do:
const [bounds, setBounds] = useState(undefined as BBox | undefined);
const { data, error } = useSwr(API_URL, fetcher);
const coords: Array<ParkingData> = data && !error ? data.data : [];
const points: Array<PointFeature<GeoJsonProperties>> = coords.map(pd => ({
type: "Feature",
properties: {
cluster: false,
pdId: pd._id,
category: 'test'
},
geometry: { type: "Point", coordinates: [ pd.lat, pd.lng ] }
}));
const { clusters } = useSuperCluster({
points,
bounds,
zoom,
options: { radius: 75, maxZoom: 25 }
});
When I debug points I get something like:
But then, clusters is empty. I update bounds like in the video with a onChange attribute, like:
onChange={({ zoom, bounds }) => {
setZoom(zoom);
setBounds([
bounds.nw.lng,
bounds.se.lat,
bounds.se.lng,
bounds.nw.lat
]);
}}
So, what am I doing wrong?
Edit:
I had added supercluster object to useSuperCluster() destructuring like const { clusters, supercluster } = useSuperCluster(...) and after debugging it I get the following object:
Try changing this line order:
geometry: { type: "Point", coordinates: [ pd.lat, pd.lng ] }
to:
geometry: { type: "Point", coordinates: [ pd.lng, pd.lat ] }
apparently, the order is that way, in my case i tried this change and it didn't work for me, but for you there's a chance it will work.
https://github.com/mapbox/supercluster/issues/45
I am running into some difficulties to remove a geojon polygon from a layer with mapboxGL.
Here the following code to add my geoson polygons where
array_geo is a polygon geometry. Adding the polygon works like a charm,
but I still did not find how to delete my polygons. The only trick I found is to use the removeLayer(id) function which delete the entire layer.
var id="mylayer";
itemObj = {
type:"Feature",
properties: {
description: description,
type: 23
},
geometry: {
type: "Polygon",
coordinates: array_geo
},
};
mpolygons.push(itemObj);
map.addSource(id,{
"type":"geojson",
"data":{
"type":"FeatureCollection",
"features":mypolygons
}
self.map.addLayer({
"id": id,
"source":id,
"type":"fill",
"layout": {'visibility':'visible'},
"paint": {
'fill-color': '#088',
//'fill-opacity': 0.8
}
})
Thanks !
I'm trying to integrate Cesium 1.11 with an existing backend sending GeoJSON. I'm able to load data onto the view successfully from the first message, however subsequent calls to load() do not update the display.
I've simplified the problem to the following, also available as a fiddle.
I expect the second load call to update the display to move the marker to New York, however it stays on London.
Feature window still shows the "foo" property as 123, I expect 456.
Code
var viewer = new Cesium.Viewer('cesiumContainer');
var source = new Cesium.GeoJsonDataSource("name123");
viewer.dataSources.add(source);
source.load({
type: "FeatureCollection",
crs: {
type: "name",
properties: {
name: "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
features: [{
type: "Feature",
properties: {
foo: 123,
},
geometry: {
type: "Point",
coordinates: [0.1275, 51.5072] // London
},
id: "123"
}]
});
// workaround, but has side effect of destroying feature window
// source.entities.removeAll();
// sometime later...
source.load({
type: "FeatureCollection",
crs: {
type: "name",
properties: {
name: "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
features: [{
type: "Feature",
properties: {
foo: 456,
},
geometry: {
type: "Point",
coordinates: [-75.1890, 42.3482] // New York
},
id: "123"
}]
});
What I've tried
"forced" an update by calling source.entities.removeAll() however this has the side effect of closing the feature window if it is open during the the update. I'm receiving messages every second so this is not desirable.
Yes, I'm aware of the proprietary CZML system, however I'd like to stick to GeoJSON for this relatively simple system.
Update: further debugging. The problem appears to be a design feature...
load() helper method in GeoJsonDataSource calls that._entityCollection.removeAll(). This is between a suspendEvents() and resumeEvents() so does not cause the feature window to close.
After the resumeEvents() "change" events are fired even though the entities have actually been recreated
The existing BillboardVisualizer created by Cesium.Viewer keeps a cached instances to the Entities it used the first time it rendered
BillboardVisualizer.update() keeps reading the first position from the 'stale' entity instances and therefore no update is seen.
This looks like a bug in Cesium I just submitted issue #2891 and will try and get a fix into the 1.12 release on August 3rd. In the meantime, you should be able to workaround the issue using your removeAll strategy combined with resetting the selected entity after the load (which should keep the InfoBox around, which is what I assume you mean by feature window.) Here's a complete example that you can based into Sandcastle to see it in action.
var viewer = new Cesium.Viewer('cesiumContainer');
var source = new Cesium.GeoJsonDataSource("name123");
viewer.dataSources.add(source);
Sandcastle.addToolbarButton('Load 1', function(){
source.entities.removeAll();
source.load({
type: "FeatureCollection",
crs: {
type: "name",
properties: {
name: "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
features: [{
type: "Feature",
properties: {
foo: 123
},
geometry: {
type: "Point",
coordinates: [0.1275, 51.5072] // London
},
id: "123"
}]
}).then(function(){
viewer.selectedEntity = source.entities.values[0];
});
});
Sandcastle.addToolbarButton('Load 2', function() {
source.entities.removeAll();
source.load({
type: "FeatureCollection",
crs: {
type: "name",
properties: {
name: "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
features: [{
type: "Feature",
properties: {
foo: 456
},
geometry: {
type: "Point",
coordinates: [-75.1890, 42.3482] // New York
},
id: "123"
}]
}).then(function(){
viewer.selectedEntity = source.entities.values[0];
});
});
An alternative solution is to just use the GeoJsonDataSource for the creation of entities from JSON, and add the adding/updating manually into the viewer global entities collection
var viewer = new Cesium.Viewer('cesiumContainer');
var source = new Cesium.GeoJsonDataSource("name123");
// don't add source to viewer
source.load(...);
// sometime later...
source.load(...);
// manually update
viewer.entities.suspendEvents();
source.entities.values.forEach(function(entity) {
var existing = viewer.entities.getById(entity.id);
if (existing === undefined) {
viewer.entities.add(entity);
} else {
entity.propertyNames.forEach(function(name) {
existing[name] = entity[name];
});
}
}, this);
viewer.entities.resumeEvents();
When loading a geoJSON file into a Google Map as a data layer, how does one access the properties of the data layer itself?
I know how to access the individual properties, like posts_here in the below example. What I'm looking to get is the properties for the layer itself- in this example, maxPosts.
$.getJSON("http://example.com/posts/grid.json" + location.search, function (data) {
grid = map_canvas.data.addGeoJson(data);
map_canvas.data.setStyle(function(feature) {
return /** #type {google.maps.Data.StyleOptions} */({
strokeWeight: Math.log(feature.getProperty('posts_here')),
});
})
});
Example of the grid.json I'm loading:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-58,-35],
[-58,-34],
[-57,-34],
[-57,-35],
[-58,-35]
]
]
},
"properties": {
"posts_here": "177"
}
}
],
"properties": {
"maxPosts": "177"
}
}
The API does only parse the features-array of a FeatureCollection, when you want to access additional properties you must implement it on your own.
Based on the given code it isn't complicated, because the geoJson is accessible as object via data inside the $.getJSON-callback, you may simply access the property via
data.properties.maxPosts
I believe you should be able to use getFeatureById(id:number|string) to access information you've added from your geoJSON.
I am trying to make an interactive map using MapBox.
The basic idea is that people will hover over certain regions and they will light up and an event will trigger showing some content.
I got the map set up using Mapbox and then went ahead and got some data for the points by first
Going here to create a shapefile - http://www.gadm.org/country
And then going here to convert that file into a json file - http://www.mapshaper.org/
I then load the data into the map via mapbox and here is my result! (code below) - http://dev.touch-akl.com/nzmap/
As you can see thanks to the data I have downloaded it is almost a perfect trace of the country the only problem is that all the regions seem to be ONE object when hovering.
$.ajax({
url: '/nzmap/js/nzmap.json',
dataType: 'json',
success: function load(data) {
// set up the regions based on the JSON data and then call the styles and the hovers
var regions = L.geoJson(data, {
style: getStyle,
onEachFeature: onEachFeature
}).addTo(map);
// selects used to style the regionsLayer
function getStyle(feature) {
return {
weight: 2,
opacity: 0.1,
color: 'black',
fillOpacity: 0.7,
fillColor: 'red'
};
}
// combine the mouse in and mouse out?
function onEachFeature(feature, layer) {
layer.on({
mousemove: mousemove,
mouseout: mouseout
});
}
// mouse over change the layer styles
function mousemove(e) {
var layer = e.target;
// highlight feature
layer.setStyle({
weight: 3,
opacity: 0.3,
fillOpacity: 0.9
});
if (!L.Browser.ie && !L.Browser.opera) {
layer.bringToFront();
}
}
//mouse out reset the style
function mouseout(e) {
regions.resetStyle(e.target);
}
}
});
Here is a link to the json file if that helps understand what is going on - http://dev.touch-akl.com/nzmap//js/nzmap.json
It looks like some of the polygons are 'multipolygons' and some are seperate. I managed to create a new version of the map using just one region and it looks like this - http://dev.touch-akl.com/nzmap2/
My function for doing this is much the same except I have split the region off and use a json file that only has the coordinates for that region.
This is the JSON file for that example - http://dev.touch-akl.com/nzmap2/js/waikato.json
So where I am stuck is... Is there a way to format the original json file in a way that will keep each region as it's own separate object for hovers? And if so how can I go about changing the way I am setting up the map get the desired result?
It looks like I could make a seperate json file for each region like I am doing with the second example but that just does not seem like the right way to do this, been stuck for days so any help would be appreciated!
This is because what you are using isn't proper GeoJSON, at least not the GeoJSON L.GeoJSON expects. What you need is a GeoJSON FeatureCollection. A collection would look something like this:
[{
"type": "Feature",
"properties": {
"foo": "bar"
},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-104.05, 48.99],
[-97.22, 48.98],
[-96.58, 45.94],
[-104.03, 45.94],
[-104.05, 48.99]
]]
}
}, {
"type": "Feature",
"properties": {
"bar": "foo"
},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-109.05, 41.00],
[-102.06, 40.99],
[-102.03, 36.99],
[-109.04, 36.99],
[-109.05, 41.00]
]]
}
}]
As you can see, a FeatureCollection contains individual features which can be or type Point, MultiPoint, LineString, MultiLineString, Polygon or MultiPolygon. If you use a FeatureCollection L.GeoJSON will work as you would expect. Take a look at the reference for FeatureCollection and L.GeoJSON. A tutorial/example on using them both can be found here.