Show marker based on user-defined Lat/Long in Google Map on button click - google-maps-markers

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.

Related

Tooltip disappears when moving leaflet map

I add markers to the map and place them in the markercluster. For markers that are not clustered, I want to show the tooltip that I attach to the marker when I create it.
var geoMarkers = L.markerClusterGroup({ removeOutsideVisibleBounds:true, chunkedLoading: true, chunkProgress: this._updateProgress });
//start loop create markers
var marker = new L.marker(latlng, { icon: icon } );
marker.bindPopup(L._("Loading.."));
marker.bindTooltip(' text ');
geoMarkers.addLayer(marker);
//end loop
map.addLayer(geoMarkers);
map.on('layeradd', function(event) {
var layer = event.layer;
if (layer instanceof L.Marker && !(layer instanceof L.MarkerCluster)) {
layer.openTooltip();
}
});
To do this, I followed advice and listen for the layeradd event. When loading the map and moving to new markers, everything works. However, at any movement of the map, on those markers where the tooltip is already open, it is closed, since the layeradd event does not affect them. There is only one way to see the hint on them again - to zoom out so that the marker "hides" in the cluster and then again increasing the scale, I see the hint again. It is desirable that it be always present when the marker is not hidden in the cluster.
I ask for help or hints.
You can use the permanent tooltip option in order to maintain the visibility of your marker. Check here for official docs.
...
var geoMarkers = L.markerClusterGroup({ removeOutsideVisibleBounds:true, chunkedLoading: true, chunkProgress: this._updateProgress });
//start loop create markers
var marker = new L.marker(latlng, { icon: icon } );
marker.bindPopup(L._("Loading.."));
marker.bindTooltip(' text ', { permanent: true} ); // here define it
geoMarkers.addLayer(marker);
//end loop

AmCharts AmMap - Set starting location for zoom actions

I would like to use the "zoomToMapObject" method based on a selection on a dropdown menu.
For some reason the start zoom location is the middle of the map and not the set the geoPoint.
(The zooming works but the start location make it look a bit weird.)
My current approach looks like this:
const duration = this.chart.zoomToMapObject(selectedPoloygon, this.countryZoom, true).duration;
setTimeout(() => {
this.chart.homeGeoPoint = geoPoint;
this.chart.homeZoomLevel = this.countryZoom;
}, duration);
this.handleCountrySelection(selectedPoloygon);
Somehow even setting the homeGeoPoint / homeZoomLevel doesn't affect next zoom actions.
**UPDATE: Workaround heavy cost (from 1300 nodes to over 9000) **
I examined the problem a step further. It seems the middle point gets set when I push a new mapImageSeries into the map.
My workarround currently is to draw all points on the map and hide them.
Then after I select a country I change the state to visible.
However this approach is very costly. The DOM-Nodes rises from 1300 to ~ 9100.
My other approach with creating them after a country has been selected AND the zoom animation finished was much more
effective. But due to the map starting every time for a center location it is not viable? Or did I do s.th. wrong?
Here is my current code which is not performant:
// map.ts
export class MapComponent implements AfterViewInit, OnDestroy {
imageSeriesMap = {};
// ... standard map initialization ( not in zone of course )
// creating the "MapImages" which is very costly
this.dataService.getCountries().forEach(country => {
const imageSeriesKey = country.id;
const imageSeriesVal = chart.series.push(new am4maps.MapImageSeries()); // takes arround 1-2 ms -> 300 x 2 ~ 500 ms.
const addressForCountry = this.dataService.filterAddressToCountry(country.id); // returns "DE" or "FR" for example.
const imageSeriesTemplate = imageSeriesVal.mapImages.template;
const circle = imageSeriesTemplate.createChild(am4core.Circle);
circle.radius = 4;
circle.fill = am4core.color(this.colorRed);
circle.stroke = am4core.color('#FFFFFF');
circle.strokeWidth = 2;
circle.nonScaling = true;
circle.tooltipText = '{title}';
imageSeriesTemplate.propertyFields.latitude = 'latitude';
imageSeriesTemplate.propertyFields.longitude = 'longitude';
imageSeriesVal.data = addressForCountry.map(address => {
return {
latitude: Number.parseFloat(address.lat),
longitude: Number.parseFloat(address.long),
title: address.company
};
});
imageSeriesVal.visible = false;
this.imageSeriesMap[imageSeriesKey] = imageSeriesVal;
});
// clicking on the map
onSelect(country) {
this.imageSeriesMap[country].visible = true;
setTimeout( () => {
const chartPolygons = <any>this.chart.series.values[0];
const polygon = chartPolygons.getPolygonById(country);
const anim = this.chart.zoomToMapObject(polygon, 1, true, 1000);
anim.events.on('animationended', () => {});
this.handleCountrySelection(polygon);
}, 100);
});
}
handleCountrySelection(polygon: am4maps.MapPolygon) {
if (this.selectedPolygon && this.selectedPolygon !== polygon) {
this.selectedPolygon.isActive = false;
}
polygon.isActive = true;
const geoPoint: IGeoPoint = {
latitude: polygon.latitude,
longitude: polygon.longitude
};
this.chart.homeGeoPoint = geoPoint;
this.chart.homeZoomLevel = this.countryZoom;
this.selectedPolygon = polygon;
}
}
Thanks to your thorough followup I was able to replicate the issue. The problem you were having is triggered by any one of these steps:
dynamically pushing a MapImageSeries to the chart
dynamically creating a MapImage via data (also please note in the pastebind you provided, data expects an array, I had to change that while testing)
In either step, the chart will fully zoom out as if resetting itself. I'm going to look into why this is happening and if it can be changed, so in the meantime let's see if the workaround below will work for you.
If we only use a single MapImageSeries set in advance (I don't particularly see a reason to have multiple MapImageSeries, would one not do?), that eliminates problem 1 from occurring. Asides from data, we can create() MapImages manually via mapImageSeries.mapImages.create(); then assign their latitude and longitude properties manually, too. With that, problem 2 does not occur either, and we seem to be good.
Here's a demo with a modified version of the pastebin:
https://codepen.io/team/amcharts/pen/c460241b0efe9c8f6ab1746f44d666af
The changes are that the MapImageSeries code is taken out of the createMarkers function so it only happens once:
const mapImageSeries = chart.series.push(new am4maps.MapImageSeries());
const imageSeriesTemplate = mapImageSeries.mapImages.template;
const circle = imageSeriesTemplate.createChild(am4core.Circle);
circle.radius = 10;
circle.fill = am4core.color('#ff0000');
circle.stroke = am4core.color('#FFFFFF');
circle.strokeWidth = 2;
circle.nonScaling = true;
circle.tooltipText = 'hi';
In this case, there's no need to pass chart to createMarkers and return it, so I've passed polygon instead just to demo dynamic latitude/longitudes, I also assign our new MapImage to the polygon's data (dataItem.dataContext) so we can refer to it later. Here's the new body of createMarkers:
function createMarkers(polygon) {
console.log('calling createMarkers');
if ( !polygon.dataItem.dataContext.redDot) {
const dataItem = polygon.dataItem;
// Object notation for making a MapImage
const redDot = mapImageSeries.mapImages.create();
// Note the lat/long are direct properties
redDot.id = `reddot-${dataItem.dataContext.id}`;
// attempt to make a marker in the middle of the country (note how this is inaccurate for US since we're getting the center for a rectangle, but it's not a rectangle)
redDot.latitude = dataItem.north - (dataItem.north - dataItem.south)/2;
redDot.longitude = dataItem.west - (dataItem.west - dataItem.east)/2;;
dataItem.dataContext.redDot = redDot;
}
}
There's no need for the animationended event or anything, it just works since there is no longer anything interfering with your code. You should also have your performance back.
Will this work for you?
Original answer prior to question's edits below:
I am unable to replicate the behavior you mentioned. Also, I don't know what this.countryZoom is.
Just using the following in a button handler...
chart.zoomToMapObject(polygon);
...seems to zoom just fine to the country, regardless of the current map position/zoomLevel.
If you need to time something after the zoom animation has ended, the zoomToMapObject returns an Animation, you can use its 'animationended' event, e.g.
const animation = this.chart.zoomToMapObject(selectedPoloygon, this.countryZoom, true);
animation.events.on("animationended", () => {
// ...
});
Here's an example with all that with 2 external <button>s, one for zooming to USA and the other Brazil:
https://codepen.io/team/amcharts/pen/c1d1151803799c3d8f51afed0c6eb61d
Does this help? If not, could you possibly provide a minimal example so we can replicate the issue you're having?

Three.js - How the functions of object3D.children can be accessed?

I'm trying to use line like this
myObject3D.children.forEach(
function(pChild){
return pChild.position.multiplyScalar(myMultiplier)
}
);
and this
myObject3D.children.forEach(
function(pChild){
pChild.position.copy(myVector3)
}
);
But for some reasons, functions in child elements of 'myObject3D' seems to be inexistent. ("Uncaught TypeError: pChild.position.multiplyScalar is not a function")
However, elements in 'myObject3D' are 'Mesh' objects.
Can anybody suggest what can I do?
Thanks
First, your forEach callback shouldn't return anything.
There doesn't appear to be anything wrong with your second code segment.
The code below runs without errors.
var group = new THREE.Object3D();
var geo = new THREE.BoxBufferGeometry(10, 10, 10);
var mat = new THREE.MeshBasicMaterial({
color: "red"
});
var mesh = new THREE.Mesh(geo, mat);
group.add(mesh);
group.add(mesh.clone());
group.add(mesh.clone());
group.add(mesh.clone());
group.add(mesh.clone());
var myVector3 = new THREE.Vector3();
group.children.forEach(function(pChild) {
pChild.position.multiplyScalar(5);
pChild.position.copy(myVector3)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.js"></script>
Please verify that you're populating your group with the correct kinds of objects. Also, you can always test if a function is available before using it:
if(obj.someFunction){
obj.someFunction();
}

Bing Maps API v7 Custom HTML pushpins in Firefox not positioned correctly

I've created an app where I use several custom HTML pushpins. Each one of these pushpins has a click event that will call setView on the map to center the map on the selected pin. This works perfectly in all browsers except for Firefox (testing version 22.0).
In Firefox, after the setView animation completes and the map is centered on the pushpin, the pushpin is then offset horizontally, vertically or both by a certain amount of pixels. The amount seems to correspond with amount of pixels the map has moved. If you then drag the map manually with the mouse, upon releasing the mouse button, the pushpin snaps back to its proper place. I've checked the top and left position values of the MapPushpinBase anchor tag in compared it with other browsers and the values differ.
Unfortunately, I cannot post a live example because the product has not yet been publicly released. But see below for the code I'm using.
this.clickHandlers.push(Microsoft.Maps.Events.addHandler(node, 'click', function (e) {
var element = $(e.target._htmlContent);
self.nodeHitboxHandler(element);
}));
Within the nodeHitboxHandler function, the only piece of Bing Map code is this:
this.map.setView({
center: new Microsoft.Maps.Location(panStart.latitude, panStart.longitude),
zoom: this.zoom,
mapTypeId: Microsoft.Maps.MapTypeId[self.mapTypeId]
});
Thanks in advance for any help.
UPDATE:
In order to make things clearer, I've created a simple example that demonstrates the problem. You can see it here: http://ginof.com/tests/bing/
In Firefox, try clicking on the different pushpins and watch the behaviour of the pushpin you've just clicked on after the map finishes panning to its new location. The map works fine in all browsers except Firefox.
Here's the complete JavaScript code for this example:
$(document).ready(function () {
var map = null,
initialCoordinates = {latitude: 40.71435, longitude: -74.00597},
initialPoint = new Microsoft.Maps.Location(initialCoordinates.latitude, initialCoordinates.longitude),
range = {
top: 3,
right: 5,
bottom: 0.01,
left: 5
},
mapOptions = {
credentials:"BING-MAPS-API-KEY",
disableKeyboardInput: true,
disableZooming: true,
enableClickableLogo: false,
enableSearchLogo: false,
showBreadcrumb: false,
showDashboard: false,
showMapTypeSelector: false,
showScalebar: false,
inertiaIntensity: 0.5,
mapTypeId: Microsoft.Maps.MapTypeId.birdseye,
labelOverlay: Microsoft.Maps.LabelOverlay.hidden,
center: initialPoint,
zoom: 14
};
function GetMap() {
// Initialize the map
map = new Microsoft.Maps.Map(document.getElementById("mapDiv"), mapOptions);
// Create nodes
map.entities.clear();
var pushpinOptions,
pushpin,
nodeCoordinates;
for (var i = 0; i < 5; i++) {
pushpinOptions = {width: null, height: null, htmlContent: '<div id="node' + i + '" class="node">' + i + '. Custom HTML</div>'};
nodeCoordinates = {latitude: initialCoordinates.latitude + i * 0.005, longitude: initialCoordinates.longitude + i * 0.005};
pushpin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(nodeCoordinates.latitude, nodeCoordinates.longitude), pushpinOptions);
pushpinClick = Microsoft.Maps.Events.addHandler(pushpin, 'click',
(function () {
var nodeId = i,
homeCoordinates = nodeCoordinates;
return function () {
console.log("node " + nodeId + " clicked.");
map.setView({center: new Microsoft.Maps.Location(homeCoordinates.latitude, homeCoordinates.longitude)});
}
})()
);
map.entities.push(pushpin);
}
}
GetMap();
});
Thanks again for any help.
This is a known issue which I was able to reproduce an has been escalated to the development team. Note that the Bing Maps forums are the best place to report these types of issues. You can find a similar thread on this topic here: http://social.msdn.microsoft.com/Forums/en-US/f77e6a80-2e0f-44c3-81cc-edb4c2327016/custom-html-pushpins-in-firefox-not-positioned-correctly

Get Marker on Google Maps via name of Business

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

Resources