Add markers and polylines to a Leaflet map from destinations in a Google Sheet - google-sheets

I'm trying to create a Leaflet map, that automatically adds markers and polylines between destinations from a Google sheet.
I've managed to set up a map from other examples which is linked to my Google Sheet. You see the example here:
<!DOCTYPE html>
<html>
<head>
<script src='//cdn.jsdelivr.net/npm/tabletop#1.5.2/src/tabletop.min.js'></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css" />
<script src="//unpkg.com/leaflet#1.3.4/dist/leaflet.js"></script>
<style>
#map-div {
position: absolute;
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="map-div"></div>
</body>
</html>
var map = L.map('map-div').setView([60.1682653, 24.9422078], 5);
var basemap = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Basemap (c) OpenStreetMap',
minZoom: 5,
maxZoom: 100
});
basemap.addTo(map);
function addPoints(data, tabletop) {
for (var row in data) {
var marker = L.marker([
data[row].Latitude,
data[row].Longitude
]).addTo(map);
marker.bindPopup('<strong>' + data[row].Info + '</strong>');
}
}
function init() {
Tabletop.init({
key: 'https://docs.google.com/spreadsheets/d/1Rs6xPlJ8pU4UFfmokjATaf4dArMWxQxZcyS-xRIIFuY/edit?usp=sharing',
callback: addPoints,
simpleSheet: true
})
}
init()
https://jsfiddle.net/Enounce/kwvn5e6z/12/
But unfortunately, I don't have the skills to make the map do what I want:
Draw lines between markers Draw lines between markers in leaflet
Zoom to fit all markers Zoom to Fit All Markers on LeafletJS Map
If possible, add an overview of all destinations, much like the directions panel in Google Maps. I haven't been able to find examples of this though.
I'm unsure if this is at all possible with the destinations being in an external source. Any help is appreciated!

Draw Line between markers:
You need to create a L.Polyline and add the latlngs to it:
function addPoints(data, tabletop) {
var line = L.polyline([]).addTo(map);
for (var row in data) {
var marker = L.marker([
data[row].Latitude,
data[row].Longitude
]).addTo(map);
line.addLatLng(marker.getLatLng());
marker.bindPopup('<strong>' + data[row].Info + '</strong>');
}
}
Zoom to fit all markers:
Add the markers to a L.FeatureGroup() and then you can fit the map bounds to the group bounds with map.fitBounds(fg.getBounds());
var fg = L.featureGroup().addTo(map);
function addPoints(data, tabletop) {
var line = L.polyline([]).addTo(map);
for (var row in data) {
var marker = L.marker([
data[row].Latitude,
data[row].Longitude
]).addTo(fg);
line.addLatLng(marker.getLatLng());
marker.bindPopup('<strong>' + data[row].Info + '</strong>');
}
map.fitBounds(fg.getBounds());
}
BUT you need to remove minZoom: 5 from the TileLayer.
Destinations
Store the destinations in an array and then create a html element in the loop and add a click listener:
var destinationHTML = document.getElementById("destinations-body");
var fg = L.featureGroup().addTo(map);
var destinations = [];
function addPoints(data, tabletop) {
var line = L.polyline([]).addTo(map);
for (var row in data) {
var marker = L.marker([
data[row].Latitude,
data[row].Longitude
]).addTo(fg);
line.addLatLng(marker.getLatLng());
marker.bindPopup('<strong>' + data[row].Info + '</strong>');
destinations.push({
marker,
data: data[row],
id: row
});
destinationHTML.innerHTML += "<div class='destination-elm' onclick='destinationClick(\""+row+"\")'><span>"+data[row].Info+"</span></div>"
}
map.fitBounds(fg.getBounds());
}
function destinationClick(id){
console.log(id)
destinations.forEach(function(obj){
if(obj.id == id){
map.panTo(obj.marker.getLatLng());
}
})
}
Example: https://jsfiddle.net/falkedesign/k3b4nups/

Related

iOS - Google Maps Places onclick conflicts with map onclick

I have a project created with ionic. In here I have a Google Map with a places search box.
I have included the Google Map library like so:
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=SOMEKEY&libraries=places" defer></script>
Now in my TypeScript code I have the following
// init the google map
initMap() {
var centerOfMap;
var draggableMarker = false;
this.mapHasBeenInitialized = true;
this.isStaticLocation = false;
centerOfMap = new google.maps.LatLng(this.locationService.gpsLat, this.locationService.gpsLong);
draggableMarker = true;
var options = {
center: centerOfMap,
zoom: 11,
fullscreenControl: false,
disableDefaultUI: true, // dont allow default zoom/sattelite/street view
gestureHandline: 'cooperative' // disable moving map with one finger
};
this.map = new google.maps.Map(this.googleMap.nativeElement, options);
this.marker = new google.maps.Marker({
position: centerOfMap,
map: this.map,
draggable: draggableMarker
});
if(!this.isStaticLocation) {
var searchBox = new google.maps.places.SearchBox(this.googleInput.nativeElement);
// add the searchbar to the google map
this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(this.googleInput.nativeElement);
// Bias the SearchBox results towards current map's viewport
this.map.addListener('bounds-changed', () => {
searchBox.setBounds(this.map.getBounds());
});
searchBox.addListener('places_changed', () => {
var places = searchBox.getPlaces();
if(places.length == 0) {
return;
}
var bounds = new google.maps.LatLngBounds();
places.forEach(place => {
if(!place.geometry) {
console.log("returned place contains no geometry");
return;
}
this.setMarkerLocation(place);
if(place.geometry.viewport) {
bounds.union(place.geometry.viewport);
} else {
bounds.extends(place.geometry.location);
}
});
this.map.fitBounds(bounds);
});
}
if(draggableMarker) {
google.maps.event.addListener(this.marker, 'dragend', (event)=>{
this.getMarkerLocation();
});
}
google.maps.event.addListener(this.map, 'click', (event: any)=> {
var clickedLocation = event.latLng;
this.marker.setPosition(clickedLocation);
this.getMarkerLocation();
});
// neccessary for reload. Made async to trick loading process
setTimeout(()=> {
google.maps.event.trigger(this.googleMap.nativeElement, 'resize');
this.map.setCenter(centerOfMap);
}, 100);
}
// function to set the location marker on a different spot
setMarkerLocation(place: any) {
this.marker.setMap(null);
this.marker = new google.maps.Marker({
position: place.geometry.location,
map: this.map,
draggable: true
});
this.getMarkerLocation();
}
getMarkerLocation() {
var currLoc = this.marker.getPosition();
this.locationService.setGoogleMapsLocation(currLoc.lat(), currLoc.lng());
this.locationChanged = true;
}
And this code works like a charm in the browser and on Android. Basically what the code does is whenever someone taps on the map, the marker position changes to their tap location.
When a person searches for a Place, the places dropdown will show over the map. On android, when you tap a place in this dropdown, the marker will go to the selected place (f.e. australia).
On iOS however, the marker will position itself on the location where the person tapped and will totally ignore the tap on the place dropdown.
So when I'm in Europe and I type in 'Australia' and select 'Australia' from my dropdown, on Android I'll go to australia but on iOS I'll stay somewhere in Europe wherever the dropdown was positioned.

Anystock comparisonMode same value in tooltip

When using a stock chart, I am using the comparisonMode with a date. The value displayed by the crosshair is correct, but the value in the tooltip is the real value (not compared). How could I display the compared value instead?
As you can see on the picture, the compared value is 107.1 but the tooltip is displaying the actual value 893.5. I am using anychart 8.0.0
I'm glad to inform you that in the new version of AnyStock 8.1.0 the calculated change value is available right from the point information. It may be used in tooltips and legends. I guess this is exactly what you were looking for.
The example of using this feature you may find on this link.
Now the context of every point includes valueChange and valuePercentChange properties.
This feature requires a few additional lines of JS code, I prepared an example below to show how it works. Now compared value is shown in cross-hair label, in the tooltip, and in legend.
anychart.onDocumentReady(function() {
var dataTable = anychart.data.table();
dataTable.addData(get_dji_daily_short_data());
var firstMapping = dataTable.mapAs({'value': 1});
var secondMapping = dataTable.mapAs({'value': 3});
chart = anychart.stock();
var plot = chart.plot();
var series0 = plot.line(firstMapping);
var series1 = plot.line(secondMapping);
var yScale = plot.yScale();
// Set comparison mode.
yScale.comparisonMode("value");
var xScale = chart.xScale();
chart.container("container");
chart.draw();
//reference points of both series
var firstVisibleValue0 = null;
var firstVisibleValue1 = null;
//after chart rendering format tooltip and legend
getVisibleValues();
tooltipLegendFormat(firstVisibleValue0, firstVisibleValue1);
//after every scroll change recalculate reference points
//and reformat tooltip and legend
chart.scroller().listen('scrollerchange', function() {
getVisibleValues();
tooltipLegendFormat(firstVisibleValue0, firstVisibleValue1);
});
function getVisibleValues() {
// Gets scale minimum.
var minimum = xScale.getMinimum();
//select data from mappings
var selectable0 = firstMapping.createSelectable();
var selectable1 = secondMapping.createSelectable();
// Sets value for search.
var select0 = selectable0.search(minimum, "nearest");
var select1 = selectable1.search(minimum, "nearest");
// get values in first visible points
firstVisibleValue0 = select0.get('value');
firstVisibleValue1 = select1.get('value');
}
function tooltipLegendFormat(firstVisibleValue0, firstVisibleValue1) {
//format tooltips and legends of both series
series0.tooltip().format(function () {
return 'Series 0: ' + Math.round(this.value - firstVisibleValue0);
});
series0.legendItem().format(function(){
return 'Series 0: ' + Math.round(this.value - firstVisibleValue0);
});
series1.tooltip().format(function () {
return 'Series 1: ' + Math.round(this.value - firstVisibleValue1);
});
series1.legendItem().format(function(){
return 'Series 1: ' + Math.round(this.value - firstVisibleValue1);
});
}
});
html, body, #container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
<script src="https://cdn.anychart.com/releases/8.0.1/js/anychart-base.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.0.1/js/anychart-stock.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.0.1/js/anychart-exports.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.0.1/js/anychart-ui.min.js"></script>
<script src="https://cdn.anychart.com/csv-data/dji-daily-short.js"></script>
<link rel="stylesheet" href="https://cdn.anychart.com/releases/8.0.1/css/anychart-ui.min.css" />
<div id="container"></div>

automatic geolocation in ruby

I jus started learn ruby on rails and currently I am creating my first rails app. And I ran into some problems. In my app, I would like to get user's position (latitude, longitude). So I can put the button "find me" and return user's locations. But I would like to load my page and show my position (latitude, longitude), don't press any buttons. And then use lat and lng in my controllers. How can I do this?
Add the below script in your view page.You may go ahead and modify this as needed as to show/customise messages and buttons.Remember to have a dedicated div with id="map-canvas" to show you map on the page.
I have used geocomplete.js to show map and allow user to enter places from search box .You may remove the scripts using geocomplete if not needed.
<script type="text/javascript">
// Enable the visual refresh
// google.maps.visualRefresh = true;
var map;
var mapOptions = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: '<p>You are here!</p>'
});
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}//initialize ends
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = '<p>Unable to find the current location</p>';
} else {
var content = '<p Your browser doesn\'t support geolocation.</p>';
}
var options = {
map: map,
zoom: 5,
position: new google.maps.LatLng(60, 105),
content: content
};
var marker = new google.maps.Marker({
position: new google.maps.LatLng(60, 105),
map: map,
animation: google.maps.Animation.DROP,
title: 'Sorry,we were unable to find your location'
});
marker.setAnimation(google.maps.Animation.BOUNCE);
var infowindow = new google.maps.InfoWindow(options);
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
infowindow.open(map,marker);
map.setCenter(options.position);
}//handleNoGeolocation ends
//load the page and execute above scripts
$(document).ready(function(){
$('#map-canvas').html("<p class='text-center text-alert'>Loading map...</p>").show(3000);
//load the map after 2 seconds
setTimeout('initialize()', 3000);
// $("#geocomplete").geocomplete({
// map: ".map-canvas-guest"
// });
//you may use this or remove this section using geocomplete.js if not needed.
$("#geocomplete").geocomplete();
$("#geocomplete").geocomplete(mapOptions).bind("geocode:result", function(event, result){
console.log(result.formatted_address);
//use this user entered address and you may call ajax here as well
})
})//document ends
</script>

Document name in geoxml3

My kml is as under
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Car Parks</name>
<description>Car Parks</description>
<Folder>
<name>Data Objects</name>
<open>1</open>
<description>data objects</description>
<Placemark id="CP11">
<name>CP11</name>
<description>CP11</description>
<styleUrl>#0-normal</styleUrl>
<Point>
<coordinates>4.878205,52.371968,0</coordinates>
</Point>
</Placemark>
</Folder>
</Document>
</kml>
My javascript is as under
geoXml = new geoXML3.parser({
createMarker: createMarker
});
createMarker:function(placemark, doc) {
var markerOptions = {
optimized: false
};
// Create the marker on the map
var marker = new google.maps.Marker(markerOptions);
if (!doc) {
doc.markers.push(marker);
}
google.maps.event.addListener(marker, 'click', function()
{
// I want to access the document name here of 'car Parks'
alert(doc.Document);
});
}
How can I get document name in marker click event of the marker? Basically when I click the marker on the map, I want to know the type of marker the user has clicked on.
There is an optional placemark parse function
pmParseFn
Which is passed a reference to the xml DOM for its associated placemark. example using it
It isn't really designed for your purpose, but if your KML format is fixed, you can get the <name> of the <Document> tag by doing this:
var map;
var geoXml = null;
function initialize() {
var latlong = new google.maps.LatLng(59.32, 13.48);
var googlemaps_options = {
zoom: 18,
center: latlong,
mapTypeId: google.maps.MapTypeId.SATELLITE,
streetViewControl: false
}
map = new google.maps.Map(document.getElementById('map_canvas'), googlemaps_options);
geoXml = new geoXML3.parser({
createMarker: createMarker,
pmParseFn: parsePlacemark,
map:map
});
geoXml.parse("http://www.geocodezip.com/geoxml3_test/SO_20140306_name.kml");
}
// Custom placemark parse function
function parsePlacemark (node, placemark) {
var addressNodes = node.parentNode.parentNode.getElementsByTagName('name');
var address = null;
if (addressNodes && addressNodes.length && (addressNodes.length > 0)) {
placemark.docName = geoXML3.nodeValue(addressNodes[0]);
}
}
function createMarker(placemark, doc) {
var markerOptions = {
optimized: false,
position: placemark.latlng,
map: map
};
// Create the marker on the map
var marker = new google.maps.Marker(markerOptions);
if (!doc) {
doc.markers.push(marker);
}
google.maps.event.addListener(marker, 'click', function()
{
// I want to access the document name here of 'car Parks'
alert(placemark.docName);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
working example
working example with 2 different KML files

openstreetmap geolocation

I'm newbie, I'm reading in internet the possibilities of openstreetmap, and also I read about openlayers...What I need, for begin, is obtain the location and create the corresponding map...I found a good example with openlayers, this is the code:
<html>
<head>
<title>HTML5 geolocation with Openstreetmap and OpenLayers</title>
<style type="text/css">
html, body, #basicMap {
width: 240;
height: 320;
margin: 10;
}
</style>
<script src="http://openlayers.org/api/OpenLayers.js"></script>
<script>
function init() {
map = new OpenLayers.Map("basicMap");
var mapnik = new OpenLayers.Layer.OSM();
map.addLayer(mapnik);
navigator.geolocation.getCurrentPosition(function(position) {
document.getElementById('anzeige').innerHTML="Latitude: " + position.coords.latitude + " Longitude: " +
position.coords.longitude + "<p>";
var lonLat = new OpenLayers.LonLat(position.coords.longitude,
position.coords.latitude)
.transform(
new OpenLayers.Projection("EPSG:4326"), //transform from WGS 1984
map.getProjectionObject() //to Spherical Mercator Projection
);
markers.addMarker(new OpenLayers.Marker(lonLat));
map.setCenter(lonLat, 14 // Zoom level
);
});
//map = new OpenLayers.Map("basicMap");
//var mapnik = new OpenLayers.Layer.OSM();
//map.addLayer(mapnik);
map.setCenter(new
OpenLayers.LonLat(3,3) // Center of the map
.transform(
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
new OpenLayers.Projection("EPSG:900913") // to Spherical Mercator Projection
), 15 // Zoom level
);
var markers = new OpenLayers.Layer.Markers( "Markers" );
map.addLayer(markers);
}
</script>
</head>
<body onload="init();">
<center>
HTML5 geolocation:
<br>
<div id="basicMap"></div>
<br>HTML5 geolocation<br>
<br>with Openstreetmap and OpenLayers<br>
For Android Froyo,iPhone,iPAD,iPod
<br>
Your position estimated by browser geolocation API:<p>
<div id="anzeige">(will be displayed here)<p></div>
Andreas Bischoff
<br>(view source to see how it works
</center>
</body>
</html>
You can see a live example here: http://www.pediaphon.org/~bischoff/location_based_services/
Next step, I need draw a scretch line which displays the rute followed. Here is a live example of drawing lines (pressing shift + clicking on mouse): http://openlayers.org/dev/examples/draw-feature.html
But I'm new and I'm lost in how call api of openlayers in order to draw line from origin to destination...any help is welcome
Best regards.
EDIT:
I just copied this peace of code ( Drawing a path with a line in OpenLayers using JavaScript ) just before the tag, but I don't see the line drawn:
var lineLayer = new OpenLayers.Layer.Vector("Line Layer");
map.addLayer(lineLayer);
map.addControl(new OpenLayers.Control.DrawFeature(lineLayer, OpenLayers.Handler.Path));
var points = new Array(
/*I put these coords of my city*/
new OpenLayers.Geometry.Point(-3.7904085, 37.76225609999999 ),
new OpenLayers.Geometry.Point(-4.7904085, 39.76225609999999 )
);
var line = new OpenLayers.Geometry.LineString(points);
var style = {
strokeColor: '#0000ff',
strokeOpacity: 0.5,
strokeWidth: 5
};
var lineFeature = new OpenLayers.Feature.Vector(line, null, style);
lineLayer.addFeatures([lineFeature]);

Resources