Create multiple direction route with car animation map in open layers - javascript

I want to create a map like this image
in open layers.
How we can create this type map in open layers and how we get API service that will ping coordinate in sequence every 3 seconds (to simulate 3rd party service)
I want to integrate this map in this code. I have no idea ho we can do this
import Feature from 'ol/Feature';
import LineString from 'ol/geom/LineString';
import Map from 'ol/Map';
import Point from 'ol/geom/Point';
import Polyline from 'ol/format/Polyline';
import VectorSource from 'ol/source/Vector';
import View from 'ol/View';
import OSM from 'ol/source/OSM';
import {Icon, Stroke, Style} from 'ol/style';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import {getVectorContext} from 'ol/render';
const center = [-5639523.95, -3501274.52];
const map = new Map({
target: document.getElementById('map'),
view: new View({
center: center,
zoom: 10,
minZoom: 2,
maxZoom: 19,
}),
layers: [
new TileLayer({
source: new OSM(),
}),
],
});
// The polyline string is read from a JSON similiar to those returned
// by directions APIs such as Openrouteservice and Mapbox.
fetch('data/polyline/route.json').then(function (response) {
response.json().then(function (result) {
const polyline = result.routes[0].geometry;
const route = new Polyline({
factor: 1e6,
}).readGeometry(polyline, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857',
});
const routeFeature = new Feature({
type: 'route',
geometry: route,
});
const startMarker = new Feature({
type: 'icon',
geometry: new Point(route.getFirstCoordinate()),
});
const endMarker = new Feature({
type: 'icon',
geometry: new Point(route.getLastCoordinate()),
});
const position = startMarker.getGeometry().clone();
const geoMarker = new Feature({
type: 'geoMarker',
geometry: position,
});
const styles = {
route: new Style({
stroke: new Stroke({
width: 6,
color: [237, 212, 0, 0.8],
}),
}),
icon: new Style({
image: new Icon({
anchor: [0.5, 1],
src: 'data/icon.png',
}),
}),
geoMarker: new Style({
image: new Icon({
src:
'https://cdn1.iconfinder.com/data/icons/basic-ui-elements-color-round/3/19-32.png',
rotation: getAngleAt(route, 0) + Math.PI / 2,
}),
}),
};
const vectorLayer = new VectorLayer({
source: new VectorSource({
features: [routeFeature, geoMarker, startMarker, endMarker],
}),
style: function (feature) {
return styles[feature.get('type')];
},
});
map.addLayer(vectorLayer);
const speedInput = document.getElementById('speed');
const startButton = document.getElementById('start-animation');
let animating = false;
function getAngleAt(lineString, distance) {
const length = lineString.getLength();
const coordinates = lineString.getCoordinates();
for (let i = 1, len = coordinates.length; i <= len; ++i) {
if (
new LineString(coordinates.slice(0, i + 1)).getLength() >=
length * distance
) {
return -Math.atan2(
coordinates[i][1] - coordinates[i - 1][1],
coordinates[i][0] - coordinates[i - 1][0]
);
}
}
}
const lastTimes = [];
function moveFeature(event) {
const speed = Number(speedInput.value);
const time = event.frameState.time;
for (let i = 0, ii = lastTimes.length; i < ii; ++i) {
let {lastTime, distance} = lastTimes[i];
const elapsedTime = time - lastTime;
distance = (distance + (speed * elapsedTime) / 1e6) % 2;
lastTime = time;
lastTimes[i] = {lastTime, distance};
const lineDistance = distance > 1 ? 2 - distance : distance;
const direction = distance > 1 ? -Math.PI / 2 : Math.PI / 2;
const currentCoordinate = route.getCoordinateAt(lineDistance);
const angle = getAngleAt(route, lineDistance) + direction;
styles.geoMarker.getImage().setRotation(angle);
position.setCoordinates(currentCoordinate);
const vectorContext = getVectorContext(event);
vectorContext.setStyle(styles.geoMarker);
vectorContext.drawGeometry(position);
}
// tell OpenLayers to continue the postrender animation
map.render();
}
function startAnimation() {
lastTimes.push({lastTime: Date.now(), distance: 0});
if (!animating) {
animating = true;
//startButton.textContent = 'Stop Animation';
vectorLayer.on('postrender', moveFeature);
// hide geoMarker and trigger map render through change event
geoMarker.setGeometry(null);
}
}
startButton.addEventListener('click', startAnimation);
});
});
{
"name": "feature-move-animation",
"dependencies": {
"ol": "7.1.0"
},
"devDependencies": {
"vite": "^3.0.3",
"#babel/core": "latest"
},
"scripts": {
"start": "vite",
"build": "vite build"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Marker Animation</title>
<link rel="stylesheet" href="node_modules/ol/ol.css">
<style>
.map {
width: 100%;
height: 400px;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<label for="speed">
speed:
<input id="speed" type="range" min="10" max="999" step="10" value="60">
</label>
<button id="start-animation">Start Animation</button>
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
<script src="https://unpkg.com/elm-pep#1.0.6/dist/elm-pep.js"></script>
<script type="module" src="main.js"></script>
</body>
</html>

Related

Mapbox Cluster Map opens all pop-ups on location click

I am trying to create a cluster map with multiple locations in the same area. Now, I have this pop-up with data which is coming from my API. I have a click event that toggles the pop-up on click for each location. But the problem is even when I specified the click unique ID to toggle it still opens all the pop-ups. Also, the zoom is not working for the clusters count circles.
This is my code:
import mapboxgl from 'mapbox-gl';
import MapboxLanguage from '#mapbox/mapbox-gl-language';
import apiFetch from '#wordpress/api-fetch';
(() => {
const mapContainer = document.querySelector('[data-gewoon-wonen]');
if (!mapContainer) {
return;
}
mapboxgl.accessToken = process.env.MAP_TOKEN_KEY;
const filterGroup = document.getElementById('map-filter');
const resetButton = filterGroup.querySelector('.hidden');
const center = [4.387733, 51.862419];
const locations = {
type: 'FeatureCollection',
features: []
};
apiFetch({ path: '/wp-json/wp/v2/map?_embed' }).then((maps) => {
maps.forEach((item) => {
const {
id,
title: { rendered: title },
_embedded,
acf
} = item;
const image =
_embedded && _embedded['wp:featuredmedia'][0]?.source_url;
const {
map_location_subtitle: subtitle,
map_location_delivery: delivery,
map_location_project: project,
map_location_content: description,
map_location_coordinates_lat: lat,
map_location_coordinates_lng: lng,
map_location_status: status,
map_location_website: website
} = acf;
const getStatus = (currentStatus) => {
let statusObj = {
bouwfase: 'marker-gray',
planfase: 'marker-bright-pink',
opgeleverd: 'marker-bright-blue',
default: ''
};
let icon = statusObj[currentStatus] || statusObj['default'];
return icon;
};
const object = {
type: 'Feature',
properties: {
id,
status,
image,
icon: getStatus(status),
title,
subtitle,
project,
website,
delivery,
description
},
geometry: {
type: 'Point',
coordinates: [lng, lat]
}
};
locations.features.push(object);
});
});
const map = new mapboxgl.Map({
container: mapContainer,
style: 'mapbox://styles/.../clcz9eocm000p14o3vh42tqfj',
center,
zoom: 10,
minZoom: 10,
maxZoom: 18,
attributionControl: false,
cooperativeGestures: true
});
map.addControl(
new MapboxLanguage({
defaultLanguage: 'mul'
})
);
const resetActiveItems = () => {
document
.querySelectorAll('.active')
.forEach((e) => e.classList.remove('active'));
};
const closePopUps = () => {
const popups = document.getElementsByClassName('mapboxgl-popup');
if (popups.length) {
popups[0].remove();
}
};
map.on('load', () => {
map.addSource('locations', {
type: 'geojson',
data: locations,
cluster: true,
clusterMaxZoom: 14, // Max zoom to cluster points on
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)s
});
locations.features.forEach((location) => {
const {
description,
delivery,
title,
subtitle,
project,
status,
image,
website,
id
} = location.properties;
const { coordinates } = location.geometry;
const layerID = `status-${status}-${id}`;
// Add a layer for this symbol type if it hasn't been added already.
if (!map.getLayer(layerID)) {
map.addLayer({
id: layerID,
type: 'symbol',
source: 'locations',
layout: {
'icon-image': ['get', 'icon'],
'icon-size': 0.9,
'icon-allow-overlap': true
},
// filter: ['==', 'id', id]
filter: ['!', ['has', 'point_count']]
});
map.addLayer({
id: `clusters-${id}`,
type: 'circle',
source: 'locations',
filter: ['has', 'point_count'],
paint: {
// Use step expressions (https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-step)
// with three steps to implement three types of circles:
// * Blue, 20px circles when point count is less than 100
// * Yellow, 30px circles when point count is between 100 and 750
// * Pink, 40px circles when point count is greater than or equal to 750
'circle-color': [
'step',
['get', 'point_count'],
'#51bbd6',
100,
'#f1f075',
750,
'#f28cb1'
],
'circle-radius': [
'step',
['get', 'point_count'],
20,
100,
30,
750,
40
]
}
});
map.addLayer({
id: `cluster-count-${id}`,
type: 'symbol',
source: 'locations',
filter: ['has', 'point_count'],
layout: {
'text-field': ['get', 'point_count_abbreviated'],
'text-font': [
'DIN Offc Pro Medium',
'Arial Unicode MS Bold'
],
'text-size': 12
}
});
}
const hasImage = image
? `<img src=${image} class="map__image" />`
: '';
const statusClass = image ? 'map__status--overlay' : '';
const popup = new mapboxgl.Popup({
offset: 25,
maxWidth: null,
className: image ? 'map__content--image' : ''
});
const content = `
${hasImage}
<span class="map__status map__status--${status} ${statusClass}">${status}</span>
<h4 class="map__title">${title}</h4>
<p class="map__subtitle">${subtitle}</p>
<p class="map__subtitle">${
delivery ? `Oplevering ${delivery}` : ''
}</p>
<p class="map__project">${project}</p>
<p class="map__info">${description}</p>
Meer informatie
`;
map.on('click', layerID, (e) => {
// Copy coordinates array.
const coordinateSlice = coordinates.slice();
resetButton.classList.remove('hidden');
// Ensure that if the map is zoomed out such that multiple
// copies of the feature are visible, the popup appears
// over the copy being pointed to.
while (Math.abs(e.lngLat.lng - coordinateSlice[0]) > 180) {
coordinateSlice[0] +=
e.lngLat.lng > coordinateSlice[0] ? 360 : -360;
}
popup.setLngLat(coordinates).setHTML(content).addTo(map);
});
// Change the cursor to a pointer when the mouse is over the places layer.
map.on('mouseenter', layerID, () => {
map.getCanvas().style.cursor = 'pointer';
});
// Change it back to a pointer when it leaves.
map.on('mouseleave', layerID, () => {
map.getCanvas().style.cursor = '';
});
});
const statusTypes = locations.features.map(
(feature) => feature.properties.status
);
const uniqueStatusTypes = Array.from(new Set(statusTypes));
const newGeoJSON = { ...locations };
resetButton.addEventListener('click', () => {
newGeoJSON.features = [...locations.features];
map.getSource('locations').setData(newGeoJSON);
map.setZoom(10).setCenter(center);
resetButton.classList.add('hidden');
resetActiveItems();
closePopUps();
});
const sortedStatusTypes = [
uniqueStatusTypes[0],
uniqueStatusTypes[2],
uniqueStatusTypes[1]
].filter((status) => status !== undefined && status !== null);
sortedStatusTypes.forEach((statusType) => {
const input = document.createElement('input');
input.value = statusType;
input.name = statusType;
input.type = 'button';
input.className = `status--${statusType}`;
input.innerText = statusType;
filterGroup.appendChild(input);
input.onclick = () => {
const statusType = input.value;
resetActiveItems();
closePopUps();
if (statusType) {
input.classList.add('active');
resetButton.classList.remove('hidden');
newGeoJSON.features = locations.features.filter(
(feature) => feature.properties.status === statusType
);
}
map.getSource('locations').setData(newGeoJSON);
};
});
// disable map rotation using right click + drag
map.dragRotate.disable();
// disable map rotation using touch rotation gesture
map.touchZoomRotate.disableRotation();
// Add zoom and rotation controls to the map.
const nav = new mapboxgl.NavigationControl({
showCompass: false
});
const fullscreen = new mapboxgl.FullscreenControl();
map.addControl(fullscreen, 'top-right');
map.addControl(nav, 'bottom-right');
});
})();

Access to current trip/coordinates from the TripLayers class in DeckGL?

I am trying to create a visualization that shows all the trips I have completed in 2022. I found that DeckGL had the highest chance of helping me accomplish this, but I am not able to dynamically access the data of the current trip being drawn (lat, lng, timestamp) on the map.
I would like to be able to pan to the coordinate on the map where the trip is taking place, and make it smooth. Currently, I have hardcoded the values in using currentTime, but I would like to have a more robust and less cluttered way of doing this.
I am not very proficient in Java-/Type-script but I have been using the tutorial and reading all the docs, have been trying to solve this for 2 days. Nothing stood out to me. Please help!
My current implementation is as follows:
// import { GoogleMapsOverlay } from "#deck.gl/google-maps";
// import { TripsLayer } from "deck.gl";
const GoogleMapsOverlay = deck.GoogleMapsOverlay;
const TripsLayer = deck.TripsLayer;
interface Data {
path: [number, number][];
timestamps: number[];
}
const DATA_URL =
"https://raw.githubusercontent.com/charlieforward9/animated_heatmap/master/data/2022.json";
const LOOP_LENGTH = 31557600;
function initMap(): void {
const map = new google.maps.Map(
document.getElementById("map") as HTMLElement,
{
center: { lat: 29.64462421696083, lng: -82.33479384825146},
mapId: '1ae1962daafbdd69',
tilt: 45,
zoom: 12,
disableDefaultUI: true,
} as google.maps.MapOptions
);
const view = new deck.MapView({id:"view", x:29.64462421696083, y: -82.33479384825146, width: 300, height: 200});
let currentTime = -1000000;
let playSpeed = 30000;
const props = {
id: "trips",
data: DATA_URL,
getPath: (d: Data) =>d.path,
getTimestamps: (d: Data) => d.timestamps,
getColor: [255, 87, 51],
opacity: 1,
widthMinPixels: 4,
trailLength: 31557600,
currentTime,
shadowEnabled: false,
jointRounded: true,
capRounded: true
};
//Hardcoded panning
function autoAnimate(): void {
window.setInterval(viewportAnimation, 80);
}
function viewportAnimation(): void {
const heading = map.getHeading() || 0;
const zoom = map.getZoom() || 10;
const tilt = map.getTilt() || 45;
console.log(currentTime);
if (currentTime < 3600000) {
//Gainesville
map.setHeading(heading + 0.1);
map.setZoom(zoom - 0.01);
} else if (currentTime < 4000000) {
//Orlando SoFlo
map.setHeading(0);
map.setZoom(zoom + 0.1);
map.setTilt(tilt - 0.1);
map.panTo({ lat: 28.6024, lng: -81.2001});
} else if (currentTime < 7300000) {
//Gainesville
map.setHeading(heading - 0.1);
map.setZoom(zoom - 0.01);
map.panTo({ lat: 29.64462421696083, lng: -82.33479384825146});
}
}
const overlay = new GoogleMapsOverlay({});
const animate = () => {
currentTime = (currentTime + playSpeed) % LOOP_LENGTH;
const tripsLayer = new TripsLayer({
...props,
currentTime,
});
overlay.setProps({
layers: [tripsLayer],
});
window.requestAnimationFrame(animate);
};
window.requestAnimationFrame(animate);
autoAnimate()
overlay.setMap(map);
}
declare global {
interface Window {
initMap: () => void;
}
}
window.initMap = initMap;
export {};

importing shape file to openLayers bing map

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.

Draw a graph inside map using Open layer and bing map

I am new to work with Open layer version 7 api , i want to draw a graph in map with js code which the points are special locations and lines should join those locations
I used this examples , i link them below
I got confused how to do it , i think i should combine them but i couldn't
https://openlayers.org/en/latest/examples/icon-color.html
https://openlayers.org/en/latest/examples/feature-move-animation.html
https://openlayers.org/en/latest/examples/bing-maps.html
https://openlayers.org/en/latest/examples/gpx.html
i want something like this img
i think you should make Gpx file of location you want and then you will be fine
use this example
The following code can read .shp files as zip and display them on the map.
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>

Live routing using Openlayers and OSM

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);
}
},

Categories