How to remove a polyline in cesiumjs,
var p = this.viewer.entities.add({
polyline: {
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.7,
color: Cesium.Color.ORANGE.withAlpha(0.7)
}),
positions: Cesium.Cartesian3.fromDegreesArrayHeights(points),
width: 15,
}
});
I used entities.removeAll(), but it is deleting entire data from the cesium conatiner(including models,etc). I want to delete only Polyline.
Save the return value from entities.add, this is a reference to the newly created entity.
var polylineEntity = viewer.entities.add({
//...
});
Later, you can remove a specific entity by reference.
viewer.entities.remove(polylineEntity);
var pathDone; //Store dataSource so later can be removed.
viewer.dataSources.remove(pathDone,true); // Removing old data.
Cesium.GeoJsonDataSource.load(data, { // Data contains geojson, linestring z.
stroke: Cesium.Color.HOTPINK,
fill: Cesium.Color.PINK.withAlpha(0.5),
strokeWidth: 2
}).then(function(geoData){
viewer.dataSources.add(geoData); //Adding new one.
pathDone=geoData;//Storing new reference.
});
This worked for me.
you can also remove entity by giving entity an id.
check cesium api doc here. https://cesium.com/learn/cesiumjs/ref-doc/EntityCollection.html?classFilter=entity#id
var p = this.viewer.entities.add({
id: "polylinId", // this is where you should add. give entity an id you can use.
polyline: {
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.7,
color: Cesium.Color.ORANGE.withAlpha(0.7)
}),
positions: Cesium.Cartesian3.fromDegreesArrayHeights(points),
width: 15,
}
});
// then remove entity by id you've given
viewer.entity.removeById("polylinId")
Related
I have added Google Maps for Flutter
i know how to add a marker as it is given clearly in there examples
MarkerOptions _options = new MarkerOptions(
position: LatLng(
driver_lat,
driver_lng,
),
infoWindowText:
const InfoWindowText('An interesting location', '*'));
Marker marker = new Marker('1', _options);
//Adding Marker
googleMapController.addMarker(_options);
And i am removing the marker like below
googleMapController.removeMarker(marker);
for adding the marker it is taking MarkerOptions object as a parameter but for removing the marker it is asking for Marker object as parameter and my removing marker code is not working.
i am getting the below error
Failed assertion: line 201 pos 12: '_markers[marker._id] == marker': is not true.
There are two ways to do this, one is via clearMarkers() Method
mapController.clearMarkers();
Another one is via targeting each marker returned by mapController.markers
mapController.markers.forEach((marker){
mapController.removeMarker(marker);
});
2020 answer:
.clearMarkers() has been deprecated as now each Marker is a Widget stored in a map. The correct way to clear all of the markers now on your Google Map is to set the state of of your marker Map to an empty map.
e.g.
...
onPressed: () {
setState(() {
gMapMarkers = {};
});
}
....
Use clearMarkers(). It will clear all markers in your map. So try googleMapController.clearMarkers();
I've came across this issue myself with the google_maps_library and the main cause of this issue '_markers[marker._id] == marker': is not true. is the fact that all GoogleMapsController methods return a Future, so this error is, let's say a concurrency issue since the method cals are async.
The correct way to add/remove a marker would be:
_testRemoveMarker() async {
Marker marker = await _mapController.addMarker(...markerOption..);
_mapController.removeMarker(marker);
}
_clearMarkersAndRead() async {
_mapController.clearMarkers().then((_) {
//TODO: add makrers as you whish;
});
}
So, if you do any operations with the markers add/remove/update, you should be sure that the previous operation that involved markers is completed.
If anyone still struggling with removing a specific marker try this method;
MarkerId id = MarkerId("Pickup");
//markers[id] = {} as Marker; clear all markers
markers.removeWhere((key, value) => key == id); //clear a specific marker
I am currently working on a Leaflet Project where I use external geojson files as data input. Since the json contains a lot of objects I would like to use the MarkerCluster plugin which I got from Mappbox:
<script src='https://api.tiles.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/leaflet.markercluster.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.css' rel='stylesheet' />
<link href='https://api.tiles.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.Default.css' rel='stylesheet' />
Displaying the json-layer without the clustering works just fine, but if i try to assign it to the cluster nothing is displayed.
var markersBar = L.markerClusterGroup();
var barLayer = new L.GeoJSON.AJAX("json/eat_drink/bar.geojson", {
pointToLayer: function(feature, latlng) {
var icon = L.icon({
iconSize: [27, 27],
iconAnchor: [13, 27],
popupAnchor: [1, -24],
iconUrl: 'icon/' + feature.properties.amenity + '.png'
});
return L.marker(latlng, {icon: icon})
},
onEachFeature: function(feature, layer) {
layer.bindPopup(feature.properties.name + ': ' + feature.properties.opening_hours);
}
});
markersBar.addLayer(barLayer);
console.log(markersBar);
map.addLayer(markersBar);
The console.log output lets me assume that there are no objects, but I don't get it why.
Object { options: Object, _featureGroup: Object, _leaflet_id: 24, _nonPointGroup: Object, _inZoomAnimation: 0, _needsClustering: Array[0], _needsRemoving: Array[0], _currentShownBounds: null, _queue: Array[0], _initHooksCalled: true }
What am I doing wrong?
Well it looks like you are using Leaflet-Ajax...so an async request is made to grab your geojson..and your immediate next line is markersBar.addLayer(barLayer);..which would contain nothing since the request is almost certainly not complete yet...
Instead, I believe you can use the loaded event provided in the documentation like
barLayer.on('data:loaded', function () {
markersBar.addLayer(barLayer);
console.log(markersBar);
map.addLayer(markersBar);
});
For anyone looking for a straight forward example for adding a marker cluster with geojson ajax to a map, binding pop-ups and adding to layer control:
// pop-up function
function popUp(f, l) {
var out = [];
if (f.properties) {
for (key in f.properties) {
out.push(key + ": " + f.properties[key]);
}
l.bindPopup(out.join("<br />"));
}
}
// add layer to map and layer control
function add_layer(layr, layr_name) {
map.addLayer(layr);
layerControl.addOverlay(layr, layr_name);
}
// fire ajax request
var points = new L.GeoJSON.AJAX("../data/points.geojson", { onEachFeature: popUp });
// create empty marker cluster group
var markers = L.markerClusterGroup()
// when geojson is loaded, add points to marker cluster group and add to map & layer control
points.on('data:loaded', function () {
markers.addLayer(points);
add_layer(markers, "Point Markers")
});
I have an observableArray with some markers, for example:
var markers = ko.observableArray([
{
id: 0,
title: ko.observable("Marker 0"),
lat: ko.observable(55.31),
lng: ko.observable(11)
},
{
id: 1,
title: ko.observable("Marker 1"),
lat: ko.observable(57.20),
lng: ko.observable(15.5)
}
]);
This array is sent to some MapWidget object, that has to create google map markers for each element. It has to move markers in case lat,lng observables change, change marker's title in case title observable changes and so on.
That means in MapWidget there's some array of googlemap markers, and it should be connected with the given observableArray. What is the best and the simpliest way to connect them?
Upd. More details about MapWidget.
MapWidget is some object that has an access to some google maps map object, and it receives as an argument an observableArray with markers like that one above.
var MapWidget = function(markers) {
var div = $("#map").get(0);
this.map = new gmaps.Map(div);
/*
The magic goes here:
markers is an observableArray, we subscribe for it's changes,
create gmaps.marker for each new element,
destroy in case of destroying them from array,
move and rename each marker in case of corresponding changes
*/
}
You could subscribe to your array like this:
ar.subscribe(function() {
// clean and redraw all markers
});
If you do that, you will receive a notification when an item is added/removed to/from the array. BUT not when an property of an item is modified.
If you want to update your google maps markers based on individual property changes in items, you could implement a simple dirty flag mechanism and then subscribe individually to each item. Since each item has an id, which I presume is unique, you could create a map with key/value pairs being the id and the map widget.
So, given each individual item:
var item = function(data) {
var self = this;
self.isChanged = ko.observable(self);
self.id = data.id;
self.title = ko.observable(data.title);
self.title.subscribe(function() { self.isChanged(self); self.isChanged.valueHasMutated(); });
self.lat = ko.observable(data.lat);
self.lat.subscribe(function() { self.isChanged(self); self.isChanged.valueHasMutated(); });
self.lng = ko.observable(data.lng);
self.lng.subscribe(function() { self.isChanged(self); self.isChanged.valueHasMutated(); });
}
And given a hypothetic map where you keep a link between your markers and the items:
var markersMap = [];
markersMap[0] = yourGoogleMapWidget;
You can then subscribe to track changes on items like this:
ar[0].isChanged.subscribe(function(item) {
var myGMapMarker = markersMap[item.id()];
// update your marker, or destroy and recreate it...
});
I am trying create a restriction on the movement of an editable polygon. I want to prevent the inside path from being pulled outside of outer path. I am using Google Maps google.maps.geometry.poly.containsLocation function to check if the new point is within the outer bounds but I can't find a way to stop the action from happening if it is outside.
I have tried returning false but the polygon still goes to the new location
google.maps.event.addListener(poly.getPaths().getArray()[1], 'set_at', function() {
return keepInside(this, arguments[0], arguments[1]);
});
function keepInside(polygon, index, new_point)
{
outer_edge = new google.maps.Polygon({
paths: polygon.getArray(),
});
is_in = google.maps.geometry.poly.containsLocation(new_point,outer_edge);
if(!is_in)
{
return false;
}
return true;
}
You got pretty close with your original code. Instead of returning false, you could set the point back to it's original position. Also, the second argument passed to the set_at listener is not the new point but the old point. Try this:
google.maps.event.addListener(poly.getPaths().getArray()[1], 'set_at', function(index, oldPoint) {
return keepInside(this, index, this.getAt(index), oldPoint);
});
function keepInside(polygon, index, newPoint, oldPoint)
{
outer_edge = new google.maps.Polygon({
paths: polygon.getArray(),
});
if(!google.maps.geometry.poly.containsLocation(newPoint, outer_edge))
{
polygon.setAt(index, oldPoint);
}
}
I have a web app with a map in it. I've added a nice little custom map control to turn on and off different layers on the map. Currently there are only two layers, and it all works nice and fine in most browsers.
Except for IE8+7. None of the layers are showing on the map when turned on. As far as I can tell the map is loading the kmz/kml files (when preserveViewport is set to false, the map moves to the right location) but they're just not appearing. One layer contains polylines, and the other contains markers. The code I use is below:
function someFunction() {
//code to initialise map etc goes here...
var layers = [];
//Create 1st layer
var exchangeslayer = new google.maps.KmlLayer('http://link.to.file/exchanges.kmz'
suppressInfoWindows: true,
preserveViewport: true
});
layers.push({name: "Exchanges", layer: exchangeslayer});
//Code to create second layer
var nyclayer = new google.maps.KmlLayer('http://www.nyc.gov/html/dot/downloads/misc/cityracks.kml'
suppressInfoWindows: true,
preserveViewport: false
});
layers.push({name: "NY City Tracks", layer: nyclayer});
addCustomLayerControls(layers);
}
function addCustomLayerControls(layers) {
//there is code here that would generate the divs for the custom map control
var container; //container is a div element created via javascript
for (var i = 0; i < layers.length; i++) {
this.addLayerLabelToContainer(layers[i], container);
}
//some more code
}
function addLayerLabelToContainer(layer, container) {
var map; //Assume I get a reference to the map
//some code here to make pretty labels for the map controls...
var layerLabel; // layerLabel is a div element created via javascript
google.maps.event.addDomListener(layerLabel, 'click', function() {
if(layer.layer.map == null) {
layer.layer.setMap(map);
} else {
layer.layer.setMap(null);
}
});
}
So as it turns out my problem related to CSS. One of my stylesheets was applying max-width: 100% to all img tags. This was playing havok with the map markers/polylines.
Its obvious now that I see it, but when you think the problem is to do with the javascript its not so obvious. As such, I'll leave this answer here for anyone else who makes the same mistake as me.
If you modify addLayerLabelToContainer() like this then it works in IE as expected. Verified it loads KMZ correctly in IE 8 and 9.
function addLayerLabelToContainer(layer, container) {
// var map; //Assume I get a reference to the map
//some code here to make pretty labels for the map controls...
var layerLabel; // layerLabel is a div element created via javascript
if(layer.layer.map == null) {
layer.layer.setMap(map);
} else {
layer.layer.setMap(null);
}
}
Don't need to invoke addDomListener(). Also note the API syntax:
addDomListener(instance:Object, eventName:string, handler:Function)
Also minor fix of syntax errors in someFunction as follows:
function someFunction() {
// var map; //assume map is initialised, I've just removed that code
var layers = [];
// see https://developers.google.com/maps/documentation/javascript/layers
//Create 1st layer
var exchangeslayer = new google.maps.KmlLayer(
'http://kml-samples.googlecode.com/svn/trunk/kml/kmz/simple/big.kmz',
{ suppressInfoWindows: true, preserveViewport: true
});
layers.push( {name: "Exchanges", layer: exchangeslayer} );
// ...
addCustomLayerControls(layers);
}