select event for getting coordinate in openlayers3 - openlayers-3

I would like you use select interaction to add a feature, but the e.coordinate shows undefined.
var select = new ol.interaction.Select({
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#0288D1',
width: 2
})
})
});
map.addInteraction(select);
select.on('select', function(e) {
var feat = new ol.Feature({
geometry: new ol.geom.Point(e.coordinate),
style: style1
});
alert(e.coordinate);
feat.setStyle(style1);
layerVector.getSource().addFeature(feat);
});
If someone know the reason, tell me how to get the coordinate when i click on viewer with this select interaction.

UPDATE
What you ask in comments (about listeners) can be easier if you become a friend of API Docs. In my beginning it was very hard to know them all, but the docs are much, much better so let it be your source.
Each part of OpenLayers has its own listeners, so, for instance, click at ol.Map, scroll to the "Fires:" section and you'll see the several listeners, the same with ol.View and so forth.
To get clicked coordinate inside ol.interaction.Select listener use:
select.on('select', function(evt){
var coord = evt.mapBrowserEvent.coordinate;
console.info(coord);
// ...
});

Related

OpenLayers 3 - Get applied style for rendered feature

Is it possible to get the applied style for a selected feature? My layer uses a style function instead of an ol.style.Style. When I call myFeature.getStyle() it returns the function.
Updating my question with some things that I have tried so far based on responses here and elsewhere.
I ended up creating a select style function for each layer.
This doesn't work, no style is returned:
selectInteraction = new ol.interaction.Select( {
style: function( feature, resolution ) {
if ( feature.selectStyle ) {
return feature.selectStyle;
}
},
layers: mylayers
} );
Also, with the above I get the following error:
Uncaught TypeError: style.getImage is not a function
ol.renderer.vector.renderFeature #ol.js:38455
ol.renderer.canvas.VectorLayer.renderFeature #ol.js:44202
renderFeature #ol.js:44148
ol.renderer.canvas.VectorLayer.prepareFrame #ol.js:44164
ol.renderer.canvas.Map.renderFrame #ol.js:45268
ol.Map.renderFrame_ #ol.js:52034
(anonymous function) #ol.js:50898
This does work, the feature is rendered using my select style. However, I don't want to have to manage re-setting styles, so it really needs to be implemented in the selectInteraction:
evt.selected.forEach( function( evt ) {
evt.setStyle( evt.selectStyle );
}, this );
My workaround was to create the style separately from the feature and then use setStyle() to apply it. I also saved the style elsewhere in the feature so it could be retrieved later.
let myStyle = new ol.style.Style({
image: new ol.style.RegularShape({
fill: new ol.style.Fill({
color: 'cyan'
}),
stroke: new ol.style.Stroke({
color: 'black',
width: 1
}),
points: 4,
radius: 9,
angle: Math.PI / 4
}),
});
myFeature.setStyle(myStyle);
myFeature.set('myStyle', myStyle); // save it for later use
During the 'select' process simply use:
feature.get('myStyle');
to retrieve the style that was applied to the feature.
You should call the function with the feature (and optionally the resolution if your style function depends on it). So something like: myFeature.getStyle().call(this, feature); or myFeature.getStyle().call(this, feature, resolution);
I think you must use myFeature.getStyleFunction() instead of myFeature.getStyle().
Good Luck.

ol.style.Circle with ol.layer.Vector throws error

I draw features on a map (WKT POINTs). Now I would like to give those points a radius. Before I even add Features and the layer to the map I do the following:
var src = new ol.source.Vector();
var layer = new ol.layer.Vector({
source: src,
style: new ol.style.Circle({
radius: 30
})
});
This throws the following error:
AssertionError: Assertion failed: obj geometry must be an ol.style.Style instance
at goog.asserts.DEFAULT_ERROR_HANDLER (http://localhost:33464/app/lib/openLayers/ol-debug.js:4330:52)
at goog.asserts.doAssertFailure_ (http://localhost:33464/app/lib/openLayers/ol-debug.js:4365:3)
at goog.asserts.assertInstanceof (http://localhost:33464/app/lib/openLayers/ol-debug.js:4575:5)
at ol.style.createStyleFunction (http://localhost:33464/app/lib/openLayers/ol-debug.js:56402:7)
at ol.layer.Vector.prototype.setStyle (http://localhost:33464/app/lib/openLayers/ol-debug.js:58228:3)
at ol.layer.Vector (http://localhost:33464/app/lib/openLayers/ol-debug.js:58115:3)
If instead I add the same style to the "new ol.layer.Tile" I'm using to display the OpenStreetMap (ol.source.OSM) in the background everything works perfect:
map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
style: new ol.style.Circle({
radius: 30
})
})
]
});
I don't really understand that. I guess it has something to do with ol.style.Circle extending ol.style.Image (which doesn't sound like something for a vector layer - rather the raster layer "Tile"). But if I add the style to the Tile-Layer, why are the features on the vector-Layer rendering with this style?
My questions:
What is the correct way of doing this?
Is there a "style-Inheritance" going on?
style is not a valid option of the ol.layer.Tile object, thus it is simply ignored. See its documentation: http://openlayers.org/en/v3.10.1/apidoc/ol.layer.Tile.html
The style definition defined in the ol.layer.Vector has to be either of the following:
a ol.style.Style object
an array of ol.style.Style objects
a style function, i.e. ol.style.StyleFunction.
So, in order for your example to work, you could define a style that looks like this:
var src = new ol.source.Vector();
var layer = new ol.layer.Vector({
source: src,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
fill: new ol.style.Fill({color: 'red'})
})
})
});
This example demonstrates custom style: http://openlayers.org/en/v3.10.1/examples/custom-interactions.html
See also the API documentation: http://openlayers.org/en/v3.10.1/apidoc/ol.layer.Vector.html

Selectable Points of vector layer have an offset

I've got a vector layer with a GeoJSON source, consisting of Points and a LineString. When I click on a point I want to open a popup with additional information.
Here's some code:
var style = {
'Point': [new ol.style.Style({
image: new ol.style.Circle({
fill: new ol.style.Fill({
color: 'rgb(255,0,0)'
}),
radius: 5,
stroke: new ol.style.Stroke({
color: '#000000',
width: 1
}),
})
})],
'LineString': [new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ff0000',
width: 3
})
})],
'MultiLineString': [new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#0000ff',
width: 3
})
})]
};
var map = new ol.Map({
target: 'map-ol-canvas',
interactions: ol.interaction.defaults({mouseWheelZoom: false}),
layers: [new ol.layer.Tile({ source: new ol.source.OSM() })],
view: new ol.View({
zoom: 8,
maxZoom: 16
})
});
map.getView().fit(extent, map.getSize());
var trackSource = new ol.source.Vector({
url: '/test.geojson',
format: new ol.format.GeoJSON()
});
var track = new ol.layer.Vector({
source: trackSource,
style: function(feature, resolution) {
return style[feature.getGeometry().getType()];
}
});
map.addLayer(track);
var select = new ol.interaction.Select({
filter: function (feature, layer) {
return feature.getGeometry().getType() === 'Point';
}
});
map.addInteraction(select);
// When user clicks on a waypoint, show a tooltip.
function onMouseClick(browserEvent) {
var coordinate = browserEvent.coordinate;
var pixel = map.getPixelFromCoordinate(coordinate);
map.forEachFeatureAtPixel(pixel, function(feature) {
if (feature.getGeometry().getType() === 'Point') {
console.log(feature.get('date'));
}
});
}
map.on('click', onMouseClick);
The problem:
When I click directly on a point nothing happens. When I click a couple of pixels below and a bit right or left (depends on zoom level!), the point gets selected and the console.log is triggered.
I can fix this by using Firebox WebDeveloper Addon and activating "Disable all styles".
However, when I manually remove all CSS one by one that behavior never goes away.
In the first place I thought this might be some inherited padding or margin, but currently I think the canvas shouldn't be affected by any CSS at all.
Any ideas about what could be wrong?
I'm experiencing the same issue. It appears to be linked to navigating to the page from a specific modal (I'm using ajax hash paging). The footer doesn't load and after I interact with the first feature on the map the following happens;
The map jumps and stretches/smears slightly
The footer shows up on my page
The vertical scroll bar appears
The issue doesn't seem to occur when i link from another page.
I have the same problem.Here are some advices may help you:
check the the size of map's container(may be a Div).
check the size of map(openlayers's map object).
compare that two size to confirm whether the two size are equal.
if not, you can use the map.setSize([width,height])to adjust the map's size.

Drag a feature POLYGON OL3

I try to find code to drag a polygon (not modify)....OL3
polygon is created by code (bbox for print area).
can anybody shere code?
var format = new ol.format.WKT();
var feature = format.readFeature(wkt2);
selectInteraction = new ol.interaction.Select({style: styles});
map.addInteraction(selectInteraction);
selectInteraction.getFeatures().push(feature);
modifyInteraction = new ol.interaction.DragAndDrop({
features: selectInteraction.getFeatures()
});
map.addInteraction(modifyInteraction);
vector = new ol.layer.Vector({
style: styles,
source: new ol.source.Vector({
features: [feature]
})
});
map.getLayers().insertAt(1000, vector);
See the drag features example here: http://openlayers.org/en/v3.4.0/examples/drag-features.html
Also there is work in progress on a Translate interaction see: https://github.com/openlayers/ol3/pull/3250
This extension called Transform Interaction work fine with dragging. It also has support for rotating, stretching and scaling. It is definitely worth a look!

Loading Fusion Tables InfoWindow data in a div outside map

I hope someone can help with what is probably a fairly simple query. I have seen a question on here about trying to do this without a mouseclick, but I want to add an event listener to the markers on the Fusion Table map that will load the infoWindow content in a separate div below the map. So far I have suppressed the infoWindow, but I'm a bit lost on the next step of adding the click, retrieving the data relevant to that marker and loading into the div.
The marker display is limited to markers within a set radius of the user's location, in order to reduce load time.
I'm assuming I need to start with something like this:
google.maps.event.addListener(layer, 'click', function() {
I'd be grateful for any clues.
Here's the relevant bit of my code so far:
var tableid = '[ID]';
var layer = new google.maps.FusionTablesLayer({
query: {
select: 'Location',
from: tableid,
where: 'ST_INTERSECTS(Location, CIRCLE(LATLNG'+marker.position+', 2000))'
},
options: {
suppressInfoWindows: true
}
});
var circle = new google.maps.Circle({
map: map,
radius: 2000,
fillOpacity: 0.1,
strokeOpacity: 0,
clickable: false
});
circle.bindTo('center', marker, 'position');
layer.setMap(map);
});
EDIT:
For everyone's amusement, this is what I've tried so far:
google.maps.event.addListener(layer, "click", function () {
$('#infoWindowDiv').append('new google.maps.infoWindowHtml');
});
It probably comes as a surprise ot no-one that it doesn't work. But hey, at least I'm trying! Thanks
EDIT 2:
I'm delighted to say I have found a solution that works - which I post here for anyone else who might have the same problem/goal:
google.maps.event.addListener(layer, "click", function (e) {
document.getElementById("infoWindowDiv").innerHTML = e.infoWindowHtml;
});
I'm delighted to say I have found a solution that works - which I post here for anyone else who might have the same problem/goal:
google.maps.event.addListener(layer, "click", function (e) {
document.getElementById("infoWindowDiv").innerHTML = e.infoWindowHtml;
});

Resources