I want to display on duty taxi positions using openlayers.
I have coordinates and heading of each taxi cab but when I'm trying to display them everything is okay with coordinates but headings aren't displaying properly. It's because I have the same style for every marker and adding them to the same vector layer.
I would like to show each vehicle with its own heading.
Any solutions for this issue will be appreciated.
My code:
var taxiMarker = new ol.style.Style({
image: new ol.style.Icon({
scale: 0.7, anchor: [0.5, 0.5],
src: 'uploads/taxiMarker.png'
})
});
var taxi_vector = new ol.layer.Vector({
source: new ol.source.Vector({
}),
style: [taxiMarker]
});
for(let i = 0; i < res.length; i++) {
let tCoords = res[i][0].split(',');
let heading = parseFloat(res[i][1]);
let marker = new ol.geom.Point(tCoords);
let featureMarker = new ol.Feature(marker);
taxiMarker.getImage().setRotation(heading);
taxi_vector.getSource().addFeature(featureMarker);
}
Related
I am working on openlayers, there is an issue when I try to add a linestring on the map which crosses the dateline several times.
To display the linestring across two worlds in the continuous segment I have added a function HandleDateline() which returns me modified (shifted either to left or right world) coordinates.
However, when you zoom-in on the left world to current settled view the linestring disappears. Also if you try to move the map to left, the line goes away.
The weird thing is if the line crosses more than 1 time, linestring on left worlds disappears otherwise same happens for right worlds. Too observe that, remove either first 3 or last 3 points from datelinecrossing[] which I will be posting down.
I am expecting a continuous linestring crossing the international dateline without any issues like disappearing.
If there is a better approach to this, I am open to all ideas.
Here is the bin : ol dateline problem
You have to split the lines crossing the dateline programmatically at the dateline.
var points = [
[-170, -10],
[170, 0],
[-170, 10]
];
var vectorSource = new ol.source.Vector();
vectorSource.addFeature(createFeature(points));
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
width: 2,
color: "red"
})
})
});
var osmLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
var map = new ol.Map({
layers: [osmLayer, vectorLayer],
target: document.getElementById("map"),
view: new ol.View({
center: ol.proj.transform([180, 0], "EPSG:4326", "EPSG:3857"),
zoom: 3
})
});
var graticule = new ol.Graticule({
strokeStyle: new ol.style.Stroke({
color: "rgba(255,120,0,0.9)",
width: 1.5,
lineDash: [0.5, 4]
}),
showLabels: true
});
graticule.setMap(map);
// -------------------------------------------------
function createFeature(points) {
var pointsSplitted = [];
var pointsArray = [];
pointsSplitted.push(points[0]);
var lastLambda = points[0][0];
for (var i = 1; i < points.length; i++) {
var lastPoint = points[i - 1];
var nextPoint = points[i];
if (Math.abs(nextPoint[0] - lastLambda) > 180) {
var deltaX = xToValueRange(nextPoint[0] - lastPoint[0]);
var deltaY = nextPoint[1] - lastPoint[1];
var deltaXS = xToValueRange(180 - nextPoint[0]);
var deltaYS;
if (deltaX === 0) {
deltaYS = 0;
} else {
deltaYS = deltaY / deltaX * deltaXS;
}
var sign = lastPoint[0] < 0 ? -1 : 1;
pointsSplitted.push([180 * sign, nextPoint[1] + deltaYS]);
pointsArray.push(pointsSplitted);
pointsSplitted = [];
pointsSplitted.push([-180 * sign, nextPoint[1] + deltaYS]);
}
pointsSplitted.push(nextPoint);
lastLambda = nextPoint[0];
}
pointsArray.push(pointsSplitted);
var geom = new ol.geom.MultiLineString(pointsArray);
geom.transform("EPSG:4326", "EPSG:3857");
var feature = new ol.Feature({
geometry: geom
});
return feature;
}
function xToValueRange(x) {
if (Math.abs(x) > 180) {
var sign = x < 0 ? -1 : 1;
return x - 2 * 180 * sign;
} else {
return x;
}
}
html,
body,
#map {
width: 100%;
height: 100%;
overflow: hidden
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<body>
<div id="map" class="map" tabindex="0"></div>
</body>
Simplifying HandleDateline so all coordinates are either in the western part of the normal world or the eastern part of the left world seems to fix it (so if the geometry crosses the date line the extent starts in the left world)
function HandleDateline(array) {
for (var i = 0; i < array.length ; i++) {
if (array[i][0] > 0) {
array[i][0] -= 360;
}
}
}
However in worlds to the right the points west of the dateline then appear to be rendered below to linestring, while those east of the dateline are above it. Moving HandleDateline(datelinecrossing); above datelinecrossing.forEach fixes that.
You might also want to consider using a multipoint geometry for the points (unless you need them to be individually selectable).
HandleDateline(datelinecrossing);
var pdlcrossing = new ol.Feature({
geometry: new ol.geom.MultiPoint(datelinecrossing).transform('EPSG:4326', 'EPSG:3857')
});
drawingSource.addFeature(pdlcrossing);
var dlcrossing = new ol.Feature({
geometry: new ol.geom.LineString(datelinecrossing).transform('EPSG:4326', 'EPSG:3857')
});
drawingSource.addFeature(dlcrossing);
There is still a problem zooming in west of the dateline in the worlds on the right, so I think there will need to be two sets of each geometry, one offset to the left and another 360 degrees to the right:
function PlotGeometries(datelinecrossing){
var pgeom = new ol.geom.MultiPoint(datelinecrossing);
var pdlcrossing = new ol.Feature({
geometry: pgeom.clone().transform('EPSG:4326', 'EPSG:3857')
});
drawingSource.addFeature(pdlcrossing);
pgeom.translate(360,0);
var pdlcrossing2 = new ol.Feature({
geometry: pgeom.transform('EPSG:4326', 'EPSG:3857')
});
drawingSource.addFeature(pdlcrossing2);
var geom = new ol.geom.LineString(datelinecrossing);
var dlcrossing = new ol.Feature({
geometry: geom.clone().transform('EPSG:4326', 'EPSG:3857')
});
drawingSource.addFeature(dlcrossing);
geom.translate(360,0);
var dlcrossing2 = new ol.Feature({
geometry: geom.transform('EPSG:4326', 'EPSG:3857')
});
drawingSource.addFeature(dlcrossing2);
}
Just set an extent to the map view for the part of the world you're working on.
I'm trying to open a popup in a map with markers, getting the markers points from a list where latitude and longitude are given, and they are plotted correctly in the map.
Following https://openlayers.org/en/latest/examples/popup.html I added the code for opening popup, and this is my code:
var container = document.getElementById('popup');
var content = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
var overlay = new ol.Overlay({
element: container,
autoPan: true,
autoPanAnimation: {
duration: 250
}
});
closer.onclick = function() {
overlay.setPosition(undefined);
closer.blur();
return false;
};
// create the map with the proper center
var map = new ol.Map({
controls: ol.control.defaults().extend(
[new ol.control.ScaleLine()]
),
view: new ol.View({
center: ol.proj.fromLonLat([center.long, center.lat]),
zoom: zoom
}),
overlays: [overlay],
layers: [new ol.layer.Tile(
{source: new ol.source.OSM()}
)
],
target: 'mapdiv',
keyboardEventTarget: document
}
);
// the style for the markers
var markerStyle = new ol.style.Style({
image: new ol.style.Icon(/** #type {module:ol/style/Icon~Options} */ ({
anchor: [0.5, 1],
anchorXUnits: 'fraction',
anchorYUnits: 'fraction',
scale: 0.4,
src: 'img/ic_place_void_black_24dp_2x.png'
}))
});
for (i = 0; i < pointList.length; ++i) {
// add the marker
markersList[i] = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([pointList[i].long, pointList[i].lat])),
namesList: pointList[i].mediaNameList
});
// apply the style to the marker
markersList[i].setStyle(markerStyle);
}
// generate the markers vector
var markers = new ol.source.Vector({
features: markersList
});
// generate the markers layer
var markerVectorLayer = new ol.layer.Vector({
source: markers,
});
// add the markers layer to the map
map.addLayer(markerVectorLayer);
/**
* Add a click handler to the map to render the popup.
*/
map.on('singleclick', function(evt) {
var clickedPosition = ol.proj.toLonLat(evt.coordinate);
console.log(clickedPosition);;
overlay.setPosition(ol.proj.fromLonLat(clickedPosition));
});
Now I'm stuck with a unexplicable behaviour; whenever I click, the popup is shown about one screen south-east, whatever zoom level of the map.
The coordinates of clickedPosition (I'm seeing them in the console) are the correct coordinates where I clicked, but the popup is shown in a wrong point, with a shift which is always the same in pixels.
What am I missing?
You can refer overlay positioning for showing features in any world.
follow the link
Is it possible in OpenLayers 3 to create a text label which clones multiple times along a linestring feature, depending on a scale? Something like:
Here you can see, that when we change scale label "IX Corps Blvd" appears twice. How can we implement this?
You can achieve this with style function. My code sample is about making arrows to line string (slightly different case), but I have commented parts necessary to be changed (at least):
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var source = new ol.source.Vector();
var styleFunction = function(feature) {
var geometry = feature.getGeometry();
var styles = [
// linestring
new ol.style.Style({
stroke: new ol.style.Stroke({ // apply street style here
color: '#ffcc33',
width: 2
})
})
];
geometry.forEachSegment(function(start, end) {
var dx = end[0] - start[0];
var dy = end[1] - start[1];
var rotation = Math.atan2(dy, dx);
// arrows
styles.push(new ol.style.Style({
geometry: new ol.geom.Point(end),
image: new ol.style.Icon({ // Use here label, not icon.
src: 'http://openlayers.org/en/v3.17.1/examples/data/arrow.png',
anchor: [0.75, 0.5],
rotateWithView: false,
rotation: -rotation
})
}));
});
return styles;
};
var vector = new ol.layer.Vector({
source: source,
style: styleFunction
});
map.addInteraction(new ol.interaction.Draw({
source: source,
type: /** #type {ol.geom.GeometryType} */ ('LineString')
}));
Some more effort is needed to place titles in correct placements. I left this answer like this to serve a solid starting point for building your feature.
My source:
[1] http://openlayers.org/en/master/examples/line-arrows.html
I have problem with my OpenLayer3 map. When I add some markers to map I want to resize my map and change the zoom so that all markers were set on the screen.
My code looks like:
/** CREATE MARKERS **/
for (var i=0;i<1;i++){
var iconFeature = new ol.Feature({
geometry: new
ol.geom.Point(ol.proj.transform([Math.random()*360-180, Math.random()*180-90], 'EPSG:4326', 'EPSG:3857'))
});
vectorSource.addFeature(iconFeature);
var newBound = ol.Bounds();
newBound.extend([Math.random()*360-180, Math.random()*180-90]);
map.zoomToExtent(newBound);
}
/** MARKER STYLE **/
var iconStyle = [
new ol.style.Style({
image: new ol.style.Icon(/** #type {olx.style.IconOptions} */ ({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 1,
scale: 0.07,
src: 'marker.png'
}))
})
];
/** ADD LAYER VECTOR **/
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: iconStyle
});
/** INIT MAP **/
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
}),
vectorLayer
],
overlays: [overlay],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
Is there a way to zoom the map to markers?
You have some errors in your logic and in some OL references. First you should create an ol.Extent that contains all the markers. Then use the map's view to fit it in.
// create ten random markers
for (var i = 0; i < 10; i++) {
var point = new ol.geom.Point(ol.proj.transform([Math.random() * 50, Math.random() * 50], 'EPSG:4326', 'EPSG:3857'));
var iconFeature = new ol.Feature({
geometry: point
});
vectorSource.addFeature(iconFeature);
}
// make the map's view to zoom and pan enough to display all the points
map.getView().fit(vectorSource.getExtent(), map.getSize());
Here's a plunker:
https://plnkr.co/edit/KVL14vdOSqJBxZz44s3u?p=preview
Once your vector features has been drawn you may get the extent using:
vector.on('render',function(e){
var myextent = vector.getSource().getExtent();
})
And then you may zoom to this extent using:
map.getView().fit(myextent , map.getSize());
So if you are going to use the render event
vector.on('render',function(e){
map.getView().fit(vector.getSource().getExtent(), map.getSize());
})
I was planning to draw polygon from lat long values referring this code.
open layers 3 how to draw a polygon programmically?
var polyCoordinates =[[1.300910900488229, 44.28372648003116],[1.3373031124022878, 44.13311552125895],[1.6648330196289067, 44.12030076099872]];
var polygon = new OpenLayers.Geometry.Polygon([polyCoordinates]);
// Create feature with polygon.
var feature = new OpenLayers.Feature(polygon);
// Create vector source and the feature to it.
var vectorSource = new OpenLayers.source.Vector();
// Create the vectorial layer
var vectorLayer = new OpenLayers.Layer.Vector('Vector Layer', {
source: vectorSource
styleMap: new OpenLayers.StyleMap({
'default': OpenLayers.Util.applyDefaults({
strokeWidth: 3,
graphicName: 'triangle',
pointRadius: '${radius}',
rotation: '${angle}'
}, OpenLayers.Feature.Vector.style['default']
),
'select': OpenLayers.Util.applyDefaults({
pointRadius: '${radius}'
}, OpenLayers.Feature.Vector.style['select']
)
})
});
OpenLayers.source is undefined is showing as error. Any help would be appreciated.
var sitePoints = [];
var coordinates =[{"long":1.300910900488229,"lat":44.28372648003116},
{"long":1.3373031124022878,"lat":44.13311552125895},
{"long":1.6648330196289067,"lat":44.12030076099872}];
var siteStyle = {
label:'ring',
title: 'press to close as a ring',
cursor: "pointer",
fontSize: '8px',
fontColor: '#222',
pointRadius: 10,
fillColor: '#cccccc',
strokeColor: '#444444'
};
var epsg4326 = new OpenLayers.Projection("EPSG:4326");
for (var i in coordinates) {
var coord = coordinates[i];
var point = new OpenLayers.Geometry.Point(coord.long, coord.lat);
// transform from WGS 1984 to Spherical Mercator
point.transform(epsg4326, map.getProjectionObject());
sitePoints.push(point);
}
console.log(sitePoints);
var linearRing = new OpenLayers.Geometry.LinearRing(sitePoints);
var geometry = new OpenLayers.Geometry.Polygon([linearRing]);
var polygonFeature = new OpenLayers.Feature.Vector(geometry, null, siteStyle);
vectorLayer.addFeatures([polygonFeature]);
map.addLayer(vectorLayer);
Here is a proper way to do this in OpenLayers 3, which has a different API than previous versions.
var polyCoordinates =[
[1.300910900488229, 44.28372648003116],
[1.3373031124022878, 44.13311552125895],
[1.6648330196289067, 44.12030076099872]];
var polygon = new ol.geom.Polygon([polyCoordinates]);
polygon.applyTransform(ol.proj.getTransform('EPSG:4326', 'EPSG:3857'));
// Create feature with polygon.
var feature = new ol.Feature({
geometry: polygon
});
// Create vector source and the feature to it.
var vectorSource = new ol.source.Vector({
features: [feature]
});
// Create the vectorial layer
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#eedd00',
width: 3
})
})
});
Edit: If you stick with OpenLayers 2, you need to create the polygon via linear ring. The setup is a little bit different. There is no OpenLayers source to deal with.
var polyCoordinates =[
[1.300910900488229, 44.28372648003116],
[1.3373031124022878, 44.13311552125895],
[1.6648330196289067, 44.12030076099872]];
// Create the polygon via linear ring
var points = [];
for (var i = 0; i < polyCoordinates.length; i++) {
coord = polyCoordinates[i];
points.push(new OpenLayers.Geometry.Point(coord[0], coord[1]));
}
var linearRing = new OpenLayers.Geometry.LinearRing(points);
var polygon = new OpenLayers.Geometry.Polygon([linearRing]);
var srcProj = new OpenLayers.Projection("EPSG:4326");
var targetProj = new OpenLayers.Projection("EPSG:3857");
polygon.transform(srcProj, targetProj);
// Create feature with polygon.
var feature = new OpenLayers.Feature.Vector(polygon);
// Create the vectorial layer
var vectorLayer = new OpenLayers.Layer.Vector('Vector Layer',
OpenLayers.Feature.Vector.style['default']
);
vectorLayer.addFeatures([feature]);