Attempting to emit a geometry after the feature is drawn on tab 1. Then trying to redraw the feature using socket.on to be displayed on tab 2. however for some reason the feature is not drawn.
window.onload = function init() {
var source = new ol.source.Vector({ wrapX: false });
//create a base vector layer to draw on
var vector = new ol.layer.Vector({
source: source,
});
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
//create map
map = new ol.Map({
layers: [raster, vector],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** #type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
view: new ol.View({
center: [0,0],
zoom: 10
})
});
function drawShape(value) {
var value = value;
if (value !== 'None') {
draw = new ol.interaction.Draw({
source: source,
type: /** #type {ol.geom.GeometryType} */ (value)
});
map.addInteraction(draw);
draw.on('drawend', function (event) {
// Get the array of features
var feature = event.feature
try {
map.removeInteraction(draw);
socket.emit('new polygon', feature.getGeometry().getCoordinates());
socket.emit('chat message', feature.getGeometry().getCoordinates());
} catch (err) { }
});
}
}
var socket = io();
socket.on('new polygon', function (msg) {
var thing = new ol.geom.Polygon(msg);
var featurething = new ol.Feature({
name: "Thing",
geometry: thing
});
source.addFeature(featurething);
});
}
when the script is run the msg contains an array of coordinates. Nothing appears in the console.
I am a beginner at node.js. anyone know what i am doing wrong
Found the error. In your socket.on callback you are calling
source.addFeatures(featurething);
when it should be
source.addFeature(featurething); // single feature, no s
or
source.addFeatures([featurething]); // put it in an array
Related
i want to import my shapefile into my map using openlayers Bing.Map but after import my shape file in map i can not zoom out or zoom in in my map and it looks like crushing
i am using openlayers7.1 in my code . i set drag and drop event for importing shape file in to map . this code can handle shape.shp shape.dbf shape.sbn and ... as shape.zip file
the rest of code can be found https://openlayers.org/en/latest/examples/bing-maps.html here but for working you need to replace your API Key where you can see API Key in the code .
i need Sample code to fix this. thanks
import BingMaps from 'ol/source/BingMaps';
import Map from 'ol/Map';
import TileLayer from 'ol/layer/Tile';
import View from 'ol/View';
import { fromLonLat } from "ol/proj";
import vectorSource from 'ol/source/Vector';
const place =[59.6067,36.2972];
const styles = [
'RoadOnDemand',
'Aerial',
'AerialWithLabelsOnDemand',
'CanvasDark',
'OrdnanceSurvey',
];
const layers = [];
let i, ii;
for (i = 0, ii = styles.length; i < ii; ++i) {
layers.push(
new TileLayer({
visible: false,
preload: Infinity,
source: new BingMaps({
key: "API Key",
imagerySet: styles[i],
// use maxZoom 19 to see stretched tiles instead of the BingMaps
// "no photos at this zoom level" tiles
// maxZoom: 19
}),
})
);
}
const map = new Map({
layers: layers,
target: 'map',
view: new View({
center: fromLonLat(place),
zoom: 8,
}),
});
const select = document.getElementById('layer-select');
function onChange() {
const style = select.value;
for (let i = 0, ii = layers.length; i < ii; ++i) {
layers[i].setVisible(styles[i] === style);
}
}
select.addEventListener('change', onChange);
onChange();
const featureStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'red',
width: 1
})
});
map.getViewport().addEventListener('dragover', function(event) {
event.preventDefault();
});
map.getViewport().addEventListener('drop',shpShow);
function shpShow(event) {
event.preventDefault();
const files = event.dataTransfer.files;
for (let i = 0, ii = files.length; i < ii; ++i) {
const file = files.item(i);
loadshp({url: file, encoding: 'utf-8'}, function(geojson) {
const features = new ol.format.GeoJSON().readFeatures(
geojson,
{ featureProjection: map.getView().getProjection() }
);
const vectorSource = new ol.source.Vector({
features: features
});
map.addLayer(
new ol.layer.Vector({
source: vectorSource,
style: featureStyle
})
);
map.getView().fit(vectorSource.getExtent());
});
}
}
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://openlayers.org/en/v6.3.1/build/ol.js"></script>
<script src="https://gipong.github.io/shp2geojson.js/lib/jszip.js"></script>
<script src="https://gipong.github.io/shp2geojson.js/lib/jszip-utils.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.6.1/proj4.js"></script>
<script src="https://gipong.github.io/shp2geojson.js/preprocess.js"></script>
<script src="https://gipong.github.io/shp2geojson.js/preview.js"></script>
I presume you are using loadshp from https://github.com/gipong/shp2geojson.js?
A dropped file needs to be read by a FileReader, in your case as a dataUrl
const file = files.item(i);
const reader = new FileReader();
reader.addEventListener('load', function() {
loadshp({url: reader.result, encoding: 'utf-8'}, function(geojson) {
....
....
});
});
reader.readAsDataURL(file);
very good question
When we import the .shp files, the map is not refreshed again.
I had this challenge for a long time and still this problem exists in my codes.
Thanks if anyone has the ability to solve this challenge.
I'm building a navigation app. I am using openlayers and osm. So far I have drawn the path between 2 points. But since my location is updated every 5 seconds I have to recreate the path. Even when re-creating the path, the old path is not deleted. How can I solve this problem?
var vectorSource = new ol.source.Vector(),
url_osrm_nearest = '//router.project-osrm.org/nearest/v1/driving/',
url_osrm_route = '//router.project-osrm.org/route/v1/driving/',
icon_url = '//cdn.rawgit.com/openlayers/ol3/master/examples/data/icon.png',
vectorLayer = new ol.layer.Vector({
source: vectorSource
}),
styles = {
route: new ol.style.Style({
stroke: new ol.style.Stroke({
width: 6, color: [40, 40, 40, 0.8]
})
}),
icon: new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: icon_url
})
})
};
var utils = {
getNearest: function(coord){
var coord4326 =coord;
return new Promise(function(resolve, reject) {
//make sure the coord is on street
fetch(url_osrm_nearest + coord4326.join()).then(function(response) {
// Convert to JSON
return response.json();
}).then(function(json) {
if (json.code === 'Ok') resolve(json.waypoints[0].location);
else reject();
});
});
},
createFeature: function(coord) {
var feature = new ol.Feature({
type: 'place',
geometry: new ol.geom.Point(coord)
});
feature.setStyle(iconStyle2);
vectorSource.addFeature(feature);
},
createRoute: function(polyline) {
var route = new ol.format.Polyline({
factor: 1e5
}).readGeometry(polyline);
var feature = new ol.Feature({
type: 'route',
geometry: route
});
feature.setStyle(styles.route);
vectorSource.addFeature(feature);
},
to4326: function(coord) {
return ol.proj.transform([
parseFloat(coord[0]), parseFloat(coord[1])
]);
}
};
const map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
}),
vectorLayer
],
target: 'map',
view: view,
});
function first_route(data)
{
lati = data.latii;
longi = data.longii;
utils.getNearest([my_longi,my_lati]);
utils.getNearest([longi,longi]);
utils.createFeature([longi,longi]);
var point1 = [my_longi,my_lati];
var point2 = [longi,longi];
fetch(url_osrm_route + point1 + ';' + point2).then(function(r) {
return r.json();
}).then(function(json) {
if(json.code !== 'Ok') {
return;
}
utils.createRoute(json.routes[0].geometry);
});
}
function locate() {
const coordinates = geolocation.getPosition();
iconCar.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null)
if(iconCar.getGeometry() != null)
map.getView().fit(iconCar.getGeometry(),{maxZoom: 16});
if(coordinates != null)
{
my_lati = geolocation.getPosition()[1];
my_longi = geolocation.getPosition()[0];
}
utils.getNearest([my_longi,my_lati]);
utils.getNearest([longi,lati]);
utils.createFeature([longi,lati]);
var point1 = [my_longi,my_lati];
var point2 = [longi,lati];
fetch(url_osrm_route + point1 + ';' + point2).then(function(r) {
return r.json();
}).then(function(json) {
if(json.code !== 'Ok') {
return;
}
utils.createRoute(json.routes[0].geometry);
});
}
setInterval(locate, 14000);
Location is updated every 5 seconds. Therefore, the route on the map also needs to be changed. But when I try to do it this way it doesn't delete the old route. It draws another route on the same route.
If you make the route feature a global variable you can create it, or if it already exists, update it
var routeFeature;
createRoute: function(polyline) {
var route = new ol.format.Polyline({
factor: 1e5
}).readGeometry(polyline);
if (!routeFeature) {
routeFeature = new ol.Feature({
type: 'route',
geometry: route
});
routeFeature.setStyle(styles.route);
vectorSource.addFeature(routeFeature);
} else {
routeFeature.setGeometry(route);
}
},
I have located a point on a map
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat(cord)),
label: 'Label'
})
]
}),
style: (feature) => {
myStyle.getText().setText(feature.get('label'));
return [myStyle];
}
});
I just wanted to make a link to the label (or the point) that takes me to another page. Any help.
Put a click event handler on your map and use getFeaturesAtPixel to find the feature (if any) that has been clicked on. For example:
map.on("click", (event) => {
const features = map.getFeaturesAtPixel(event.pixel);
if (features && features.length > 0) {
// ...
}
});
I'm making a map with OpenLayers that pulls data from a database and parses that data through an API to display it onto the map, and that section is working completely fine (see: https://i.imgur.com/z8ItBxr.png) however, when trying to make the icons clickable I'm running into issues. I'm not sure if I have to do something different when accounting for multiple icons, but I've tried to follow the documentation at https://openlayers.org/en/latest/examples/icon.html to no help. I'm essentially trying to display the MMSI (ID of the vessels) above the ships as a pop-up when the ship is clicked on, but it isn't really working properly. It'll mouse over the icons properly, but clicking doesn't really do anything. If anyone can help, it's greatly appreciated. I've attached my index.js below:
const { Client } = require('pg')
import "ol/ol.css";
import Feature from "ol/Feature";
import Point from "ol/geom/Point";
import Map from "ol/Map";
import View from "ol/View";
import Overlay from 'ol/Overlay';
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { defaults as defaultControls, FullScreen } from "ol/control";
import OSM from "ol/source/OSM";
import { fromLonLat } from "ol/proj";
import VectorSource from "ol/source/Vector";
import { Icon, Style } from "ol/style";
const newportLonLat = [-71.307607, 41.529193];
const newportWebMercator = fromLonLat(newportLonLat);
//const text = 'SELECT DISTINCT mmsi, MAX(basedatetime), lat, lon FROM public.vessels GROUP BY mmsi, lat, lon ORDER by MAX(basedatetime) DESC, mmsi, lat, lon'
function loadJSON() {
var data_file = "http://localhost:3000/latlong";
var http_request = new XMLHttpRequest();
try{
// Opera 8.0+, Firefox, Chrome, Safari
http_request = new XMLHttpRequest();
}catch (e) {
// Internet Explorer Browsers
try{
http_request = new ActiveXObject("Msxml2.XMLHTTP");
}catch (e) {
try{
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}catch (e) {
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
http_request.onreadystatechange = function() {
if (http_request.readyState == 4 ) {
// Javascript function JSON.parse to parse JSON data
console.log(http_request);
var jsonObj = JSON.parse(http_request.responseText);
var allIcons = [];
for(var i = 0; i < jsonObj.length - 1; i++){
console.log("-----------")
console.log("Latitude: ", jsonObj[i]['lat'])
console.log("Longitude: ", jsonObj[i]['lon'])
console.log("ID: ", jsonObj[i]['mmsi'])
var lat = jsonObj[i]['lat']
var long = jsonObj[i]['lon']
var mmsi = jsonObj[i]['mmsi']
var iconFeature = new Feature({
geometry: new Point(fromLonLat([long, lat])),
name: mmsi,
population: 4000,
rainfall: 500
});
var iconStyle = new Style({
image: new Icon(
/** #type {olx.style.IconOptions} */ ({
anchor: [0.5, 46],
anchorXUnits: "fraction",
anchorYUnits: "pixels",
src: "https://i.imgur.com/P30vpnp.png",
scale: 0.5
})
)
});
iconFeature.setStyle(iconStyle);
allIcons.push(iconFeature);
}
var map = new Map({
controls: defaultControls().extend([new FullScreen()]),
layers: [
new TileLayer({
source: new OSM()
}),
new VectorLayer({
style: function(feature) {
return feature.get("style");
},
source: new VectorSource({ features: allIcons })
})
],
target: document.getElementById('map'),
view: new View({
center: newportWebMercator,
zoom: 3
})
});
var element = document.getElementById('popup');
var popup = new Overlay({
element: element,
positioning: 'bottom-center',
stopEvent: false,
offset: [0, -50]
});
map.addOverlay(popup);
// display popup on click
map.on('click', function(evt) {
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature) {
return feature;
});
if (feature) {
var coordinates = feature.getGeometry().getCoordinates();
popup.setPosition(coordinates);
$(element).popover({
placement: 'top',
html: true,
content: feature.get('name')
});
$(element).popover('show');
} else {
$(element).popover('destroy');
}
});
// change mouse cursor when over marker
map.on('pointermove', function(e) {
if (e.dragging) {
$(element).popover('destroy');
return;
}
var pixel = map.getEventPixel(e.originalEvent);
var hit = map.hasFeatureAtPixel(pixel);
map.getTarget().style.cursor = hit ? 'pointer' : '';
});
}
}
http_request.open("GET", data_file, true);
http_request.send();
}
loadJSON();
I'm currently using PlacesService library from Google Maps API. I want to render suggestions for New York City. I added strict_bounds for this matter but I still get results way out of New York as shown in the image.
For the most part it works, but I get many out of bounds suggestions.
/** #private {?this._google.maps.Map} The google map object. */
this._map = new this._google.maps.Map(this._mapEl, {
zoom: 11,
center: this._mapPosition
});
/** #private {this._google.maps.places.Autocomplete}Autocomplete instance */
this._service = new this._google.maps.places.AutocompleteService();
/** #private {this._google.maps.places.PlaceService}PlaceService instance */
this._placeService = new this._google.maps.places.PlacesService(this._map);
Here is the instance in the constructor.
// Attach handler for the autocomplete search box. This updates the map
// position and re-sorts locations around that position.
this._searchEl.addEventListener('keyup', (event) => {
if(event.target.value) {
this._service.getPlacePredictions({
input: event.target.value,
offset: 3,
strictBounds: true,
types: ['geocode'],
bounds: this._map.getBounds()
}, (predictions) => {
if(predictions) {
let results = predictions.map(e => [e['description']]);
event.target.missplete = new MissPlete({
input: event.target,
options: results,
className: 'c-autocomplete'
})
event.target.missplete.select = () => {
let msplt = event.target.missplete;
if (msplt.highlightedIndex !== -1) {
msplt.input.value = msplt
.scoredOptions[msplt.highlightedIndex].displayValue;
msplt.removeDropdown();
console.dir('we did it');
}
};
event.target.predictions = predictions;
console.log(event.target.predictions);
}
});
}
});
There is a method displayPlacesOnMap that gets an array of Google place objects. Here we get the place_id in order to make use of PlaceService library.
displayPlacesOnMap(mapItems) {
if(mapItems) {
mapItems.forEach(place => {
let request = {
placeId: place.place_id,
fields: ['name', 'formatted_address', 'place_id', 'geometry']
}
const officeMap = this;
this._placeService.getDetails(request, function(place, status) {
if (status === 'OK') {
officeMap._mapPosition = place.geometry.location;
officeMap._map.panTo(officeMap._mapPosition);
officeMap.sortByDistance().clearLocations().updateUrl().updateList()
.updateUrl();
$(officeMap._searchEl).blur();
}
})
})
}
};