OpenLayers I am not able to drag the custom features - javascript

Following the query here:
Openlayers can't modify drawn features
I have built some code, which allowes me to edit nodes of my drawn features:
var modifyInteraction = new ol.interaction.Modify({
features: selectInteraction.getFeatures(),
deleteCondition: function(event) {
return ol.events.condition.shiftKeyOnly(event) &&
ol.events.condition.singleClick(event);
}
});
map.addInteraction(modifyInteraction);
However I have lost the option for dragging my features, which is defined by this code:
var translateInteraction = new ol.interaction.Translate({
features: selectInteraction.getFeatures(),
});
map.addInteraction(translateInteraction);
The new ol.interaction.Translate({ has been switched off, otherwise I am not able to edit my features, but I can only drag them.
Is there any chance to make my features draggable when I can edit them like defined in the code new ol.interaction.Modify({ above?
My full JSfiddle is here:
https://jsfiddle.net/g196cqoa/

You can add a condition option to the translate interaction to only interact when ctrl key is pressed.
var modifyInteraction = new ol.interaction.Modify({
features: selectInteraction.getFeatures(),
deleteCondition: function(event) {
return ol.events.condition.shiftKeyOnly(event) &&
ol.events.condition.singleClick(event);
},
});
map.addInteraction(modifyInteraction);
const translate = new ol.interaction.Translate({
features: selectInteraction.getFeatures(),
condition: function (event) {
return ol.events.condition.platformModifierKeyOnly(event) &&
ol.events.condition.primaryAction(event);
},
});
map.addInteraction(translate);
Alternatively, if you add the translate interaction before the modify interaction it should allow you to drag polygons as long as you stay away from the edges. This won't work with lines and points. as there is no area where the geometry cannot be modified.
The order in which the interactions are added to the maps interaction collection determines whether the modify interaction is allowed see and handle the events before the translate interaction handles them

Related

Azure maps cluster position discrepancies

I've got a list of positions that I retrieve from an ms endpoint like so:
https://atlas.microsoft.com/search/fuzzy/json?top=100&typeahead=true&subscription-key=subscription-key&api-version=1&query=Leeds
The user then selects one of the proposed addresses and the position provided by this endpoint is then used to be displayed on a map that uses clusters. So for Leeds for example, I have the following:
-1.548567, 53.801277
However, when I create the clusters in the clusterRenderCallback function I provide upon creating the HtmlMarkerLayer, I get positions that are close to the ones I've provided, but different and I have no idea how or why.
so the code would look something like:
First I create the dataSource
dataSource = new atlas.source.DataSource(null, {
//Tell the data source to cluster point data.
cluster: true
});
map.sources.add(dataSource);
Then I manage the cluster creation inside the HtmlMarkerLayer creation:
clusterRenderCallback: function (id, position, properties) {
var cluster = new atlas.HtmlMarker({
position: position, // different position to that which I have provided
htmlContent: `<div>${properties.point_count_abbreviated}</div>`,
values: properties,
});
map.events.add('click', cluster, clusterClicked);
return cluster;
}
And here I create points to add to my data source:
let features = list.map(x => new atlas.data.Feature(new atlas.data.Point(new atlas.data.Position(x.lon, x.lat)), x));
dataSource.add(features);
The position I receive for the Leeds cluster for example is -1.549072265625, 53.80065082633024, even though I had 2 poisitions in Leeds, both made out of the same coordinates: -1.548567, 53.801277
It seems like there's some sort of mechanism inside the atlas code that "fixes" the provided coordinates; anyone knows how to stop this or what am I doing wrong here?
==EDIT 02/05==
ok, so following #rbrundritt answer, here the last bit of code I should have added, showing what we do once the cluster is clicked:
function clusterClicked(e) {
var cluster = e.target;
datasource.getClusterExpansionZoom(cluster.properties.cluster_id).then(function (zoom) {
map.setCamera({
center: cluster.getOptions().position,
zoom: zoom
});
});
}
And this is where we have our problem with this discrepancy- clicking on the cluster zooms in to the zoom level where the cluster breaks; however, since we centre the map to the cluster position, the pin position, being different to the cluster one, is not being seen in the map on that zoom level (ie 3 afair). On top of that we have no way of knowing inside the context of this function to what pin does the cluster corresponds, this leaves us with a buggy behaviour.
Clusters should rarely have the same coordinates as any points that they contain. Clusters group overlapping points together and an average position is used to represent that group on the map. When a cluster breaks apart into its individual points then that marker will have the original position value.
Ok, so I wasn't aware of what the datasource.getClusterLeaves method was returning (I've simply mistaken the leaves for the verb leaving). This is what I was looking for, so my code now looks like this:
function inSamePosition(pos1, pos2) {
return pos1.data.geometry.coordinates[0] == pos2.data.geometry.coordinates[0]
&& pos1.data.geometry.coordinates[1] == pos2.data.geometry.coordinates[1];
}
function clusterClicked(e) {
var cluster = e.target;
(cluster.properties.cluster_id, Number.POSITIVE_INFINITY, 0).then(pins => {
let position = pins.every(p => inSamePosition(p, pins[0])) ? pins[0]['data'].geometry.coordinates : null;
datasource.getClusterExpansionZoom(cluster.properties.cluster_id).then(function (zoom) {
map.setCamera({
center: position ? position : cluster.getOptions().position,
zoom: zoom
});
});
})
}

Fabric.js - how to use custom cursors without drawing mode

I have no idea how to set up cursor image for drawing on the Canvas. I have noticed that I can set it only when
FABRICCANVAS.isDrawingMode = true;
However, the problem is that I have created dedicated drawing tools and I don't want to use those that are built into the Fabric.js.
Sample of my code (which doesn't work properly):
const FABRICCANVAS = new fabric.Canvas('canvas-draft');
const DRAFT = document.querySelector(".upper-canvas");
button.addEventListener('click', () => {
DRAFT.style.cursor = 'url(img/cursors/image.png) 0 34, auto';
});
But when I set isDrawingMode to true, it works. Unfortunately, I don't want to use built-in drawing tools because they leave paths (that can then be moved later, when FABRICCANVAS.selection = true).
Do you know any solution for this problem?
For the Canvas you can set different cursors:
e.g.
canvas.hoverCursor
canvas.defaultCursor
canvas.moveCursor
You can use absolute or relative paths to your cursor image:
canvas.moveCursor = 'url("...") 10 10, crosshair';

Openlayers 3: interactions on loaded vector features

When I use map Interactions as from this example, creating features collection from scratch everithing goes well:
var features = new ol.Collection();
but when I try to define map interaction on imported features:
var geojsonObject = { ...a well defined (visible) GeoJSON object ...};
var features = new ol.format.GeoJSON().readFeatures(geojsonObject)
I get the following exception:
Error: addEventListener and attachEvent are unavailable. (ol.js:34:302)
when I use features collection in modify interaction definition:
modifyInteraction = new ol.interaction.Modify({
features: features,
deleteCondition: function(event) {
return ol.events.condition.shiftKeyOnly(event) &&
ol.events.condition.singleClick(event);
}
});
Are you attaching the features to a Vector source and to a f.ex ol.layer.Vector?
this line of code
var features = new ol.format.GeoJSON().readFeatures(geojsonObject)
returns an array of features and not an ol.Collection of features.
On the other hand ol.interaction.Modify expects to get features parameter as an ol.Collection of features. I suspect this is where your error comes from.
Try to chcnge the above line of code to this
var features = new ol.Collection(new ol.format.GeoJSON().readFeatures(geojsonObject));
Note that all the above have impact to the latest version of ol3.

Restricting pointermove interactions to two layers in openlayers 3

In openlayers version v3.6 running in Chrome on Ubuntu
I have create a map with several layers (foo, bar, beltch) in it using the syntax:
layers:[foo,bar,beltch],
I would like to limit interactions to the layers foo and bar
The api documents at http://openlayers.org/en/master/apidoc/ol.interaction.Select.html
suggest using the following syntax
var selectPointerMove = new ol.interaction.Select({
condition: ol.events.condition.pointerMove,
layers:[foo,bar]
});
But I seem to get events for all layers, I have checked the examples and nothing seem to cover this area unless I have overlooked something.
Does anybody have any suggestions
Use filter instead of layers. And make sure you set a layer property to compare later.
var layerFeatures = new ol.layer.Vector({
name: 'selectable',
source: sourceFeatures
});
var hoverInteraction = new ol.interaction.Select({
condition: ol.events.condition.pointerMove,
filter: function(feature, layer){
if(layer.get('name') === 'selectable')
return true;
}
});

Is there a way to disable rotation in OpenLayers 3?

I am currently upgrading my OpenLayers 2 Mapview to OpenLayers 3. I really like the new OpenLayers client, but i wanted to deactivate the ability to rotate the map on mobile devices (rotating with 2 fingers).
But I can't find any settings for this. Is this not possible or am I only to dumb to find the setting?
I am using the current release version (3.0.0) of the openlayers javascript client. (https://github.com/openlayers/ol3/releases/tag/v3.0.0)
Yes there is a way to deactivate the ability to rotate the map.
You need to customize the interactions of the ol.Map object. Either you use the ol.interaction.defaults function to create an ol.Collection with interactions or you create an array with only the interactions you want. Then you can pass it to the constructor of ol.Map.
Using the ol.interaction.defaults function (http://openlayers.org/en/master/apidoc/ol.interaction.html#defaults):
var interactions = ol.interaction.defaults({altShiftDragRotate:false, pinchRotate:false});
var map = new ol.Map {
interactions: interactions
};
The first line creates all default interactions but the ability to rotate via keyboard+mouse and using fingers on a mobile device.
You maybe want to remove the ol.control.Rotate then, too. (This is the needle in the upper right which is used to reset the rotation and only appears if the map is rotated). Works the same way.
Creating controls without compass via ol.control.defaults (http://openlayers.org/en/master/apidoc/ol.control.html#defaults)
var controls = ol.control.defaults({rotate: false});
'Full' code:
var controls = ol.control.defaults({rotate: false});
var interactions = ol.interaction.defaults({altShiftDragRotate:false, pinchRotate:false});
var map = new ol.Map {
controls: controls,
interactions: interactions
};
In the current version of OpenLayers 3 you can simply disable the enableRotation flag of the view object:
view: new ol.View({
...
enableRotation: false
})

Categories

Resources