I am having a hard time trying to add a simple clickable marker to an ArcGIS, map purely using JavaScript. All of the ArcGIS Samples seem to get their marker and related popup information from the server. How can I achieve the same result with ArcGIS as this Google Maps sample code below?
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<div id="map" style="width: 500px; height: 500px;"></div>
<script type="text/javascript">
window.onload = function() {
var myOptions = {
zoom: 2,
center: new google.maps.LatLng(40, -75),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"), myOptions);
var icon = new google.maps.MarkerImage("http://cinnamonthoughts.org/wp-content/uploads/2010/01/Custom-Marker-Avatar.png");
var markerOptions = {
icon: icon,
map: map,
position: new google.maps.LatLng(37.7699298, -122.4469157),
};
var marker = new google.maps.Marker(markerOptions);
google.maps.event.addListener(marker, 'click', function() {
var infoWindow = new google.maps.InfoWindow();
infoWindow.setContent("hello world");
infoWindow.open(map, marker);
});
};
</script>
Try this:
Create a Point for you longitude and latitude
Convert the point to Web Mercator spatial reference, if it's necessary
Create a PictureMarkerSymbol for you custom picture marker
Create a Graphic using the point and the symbol
Create a GraphicsLayer
Add the graphic to the graphic layer
Add the graphic layer to your map
Add a custom onClick event listener to your layer
Some equivalent code:
var point = new esri.geometry.Point(longitude, latitude);
point = esri.geometry.geographicToWebMercator(point);
var symbol = new esri.symbol.PictureMarkerSymbol("marker.png", 32, 32);
var graphic = new esri.Graphic(point, symbol);
var layer = new esri.layers.GraphicsLayer();
layer.add(graphic);
map.addLayer(layer);
dojo.connect(layer, "onClick", onClick);
On the event listener you can open a custom infoWindow or whatever you like:
function onClick(event) {
map.infoWindow(...)
...
Change "marker.png" and 32x32 to use your custom marker image and dimensions.
Try placing your image icon anywhere on the screen X Y using the CSS positioning then just put your onClick handler inside the actual DIV or IMG tag. Try playing with combination relative vs. absolute to get it just right.
div#header {
position: relative;
}
img#headimg {
position: absolute;
left: whatever you like
top: whatever you like
}
Related
Any ideas why my markers aren't clustering? I've tried many different ways and nothing will make them cluster. I realize there might be something wrong with the arguments I'm passing the markerClusterer but I can't find a way to make it work with anything. There's also little to no documentation on markerClusterer.MarkerClusterer (which is required when using unpkg).
function initMap() {
//set map options
var myMapOptions = {
center: {lat: 40.7498024, lng: -73.9774375},
zoom: 12,
}
//fill the html div with a map and pass in map options
var myNewMap = new google.maps.Map(document.getElementById('mymap'), myMapOptions);
//pass in data
myNewMap.data.loadGeoJson('missedConnections.geojson');
//define popup windows
var infowindow = new google.maps.InfoWindow({maxWidth: 750, autopanMargin: 10,});
//create new popup windows on marker click
myNewMap.data.addListener('click', function(event) {
console.log(event);
// set variables
let videourl = event.feature.getProperty('videoURL');
//padding/margin is wonky on mobile vs desktop
let html = '<video style="padding-bottom: 5px; padding-right: 3px;" preload="none" autoplay width=" 90%"><source src="' + videourl + '"></video>';
// show the html variable in the infowindow
infowindow.setContent(html);
infowindow.setPosition(event.latLng);
infowindow.setOptions({pixelOffset: new google.maps.Size(0, -30)});
// move the infowindow up 42 pixels to the top of the default marker icon
infowindow.open(myNewMap);
});
new markerClusterer.MarkerClusterer({myNewMap.data, myNewMap});
}
First, you are using object shorthand incorrectly.
Second, that isn't the interface for the library.
const markerCluster = new MarkerClusterer({ map, markers });
where markers is an array of google.maps.Markers. See MarkerClustererOptions.
Into your html:
<script src="https://unpkg.com/#googlemaps/markerclusterer/dist/index.min.js"></script>
Into your js, code both of these works
var mc = new markerClusterer.MarkerClusterer({ markers, map });
or
new markerClusterer.MarkerClusterer({ markers, map });
I'm trying to get an infobox to open after clicking an overlay(custom HTML marker).
This map shows a typical marker and a customer HTML marker. When I click the typical marker, the infobox opens correctly. When I click the custom HTML marker, the infobox doesn't open with error msg: TypeError: anchor.getPosition is not a function. This relates to the incorrect parameters I'm passing to infobox.open(). It expects a marker, but since I'm clicking an overlay (custom HTML marker), the parameter passed is incorrect.
How can I adjust the infobox.open() function so that it accepts my overlay as a parameter?
<!DOCTYPE html>
<html>
<style>
#map{
height: 600px;
width: 600px;
}
</style>
<body>
<div id="map"></div>
<script src="https://maps.google.com/maps/api/js?sensor=false"></script>
<script src="https://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/src/infobox.js"></script>
<script src="....path/to/custom-html-markers-google-maps.js"></script>
<script>
var infobox = new InfoBox({
disableAutoPan: false,
maxWidth: 300,
pixelOffset: new google.maps.Size(-75, -70),
zIndex: null,
boxStyle: {width: '150px'},
infoBoxClearance: new google.maps.Size(15, 50)
});
function initialize() {
var loc = new google.maps.LatLng(-33.89, 151.26);
var locMarker = new google.maps.LatLng(-33.89, 151.23);
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 12,
center: loc,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
//This works FINE.. It sets the marker and infobox listener
var marker = new google.maps.Marker({
map: map,
position: locMarker,
visible: true
});
google.maps.event.addListener(marker, 'click', function() {
infobox.setContent('<div style="background-color:yellow">This is<br>an infobox.</div>');
infobox.open(map, this);
});
//Overlay from: http://humaan.com/custom-html-markers-google-maps/
var overlay = new CustomMarker(loc, map, {marker_id: '123'});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</body>
</html>
Part of Custom HTML Marker script:
google.maps.event.addDomListener(div, "click", function(event) {
infobox.setContent('<div style="background-color:yellow">Hi there</div>');
infobox.open(map, this); //*******THIS IS THE PROBLEM********
google.maps.event.trigger(self, "click");
});
My problem is infobox.open(map, this); is expecting a marker and I give it the "div". How can I adjust this function so that it accepts my div?
Full script: http://humaan.com/custom-html-markers-google-maps/
To use anything as an anchor for a marker, it needs to expose a latLng position property and an optional anchorPoint property.
from the documentation:
open(map?:Map|StreetViewPanorama, anchor?:MVCObject)
Return Value: None
Opens this InfoWindow on the given map. Optionally, an InfoWindow can be associated with an anchor. In the core API, the only anchor is the Marker class. However, an anchor can be any MVCObject that exposes a LatLng position property and optionally a Point anchorPoint property for calculating the pixelOffset (see InfoWindowOptions). The anchorPoint is the offset from the anchor's position to the tip of the InfoWindow.
I wasn't carrying the correct loc(lat/lng) and map into the function call.
Here is the revised listener:
google.maps.event.addDomListener(div, "click", function(event) {
var map = self.getMap();
var loc = self.latlng;
infobox.setContent('<div style="background-color:yellow">Hi there</div>');
infobox.openRevised(map, this, loc);
google.maps.event.trigger(self, "click");
});
Here is the revised infobox.open() function:
InfoBox.prototype.openRevised = function (map, anchor, loc) {
if (anchor) {
this.position_ = loc;
}
this.setMap(map);
};
My end-goal: Load only map markers within current map viewport and if map is moved, reload map markers within new viewport.
As far as I know, to do this I need the map corner coordinates which I can only load once the map is idle, that way I can pass these coords to my PHP file to query my database and output the XML for the map markers within the corners (I'm trying to reduce the stress on my DB by restricting the query to only the relevant map area). I'm having trouble adding a dummy marker post-initialize (see code below). It's simply not loading the marker, everything else works fine.
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script>
function initialize() {
var map = new google.maps.Map(document.getElementById("googleMap"), {
zoom: 12,
center: new google.maps.LatLng(40.779502, -73.967857)
});
google.maps.event.addListener(map, 'idle', function() {
/*bounds = map.getBounds();
ne = bounds.getNorthEast();
sw = bounds.getSouthWest();
window.top.showBounds();*/
TestMarker();
});
}
function addMarker(location) {
marker = new google.maps.Marker({
position: location,
map: map
});
}
// Testing the addMarker function
function TestMarker() {
CentralPark = new google.maps.LatLng(40.779502, -73.967857);
addMarker(CentralPark);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
You don't need to wait for the idle event. The map bounds are available the first time the 'bounds_changed' event fires.
Wait for the bounds_changed event; whenever the bounds changes (including the first time), then update your markers on the map.
working fiddle
code snippet:
var map;
var bounds;
function initialize() {
map = new google.maps.Map(document.getElementById("googleMap"), {
zoom: 12,
center: new google.maps.LatLng(40.779502, -73.967857)
});
google.maps.event.addListener(map, 'bounds_changed', function() {
bounds = map.getBounds();
ne = bounds.getNorthEast();
sw = bounds.getSouthWest();
document.getElementById('mapBounds').innerHTML = bounds.toUrlValue(6);
TestMarker();
});
}
function addMarker(location) {
marker = new google.maps.Marker({
position: location,
map: map
});
}
// Testing the addMarker function
function TestMarker() {
CentralPark = new google.maps.LatLng(40.779502, -73.967857);
addMarker(CentralPark);
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#googleMap {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="mapBounds"></div>
<div id="googleMap" style="border: 2px solid #3872ac;"></div>
Why don't you add another listener event inside your initialize function:
google.maps.event.addListener(map, 'dragend', function(){
var latlng = new google.maps.LatLng(35, -90);
var marker = new google.maps.Marker({
position: latlng
});
marker.setMap(map)
});
Google Maps Marker adding is very simple thing.I've created an example, for you.In this page there is some basic examples of google maps markers
http://www.w3docs.com/learn-javascript/google-maps-markers.html
I have a working google map via JS with custom styles. I am looking to use this twice on the site, however with a fixed element, the element is set # 0px then transitions to 800px in height. However I need to call the google resize event in order for the map to re-size otherwize it results in a bad UI (clipped map).
Resize Code:
google.maps.event.trigger(map, 'resize');
I have the following code:
function google_map_custom(){
function GoogleMapOptions(){
var markerPosition = new google.maps.LatLng([variable],[variable]),
mapCenter = new google.maps.LatLng([variable],[variable]);
var mapOptions = {
zoom: 15,
scrollwheel: false,
panControl:true,
zoomControl:true,
rotateControl:true,
disableDefaultUI:true,
center: mapCenter,
styles: [
{
"CUSTOM Google JSON": "styles"
},
{}]
};
// ASSOCIATE VARIABLE WITH HTML ID
var mapElement = document.getElementById('google-map');
// Align Settings to DOM Element
var map = new google.maps.Map(mapElement, mapOptions);
// RETINA MARKER (CUSTOM RE-SIZE) - USE VARIABLE BELOW
var image = new google.maps.MarkerImage("[path-to-url]", null, null, null, new google.maps.Size(44,65));
// Tailor Custom Marker (SVG / PNG ACCEPTED) - USE CDN
var marker = new google.maps.Marker({
position: markerPosition,
map: map,
icon:image
});
}
// Trigger map with element id and specific settings above
google.maps.event.addDomListener(window, 'load', GoogleMapOptions);
}
My question is, how do I call the resize event on a click handler? I have this code as an example:
$('[class selector]').click(function(){
$('#google-map.hidden--homepage').toggleClass('[active selector 800px in height]');
// INVOKE FUNCTION
google_map_custom();
});
Just to confirm, transition works, styles work, map loads. I just need to trigger the map when the element is enlarged.
thanks!
COMMENT IMG (this is the styles for the google container:
I'm playing around with Google maps for the first time, so I looked at a nice tutorial over at CSS Tricks: http://css-tricks.com/google-maps-slider/ I like working with jQuery better than pure JS, and this tutorial makes a nice way to click on a place in a list to display the marker in the map.
I liked it that way, but I need to add infowindows to the marker. Which I did, but when I click on a place on the list and the map pans away, the infowindow stays open! I think it's because I need to attach the infowindow.close() to the event of clicking on a "#locations li".
Here's my code, which runs on document.ready:
$(function() {
var chicago = new google.maps.LatLng(41.924832, -87.697456),
pointToMoveTo,
first = true,
curMarker = new google.maps.Marker({}),
$el;
var myOptions = {
zoom: 10,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map($("#map_canvas")[0], myOptions);
$("#locations li").click(function() {
$el = $(this);
if (!$el.hasClass("hover")) {
$("#locations li").removeClass("hover");
$el.addClass("hover");
if (!first) {
// Clear current marker
curMarker.setMap();
// Set zoom back to Chicago level
// map.setZoom(10);
}
// Move (pan) map to new location
function move(){
pointToMoveTo = new google.maps.LatLng($el.attr("data-geo-lat"), $el.attr("data-geo-long"));
map.panTo(pointToMoveTo);
}
move();
// Add new marker
curMarker = new google.maps.Marker({
position: pointToMoveTo,
map: map
});
// Infowindow: contenido
var contentString = '<p>'+$el.find("h3").html()+'</p>';
contentString += 'hola' ;
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50),
content: contentString
});
// On click, zoom map
google.maps.event.addListener(curMarker, 'click', function() {
//map.setZoom(14);
infowindow.open(map,curMarker);
});
It looks like you're creating a new InfoWindow for each marker. Quoting from the Google Maps API Docs:
If you only want one info window to display at a time (as is the behavior on Google Maps), you need only create one info window, which you can reassign to different locations or markers upon map events (such as user clicks).
Therefore, you may simply want to create one InfoWindow object just after you initialize your map, and then handle the click event handler as follows:
google.maps.event.addListener(curMarker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map, curMarker);
});
Then the InfoWindow should automatically close when you click on a new marker without having to call the close() method.