I am building a website, and on it I have a Google Map. I also have a list of business names, e.g. WH Smith, Manchester.
Assuming there is only one in Manchester, how can I get a Marker showing on my Map the location of the WH Smith branch?
I tried searching, but found nothing on the subject !
The way I do it is to set up an array of locations, each of which is an array of the necessary information, in the order html for tooltip, latitude, longitude, title. I get the Latitude and Longitude from this site: http://universimmedia.pagesperso-orange.fr/geo/loc.htm So you would just type in the city center.
function initialize() {
geocoder = new google.maps.Geocoder();
var businesslocations = [
['HTML TO DISPLAY ON TOOLTIP', LATITUDE, LONGITUDE,'LOCATION NAME'],
['HTML TO DISPLAY ON TOOLTIP', LATITUDE, LONGITUDE,'LOCATION NAME'],
Finish that array off, then do your other map settings. Then set up the map. Then set up its markers programmatically using that array. The for loop goes through the different locations, and then pulls out the 4 elements of the array.
var bounds = new google.maps.LatLngBounds();
var infowindow = new google.maps.InfoWindow();
var marker, x;
for (x = 0; x < businesslocations.length; x++) {
var latllong = new google.maps.LatLng(businesslocations[x][1], businesslocations[x][2]);
marker = new google.maps.Marker({
position: latlong,
map: map,
title: businesslocations[i][3]
});
bounds.extend(latlong);
google.maps.event.addListener(marker, 'click', (function(marker, x) {
return function() {
infowindow.setContent(businesslocations[x][0]);
infowindow.open(map, marker);
}
})(marker, x));
}
map.fitBounds(bounds);
Related
Is it possible to indicate events along a series in amCharts v4 similar to the Stock Event in the v3 stock chart?
While I was brought on board specifically for v4 and am not familiar with v3, I'm confident you can simulate some of these features using Bullets.
A bullet is a Container (basically a placeholder parent for whatever visual object or additional Containers that you want), that will appear at every point of data. You can put a label there as well as a line and any other shape, e.g.:
var stockBullet = series.bullets.push(new am4charts.Bullet());
stockBullet.dy = -20;
var circle = stockBullet.createChild(am4core.Circle);
circle.stroke = "#000";
circle.strokeWidth = 1;
circle.radius = 10;
circle.fill = series.fill.brighten(-0.3);
circle.dy = -10;
var line = stockBullet.createChild(am4core.Line);
line.stroke = "#000";
line.strokeWidth = 1;
line.height = 20;
var label = stockBullet.createChild(am4core.Label);
label.fill = am4core.color("#000");
label.strokeWidth = 0;
label.dy = -20;
label.textAlign = "middle";
label.horizontalCenter = "middle"
Since we don't want a bullet to appear at every point of data, only at Stock Events, we can handle that once the bullets are ready on the chart by going through their data, disabling them if need be, otherwise providing text for our label (and maybe tooltipText if need be) (presume there is a property stockEvent in the data):
stockBullet.events.on("inited", function(event) {
if (event.target.dataItem && event.target.dataItem.dataContext && event.target.dataItem.dataContext.stockEvent) {
event.target.children.getIndex(2).text = event.target.dataItem.dataContext.stockEvent.text;
} else {
event.target.disabled = true;
}
});
Getting tooltips of different objects to play well with each other can be tricky depending on your chart, e.g. if it has Chart Cursor enabled there's a cursorTooltipEnabled property to prevent triggering a tooltip over bullets. To simplify things in this case what I did is make an invisible series per unique stock event bullet. For each stock event, use adapters to set its paired series' tooltipText to what's desired, and the base, visible series' tooltipText to "":
series.adapter.add("tooltipText", function(text, target) {
if (target.tooltipDataItem.dataContext.stockEvent) {
return "";
}
return text;
});
// ...
hiddenSeries.adapter.add("tooltipText", function(text, target) {
if (target.tooltipDataItem.dataContext.stockEvent) {
return target.tooltipDataItem.dataContext.stockEvent.description;
}
return "";
});
Here's a demo:
https://codepen.io/team/amcharts/pen/337984f18c6329ce904ef52a0c3eeaaa
Screenshot:
I am currently able to restrict places to only one country, but I also want to restrict on a specific city also. Any ideas how to achieve that? This is my current code:
var autocomplete,
options = {
types: ['geocode'],
componentRestrictions: {country: 'est'}
};
autocomplete = new google.maps.places.Autocomplete(input, options);
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var place = autocomplete.getPlace().formatted_address;
$(input).attr('value',place);
});
As Luke said the places autocomplete allows you to use componentRestrictions to filter by country only.
But you can use a little trick with a search request string.
Just add prefix with city name in request.
var prefix = 'Kyiv, ';
$(input).on('input',function(){
var str = input.value;
if(str.indexOf(prefix) == 0) {
// string already started with prefix
return;
} else {
if (prefix.indexOf(str) >= 0) {
// string is part of prefix
input.value = prefix;
} else {
input.value = prefix+str;
}
}
});
http://jsfiddle.net/24p1et98/
Places Autocomplete currently allows you to use componentRestrictions to filter by country. What I would do in your situation is to use the options argument to filter by the bounds that define the city in question:
var cityBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(25.341233, 68.289986),
new google.maps.LatLng(25.450715, 68.428345));
var options = {
bounds: cityBounds,
types: ['geocode'],
componentRestrictions: {country: 'est'}
};
Google Provides two ways to achieve this. If you are not satisfied because in countries like India it do not work well, because states and provisions here do not have rectangular or structure boundaries.
1.LatLngBounds (LatLng southwest, LatLng northeast): Where you can give latitude and longitude to form an rectangle.
2. Location (Lat,Lng) & Radius: Where you can give latitude and longitude to form a circle.
But the problem with these approaches they do not provide expected results if you are from countries like India, where states and provisions are not in structured shapes (Rectangular) as in USA.
If you are facing same issue than there is an hack.
With jQuery/Jacascript, you can attach functions which will consistently maintain city name in text input which is bounded with Autocomplete object of Places API.
Here it is:
<script>
$(document).ready(function(){
$("#locality").val(your-city-name) //your-city-name will have city name and some space to seperate it from actual user-input for example: “Bengaluru | ”
});
$("#locality").keydown(function(event) { //locality is text-input box whixh i supplied while creating Autocomplete object
var localeKeyword = “your-city-name”
var localeKeywordLen = localeKeyword.length;
var keyword = $("#locality").val();
var keywordLen = keyword.length;
if(keywordLen == localeKeywordLen) {
var e = event || window.event;
var key = e.keyCode || e.which;
if(key == Number(46) || key == Number(8) || key == Number(37)){
e.preventDefault();
}//Here I am restricting user to delete city name (Restricting use of delete/backspace/left arrow) if length == city-name provided
if(keyword != localeKeyword) {
$("#locality").val(localeKeyword);
}//If input-text does not contain city-name put it there
}
if(!(keyword.includes(localeKeyword))) {
$("#locality").val(localeKeyword);
}//If keyword not includes city name put it there
});
I am using openlayers 3. From the values contained in a vector GeoJSON, I want to fill a dropdown menu. When selecting a value from the dropdown menu, I want to zoom in on the entity.
My problem now is that I want to generate my HTML from the attributes of my GeoJSON. So I tried this simple code but it doesn't work :
var menu = document.getElementById('menuDropDown');
vector2.getSource().forEachFeature(function() {
menu.innerHTML = feature.get('NOM').join(', ');
});
EDIT:
I'm able to populate a dropdown menu from a list:
var list = ['a','b','c'];
var mySelect = $('#mySelect');
$.each(list, function(val, text) {
mySelect.append(
$('<option></option>').val(val).html(text)
);
});
What i want to do it's to populate this list from the attribute of my vector
So i try this:
// vector2 it's a GeoJSON who is integrate on my map
vector2.getSource().getFeatures().forEachFeature(function(feature) {
list.push(feature.get('NOM'));
});
Firstly I'm assuming you have to pass some parameter to your callback:
vector2.getSource().forEachFeature(function(feature) {
Then you can append an item to a dropdown like so:
var item = document.createElement('option');
item.setAttribute('value', feature.get('NOM'));
var textNode = document.createTextNode(feature.get('NOM'));
item.appendChild(textNode)
menu.appendChild(item);
All together:
var menu = document.getElementById('menuDropDown');
vector2.getSource().forEachFeature(function(feature) {
var item = document.createElement('option');
item.setAttribute('value', feature.get('NOM'));
var textNode = document.createTextNode(feature.get('NOM'));
item.appendChild(textNode)
menu.appendChild(item);
});
I have resolve my problem:
vector2.getSource().on('change', function(evt){
var source = evt.target;
var list = [];
source.forEachFeature(function(feature) {
list.push(feature.get('NOM'));
});
// console.log("Ecrit moi les noms : " + list);
Thanks you to those who took the time to respond
Google maps and Bing maps have methods that can give the directions from point A to point B on a map. This highlights a path from A to B on the map - call this P1
Suppose, P2 is another path from C to D (some other points), how can we find the longest common length of path between paths P1 and P2?
You have plenty of ways to do what you want.
Curiously, I tried to do it using JavaScript only and to do so, I used JSTS library that would compute the intersection between two routes (in my case, the geometry were retrieved from Bing, but I did not include the request in this example as it's not helpful).
Use case:
So, you want to have the common path between two paths (or the part of a route where you can use car-sharing or where you can run with your friend for example), if this is correct, then this example will help you.
Libraries:
First, the following library is need: JSTS, you can get it through Github dedicated repository: https://github.com/bjornharrtell/jsts
On other interesting library is Turf available here: https://github.com/Turfjs/
Implementation with JSTS and leaflet:
Here is the piece of JavaScript that will be interesting in this case:
<script type="text/javascript">
var routeCoordinatesA = [[50.619512, 3.061242]....TRUNCATED FOR READIBILITY** ];
var routeCoordinatesB = [[50.619512, 3.061242]....TRUNCATED FOR READIBILITY** ];
$(function () {
var map = L.map('map').setView([47.5, 2.75], 5);
// Add base tile layer - sample from Leaflet website
L.tileLayer('http://{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var polylineA = L.polyline(routeCoordinatesA, { color: '#4b98dc' }).addTo(map);
var polylineB = L.polyline(routeCoordinatesB, { color: '#de6262' }).addTo(map);
var geometryFactory = new jsts.geom.GeometryFactory();
// Coordinates adapted to match for jsts
var coordsA = [];
$.each(routeCoordinatesA, function (idx, current) { coordsA.push([current[1], current[0]]); });
var coordsB = [];
$.each(routeCoordinatesB, function (idx, current) { coordsB.push([current[1], current[0]]); });
// Element A
var coordinatesA = bindCoord2JTS(coordsA);
var shellA = geometryFactory.createLinearRing(coordinatesA);
var jstsPolygonA = geometryFactory.createPolygon(shellA);
// Element b
var coordinatesB = bindCoord2JTS(coordsB);
var shellB = geometryFactory.createLinearRing(coordinatesB);
var jstsPolygonB = geometryFactory.createPolygon(shellB);
// Interection
var bufferTolerance = (2 / 1000); // Small buffer to avoid different node no detection
var intersection = shellA.buffer(bufferTolerance).intersection(shellB);
var intersectionPoints = [];
$.each(intersection.getCoordinates(), function (idx, current) {
intersectionPoints.push([current.x, current.y]);
});
intersectionPoints.pop();
var intersectionLine = L.polyline(intersectionPoints, { color: '#4fc281', weight: 8 }).addTo(map);
map.fitBounds(routeCoordinatesA.concat(routeCoordinatesB));
});
var bindCoord2JTS = function (coords) {
var coordinates = [];
for (var i = 0; i < coords.length; i++) {
coordinates.push(new jsts.geom.Coordinate(
coords[i][1], coords[i][0]));
}
return coordinates;
};
You can grab all the working example among my Leaflet experiments available on Github as well:
https://github.com/nicoboo/maps/tree/master
And here the page that implements what I was talking about:
https://github.com/nicoboo/maps/blob/master/Boo.Maps.Web.LeafletExperiments/LeafletWithin/index.html
Here for the live demo: http://htmlpreview.github.io/?https://github.com/nicoboo/maps/blob/master/Boo.Maps.Web.LeafletExperiments/LeafletWithin/index.html
Considerations:
Of course, this is really based on the client side and it might be usefull to have the information on the server-side, I would recommend to use a spatially enabled database so you can use the STBuffer() and STIntersection() methods directly on the column or results that you manipulate with the best performances.
I am not sure to fully understand your request but both Bing maps ans Google maps API for the directions contains in their response a "distance" field which specifies the value of the directions.
Here are two links for both documentation:
Bing Maps & Google Maps
With that you could compare the distance value between the two path and find the longest.
Hope this help.
First of, newbie here. SO please bear with my question. :)
Let's say I have a location(lat/long) extracted from my database, and I want to use this location as the position of where the marker is plotted in the map.
How to do?
I've tried implementing some codes I've found here, but doesn't seem to work for me.
Here's what I have so far:
var center;
var myLatlng;
function initialize() {
myLatlng = new google.maps.LatLng(document.getElementById("txtLatLng"));
var mapOptions = {
zoom: 12,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map
});
google.maps.event.addDomListener(window, 'load', initialize);
I'm trying to replace the value of myLatLng variable with txtbox value, but no luck.
PS. I'm aware that this is on event load. which leads me to my 2nd question, how to do all of this in event btnClick?
Thanks in advance!
Check example at jsbin.
You can use one input field as you started but you have to parse it. I left it there and add basic parsing. That part is not triggered with button click.
For me it's better to have separate input field for latitude and longitude: added two input fields and button which triggers function:
function setMarker() {
var latitude = latEl.value;
var longitude = lngEl.value;
if (latitude == '' || longitude == '') {
console.log('lat or lng not defined');
return;
}
var position = new google.maps.LatLng(parseFloat(latitude),
parseFloat(longitude));
var marker = new google.maps.Marker({
position: position,
map: map
});
map.setCenter(position);
}
setCenter() is called to position marker to the center. Otherwise it could happen that it is off the visible part.