I have several points on a layer and all might have different styles associated with them. So I'm doing
VectorFeature pointFeature = new VectorFeature(point,pointStyle)
It all works fine until I do the select(i.e. click the point). When I do a select, the points are not highlighting. The point highlighlights if I remove the pointStyle from the VectorFeature, i.e.,
VectorFeature pointFeature = new VectorFeature(point)
I tried using StyleMap on the layer but ended up getting the same result.
What could possibly be the solution to this problem?
Related
I'm trying to add clustering and layer control to filter markers on my map. After reading older posts on this issue, the code that was marked as the right answer looks like this. However, no matter how I change it, it does not work on my map.
var parent= new L.MarkerClusterGroup().addTo(map);
var overlay={}
overlay["Markers A"]=L.featureGroup.subGroup(parent,aPoints).addTo(map);
overlay["Markers B"]=L.featureGroup.subGroup(parent,bPoints).addTo(map);
control = L.control.layers(null, overlay, {collapsed: false });
control.addTo(map);
What am I doing wrong?
The issue that I was having was that L.featureGroup.subGroup takes in an array of markers as it's second parameters therefore, aPoints needed to be [aPoints].
I am setting up a GeoJSON layer and on top of it a MarkerCluster layer
this.itemLayer = L.geoJson(items, layerOptions)
this.clusterLayer = L.markerClusterGroup()
this.clusterLayer.addLayer(this.itemLayer)
this.clusterLayer.addTo(this.map)
Upon update I am doing:
this.itemLayer.clearLayers()
this.itemLayer.addData(newItems)
this.clusterLayer.refreshClusters(this.itemLayer)
But the clusters do not appear, nor do the items in the itemLayer
Solution
this.itemLayer.clearLayers()
this.itemLayer.addData(this.props.items)
this.clusterLayer.clearLayers()
this.clusterLayer.addLayer(this.itemLayer)
Leaflet.markercluster does not keep track of Layer Groups (like your this.itemLayer GeoJSON layer group) unfortunately. When passed a group to clusterLayer.addLayer(), MCG will extract all individual (i.e. non-group) layers from that group, and forget any reference to the group.
See also Leaflet.markercluster issue #647.
Therefore when clearing your group with this.itemLayer.clearLayers(), it effectively removes all children from this.itemLayer, but this.clusterLayer is unaffected.
Similarly when adding data to this.itemLayer, that group creates new child layers, but MCG is unaffected.
Then when calling this.clusterLayer.refreshClusters(this.itemLayer), none of the child layers of this.itemLayer are part of this.clusterLayer, so it ends up with unexpected effect (maybe just doing nothing special).
If you want to change the clustered layers, make sure to remove them from MCG (e.g. simply do this.clusterLayer.clearLayers()), then add back the new layers into it. You could also remove the current MCG and build a new one.
I'm reading an imageOverlay URL from an ArcGIS webserver that uses the leaflet getBound() coordinates as part of the URL (we have large maps that are filtered for the current window 'extent'). Apologies for not including the actual path (I'm working with sensitive client data). Eg:
http://myarcgiswebserver.com/MapServer/export/dpi=96&format=png32&bbox=27.119750976562504%2C-31.194007509998823%2C32.39044189453126%2C-29.692824739380754&size=1719%2C434
[bbox] = current imageBounds
When dragging my map the imageOverlay url is updated correctly but my leaflet window is no longer aligned to the imageBound values that were set when first adding the imageOverlay which results in a skewed output (this is my assumption):
The only workaround is to remove the existing imageOverlay and add a new one (which ruins the user experience as the map disappears then reappears each time the window is dragged or zoomed).
Am i approaching this problem incorrectly or would the introduction of a function to update the current imageBounds resolve this? Perhaps not a new function but the expansion of setUrl with additional parameters...?
Many thanks for any feedback...
As #ghybs pointed out, your use case might be better served by using the WMS
interface of your ArcGIS server.
Anyway, you say
The only workaround is to remove the existing imageOverlay and add a new one (which ruins the user experience as the map disappears then reappears each time the window is dragged or zoomed).
Well, that glitch is due to you probably doing something like:
Remove old overlay
Add new overlay
Wait until the image is received from the network
Wait one frame so the new overlay is shown
and instead you should be doing something like:
Add new overlay
Wait until the image is received from the network
Remove old overlay
Wait one frame so the new overlay is shown
The problem is just the async wait and the possible race conditions there, but should be easy to hack together, e.g.:
var activeOverlay = null;
var overlayInRequest = null;
map.on('moveend zoomend', {
// If we are already requesting a new overlay, ignore it.
// This might need some additional debouncing logic to prevent
// lots of concurrent requests
if (overlayInRequest) {
overlayInRequest.off('load', showOverlay);
}
overlayInRequest = L.imageOverlay( computeUrl( map.getBounds() ), myOverlayOptions );
overlayInRequest.on('load', showOverlay);
});
function showOverlay(ev) {
activeOverlay.remove();
activeOverlay = overlayInRequest;
activeOverlay.addTo(map);
overlayInRequest = undefined;
}
If you use an ImageOverlay but change its url dynamically, with a new image that reflects a new bounding box, then indeed that is the reason for the behaviour you describe: you display an image that has been generated using a new bbox, but positioned in the initial bbox, since the image overlay remains at the same geographical position on the map.
Instead, it sounds to me that you should use a TileLayer.WMS.
It would automatically manage the bounding box update for you. You may need to find the correct options to fit your service provider required URL syntax, though.
Example: http://playground-leaflet.rhcloud.com/yel/1/edit?html,output
I have built a bokeh app that allows users to select windows in data and run python code to find and label (with markers) extreme values within these limits. For ease of interaction, I use the box select tool for the range selection. My problem arises when repeating this process for subsequent cases. After markers are placed for the results, they are rendered invisible by setting alpha to zero and another case needs to be chosen. When the new select box includes previous markers, they become visible based on the selection. How do I override this default behavior? Can markers be made unselectable? or can I add code to the customJS to hide them after they are selected?
Thanks in advance for any help!
There are a few possible approaches. If you just want non-selected glyphs to "disappear" visually, you can set a policy to do that as described here:
http://docs.bokeh.org/en/latest/docs/user_guide/styling.html#selected-and-unselected-glyphs
Basically, for bokeh.plotting, pass
nonselection_fill_alpha=0.0,
nonselection_line_alpha=0.0,
as arguments to your plot.circle call or whatever. Or if you are using the low level bokeh.models interface, something like:
renderer.nonselection_glyph = Circle(fill_alpha=0.0, line_alpha=0.0)
But be aware (I think you already are) that the invisible markers are still there, and still selectable if the user happens to draw a box over them with the selection tool.
If you truly want only a subset of the data to be visible and selectable after a selection, I'd say you want to replace the data in the column data source wholesale with the subset in your selection callback.
This must be really simple, but I can't seem to get, how one could fix together two bodies in cannon.js. I have experimented with different types of constraints no (first I thought, LockConstraint should be exactly what I need, being desribend as "removing all degrees of freedom").
What I want to achieve is to "stick together" several bodies so that they rotate/behave together if one of them moves/rotates, e.g. like a hammer to its shaft, but absolutely "fix". (The constraints behave a little like if the bodies were connected with rubber bands, even if applying a very high "maxForce" option)
How would I do that? Is body.addShape() the right direction..?!
Thanks a lot for any hints.
If you want two shapes to always have the same relative transform, you should put them in the same Body.
This example code creates a body with two boxes in it, at X=2 and X=-2 locally in the Body, relative to the center of mass.
var body = new CANNON.Body({ mass: 1 });
var shapeA = new CANNON.Box(new CANNON.Vec3(1,1,1));
body.addShape(shapeA, new CANNON.Vec3(2,0,0), new CANNON.Quaternion());
var shapeB = new CANNON.Box(new CANNON.Vec3(1,1,1));
body.addShape(shapeB, new CANNON.Vec3(-2,0,0), new CANNON.Quaternion());
Also see the compound demo: http://schteppe.github.io/cannon.js/demos/compound.html