I am able to display map on screen and get the current positions of latitude and longitude. However I want to display a marker at the position of those latitude and longitude values. I have tried by adding a listener when map is rendered. Below is the code. But no marker shows up on the screen. Any pointers on how to get the marker displayed at the current position will be really helpful..
<script src="http://maps.googleapis.com/maps/api/js?sensor=true"></script>
<link href="touch/resources/css/sencha-touch.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
Ext.application({
name: 'MapApp',
launch: function() {
var lat,lng;
//get latitude and longititude values
Ext.device.Geolocation.getCurrentPosition({
success: function(position) {
lat = position.coords.latitude;
lng = position.coords.longitude;
alert(lat);
alert(lng);
Ext.Viewport.add( {
xtype:'map',
useCurrentLocation:true,
fullscreen: true,
layout:'fit',
listeners : {
maprender : function() {
alert('map rendered');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat,lng),
title : 'testing',
});
}
}
});
},
failure: function() {
alert('something went wrong!');
}
maprender : function(map, gmap, options) {
alert('map rendered');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat,lng),
title : 'testing',
map: //gmap or map, try both one of them will work
});
}
this map key is importatnt also u need to ensure you sabe markers in a array for future use
Related
I want to see all the features in a graphicsLayer that match an x,y from a mouse. The hitTest() method works for the topmost one:
mapView.on("pointer-move", function(event) { // HANDLE HOVER
let screenPoint={ x: event.x, y: event.y };
mapView.hitTest(screenPoint).then(function(response) {
if (response.results.length) {
DO SOMETHING...
}
});
But, when I'm zoomed out, the points overlay into one. How can I know that there are others and get access to them?
Google Earth used to have a function that automatically displayed them in a circle. It would be great if arcGis has that, but I'm with doing it the hard way.
In the new version of the API, 4.x, what usually was a the GraphicLayer purpose (handling client side features) became part of FeatureLayer or other layers like GeoJSONLayer or CSVLayer.
Now, the recomendation is to use FeatureLayer,
It is generally preferred to construct a FeatureLayer with its source property when working with client-side graphics since the FeatureLayer has more capabilities than the GraphicsLayer, including rendering, querying, and labeling.
ArcGIS JavaScript API - GraphicLayer
In regard to visualization, your could use clustering on FeatureLayer.
Take a look at this example I made for you base on ArcGIS JavaScript Examples - Point clustering.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>FeatureLayer Cluster - 4.15</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.15/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.15/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/Graphic",
"esri/geometry/Point",
"esri/widgets/Legend",
"esri/widgets/Expand"
], function(
Map,
MapView,
FeatureLayer,
Graphic,
Point,
Legend,
Expand
) {
function getRandomNumber(min, ref) {
return Math.random() * ref + min;
}
function getGraphics() {
const graphics = [];
let location = null;
// generate random points features
let oid = 0;
for (let i = 0; i <= getRandomNumber(20, 50); i++) {
location = new Point({
latitude: getRandomNumber(10, 50),
longitude: -getRandomNumber(50, 50)
});
for (let j = 0; j <= getRandomNumber(0, 50); j++) {
graphics.push(
new Graphic({
geometry: location,
attributes: {
OBJECTID: oid,
name: `${i}-${j}`
}
})
);
oid++;
}
}
return graphics;
}
const graphics = getGraphics();
function popupTemplateContent(feature) {
const location = feature.graphic.geometry;
return `lat:${location.latitude.toFixed(2)} lon:${location.longitude.toFixed(2)}`;
}
const clusterConfig = {
type: "cluster",
clusterRadius: "100px",
popupTemplate: {
content: "{cluster_count} features."
}
};
function createLayer() {
return new FeatureLayer({
source: graphics,
objectIdField: "OBJECTID",
fields: [
{
name: "OBJECTID",
type: "oid"
},
{
name: "name",
type: "string"
}
],
featureReduction: clusterConfig,
popupTemplate: {
title: '{name}',
content: popupTemplateContent
},
renderer: {
type: "simple",
field: "mag",
symbol: {
type: "simple-marker",
size: 4,
color: "#fc3232",
outline: {
color: [50, 50, 50]
}
}
}
});
}
const layer = createLayer();
const view = new MapView({
map: new Map({
basemap: "gray-vector"
}),
container: "viewDiv",
zoom: 2,
center: [-75, 35]
});
view
.when()
.then(addLayerToView)
.catch(function(e) {
console.error("Creating FeatureLayer failed", e);
});
function addLayerToView() {
view.map.add(layer);
}
const legend = new Legend({
view: view,
container: "legendDiv"
});
const infoDiv = document.getElementById("infoDiv");
view.ui.add(
new Expand({
view: view,
content: infoDiv,
expandIconClass: "esri-icon-layer-list",
expanded: true
}),
"top-left"
);
const toggleButton = document.getElementById("cluster");
toggleButton.addEventListener("click", function() {
const fr = layer.featureReduction;
layer.featureReduction =
fr && fr.type === "cluster" ? null : clusterConfig;
toggleButton.innerText =
toggleButton.innerText === "Enable Clustering"
? "Disable Clustering"
: "Enable Clustering";
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="infoDiv" class="esri-widget">
<button id="cluster" class="esri-button">Disable Clustering</button>
<div id="legendDiv"></div>
</div>
</body>
</html>
In the example, when you select if clustering is on it will show how many features there are, and if clustering is off you will get all features.
I am using webamp to show the map created in ArcGIS (Javascript API in PHP website). In the map, a popup also appears when clicking on the layer's points. Recently I have updated the version 4.14 from 4.13. After updating it, the popup is not working properly. I have a custom popup template. After research in the documentation, I came to know there required a return function to show the custom div on the popup. The below code I have added to show my custom popups.
var template = { content: function(){ var div = document.createElement("div"); div.className = "myClass"; div.innerHTML = "<span>My custom content!</span>"; return div; } }
layers[layerIndex].popupTemplate = template;
Now the popup appears fine. But I have to show the field values on the popup. I have used the required field attributes in double brackets eg: {Name}. But in the latest version, the field values are not appearing when I used the same.
The code I have used in version 4.13 and it was working,
popupTemplate = {
title: "{Name}",
content: '<div id="popup_address">{Address}</div><div class="right"><div href="#" id="popupRight" class="toggle"><p onClick="openPopupDetails({FACILITYID})">+</p></div></div>' };
layers[layerIndex].popupTemplate = popupTemplate;
Please help me to fix this issue.
Thanks.
The complete code for the Webmap and custom popup
map.js
// The map classes and includ1a65d527bfd04cc180c87edf0908907bes
require([
"esri/views/MapView",
"esri/WebMap",
"esri/widgets/Search",
"esri/widgets/Zoom",
"esri/widgets/Locate"
], function(MapView, WebMap, Search, Zoom, Locate) {
var webmap = new WebMap({
portalItem: {
id: "d1ca798d8c7d4afab8983d911df8326b"
}
});
var view = new MapView({
map: webmap,
container: "map",
center: [-95.9406, 41.26],
zoom: 16,
maxZoom: 21,
minZoom: 13,
basemap: "topo",
ui: {
components: ["attribution"]
}
});
webmap
.load()
.then(function() {
return webmap.basemap.load();
})
.then(function() {
let allLayers = webmap.allLayers;
console.log(allLayers);
var promises = allLayers.map(function(layer) {
return layer.load();
});
return Promise.all(promises.toArray());
})
.then(function(layers) {
// Position of the popup in relation to the selected feature.
view.popup.alignment = "top-center";
// To disable the collapse functionality
view.popup.collapseEnabled = false;
// A spinner appear at the pointer
view.popup.spinnerEnabled = false;
// To disable the dock (The popup will be appear in bottom or any corner of the window)
view.popup.dockEnabled = false;
// Disable the pagination
view.popup.featureNavigationEnabled = false;
// Popup template details, Keep only name and address in the popup and avoid all other details
view.popup.viewModel.actions.getItemAt(0).visible = false;
// view.on("click", function(event) {
// keep a delay to align the popup and the pointer together positioned to the map center
// Add animation only if the browser not IE
// });
layers.forEach(function(popupLayers, layerIndex) {
console.log(popupLayers);
var template = {
title: "{Name}",
content: function() {
var div = document.createElement("div");
div.className = "myClass";
div.innerHTML = "<span>{Address}</span>";
return div;
}
};
layers[layerIndex].popupTemplate = template;
// popupTemplate = {
// title: "{Name}",
// content:
// '<div id="popup_address">{Address}</div><div class="right"><div href="#" id="popupRight" class="toggle"><p onClick="openPopupDetails({FACILITYID})">+</p></div></div>'
// };
// layers[layerIndex].popupTemplate = popupTemplate;
});
// To close the popup when hit on esc button
document.onkeyup = function(evt) {
var key = evt.keyCode;
if (key == 27) {
view.popup.close();
}
};
})
.catch(function(error) {
// console.log(error);
});
});
Index.php
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>Load a basic WebMap - 4.14</title>
<style>
html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.14/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.14/"></script>
<script src="map.js"></script>
</head>
<body>
<div id="map"></div>
</body>
</html>
I have modified the code,
for (let i = 2; i < layers.length; i++) {
var template = {
title: "{Name}",
content: function() {
var div = document.createElement("div");
div.innerHTML =
'<div id="popup_address">{Address}</div><div class="right"><div href="#" id="popupRight" class="toggle"><p onClick="openPopupDetails({FACILITYID})">+</p></div></div>';
return div;
}
};
layers[i].popupTemplate = template;
console.log(layer[i]);
}
When I apply custom div, the {Address} part is not rendering. It appears like {Address} itself.
I think you are a bit confuse, you still can use a string, or you can use a function for the content of the popup template. So if you want to use a function, you can use something like this,
popupTemplate = {
title: "{Name}",
content: popupContentChange
}
layers[layerIndex].popupTemplate = template;
function popupContentChange(feature) {
let div = document.createElement("div");
div.className = "myClass";
div.innerHTML = "<span>"+feature.graphic.attributes.Address+"</span>";
return div;
}
There are several examples in the API documentation, take a look there. Just to reference one, ArcGIS JavaScript API Examples - Intro to Popups
Here an example I made for you taking your code as base adding some fixes to display what you want.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>Sketch Feature Coords</title>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.14/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.14/"></script>
<style>
html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
require([
"esri/views/MapView",
"esri/WebMap",
"esri/widgets/Search",
"esri/widgets/Zoom",
"esri/widgets/Locate"
], function(MapView, WebMap, Search, Zoom, Locate) {
var webmap = new WebMap({
portalItem: {
id: "d1ca798d8c7d4afab8983d911df8326b"
}
});
var view = new MapView({
map: webmap,
container: "map",
center: [-95.9406, 41.26],
zoom: 16,
maxZoom: 21,
minZoom: 13,
basemap: "topo",
ui: {
components: ["attribution"]
}
});
webmap
.load()
.then(function() {
return webmap.basemap.load();
})
.then(function() {
let allLayers = webmap.allLayers;
console.log(allLayers);
var promises = allLayers.map(function(layer) {
return layer.load();
});
return Promise.all(promises.toArray());
})
.then(function(layers) {
// Position of the popup in relation to the selected feature.
view.popup.alignment = "top-center";
// To disable the collapse functionality
view.popup.collapseEnabled = false;
// A spinner appear at the pointer
view.popup.spinnerEnabled = false;
// To disable the dock (The popup will be appear in bottom or any corner of the window)
view.popup.dockEnabled = false;
// Disable the pagination
view.popup.featureNavigationEnabled = false;
// Popup template details, Keep only name and address in the popup and avoid all other details
view.popup.viewModel.actions.getItemAt(0).visible = false;
// it is only going to work on the last two layers
// those are the one that have fields: Name and Address
for (let i = 2; i < layers.length; i++) {
var template = {
title: "{Name}",
content: "<span>Address: {Address}</span>"
};
layers[i].popupTemplate = template;
console.log(layer[i]);
}
// To close the popup when hit on esc button
document.onkeyup = function(evt) {
var key = evt.keyCode;
if (key == 27) {
view.popup.close();
}
};
})
.catch(function(error) {
console.log(error);
});
});
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
If you want to use a function as content, you have to set the outFields parameter to include the fields you want to use in the function. The selected feature is pass as a parameter to the function, and inside you use feature.graphic.attributes to access the attributes. This should work,
var template = {
title: "{Name}",
// content: "<span>Address: {Address}</span>"
content: function(feature) {
console.log(feature);
var div = document.createElement("div");
div.className = "myClass";
div.innerHTML = "<span>Address:"+feature.graphic.attributes.Address+"</span>";
return div;
},
outFields: ["Name", "Address"]
};
featureNavigationEnabled is deprecated as of version 4.15. Use Popup.visibleElements.featureNavigation instead.
https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Popup.html#featureNavigationEnabled
how can I do 5 photos instead of 3, how to change their size, how to do that they will be change automatically becouse now I have to press play to start?
html:
<script>
$(function () {
// Unstyled Example
$.monte('#example1');
// Styled Buttons Example
// (see the CSS in the above style block)
$.monte('#example2', {auto:false});
// Callback Example
// Format and append the HTML:
$('#example3 > img').each(function(){
$(this)
.wrap('<div style="position:relative"/>')
.parent()
.append('<div><p>' + $(this).attr('alt') + '</p></div>')
.append('<img src="frame.png" alt="" class="frame"/>');
});
// Hide the text on all but the center slide:
$('#example3 div div').css({opacity: 0}).eq(0).css({opacity: 0.8});
// Using the callbacks to reveal and hide the text:
$.monte('#example3', {
auto:false,
callbackIn: function () {
$(this[0]).find('div').animate({opacity: 0.8}, 450);
},
callbackAway: function () {
$(this[0]).find('div').animate({opacity: 0}, 450);
}
});
});
</script>
Here is link to the source where I found it [https://github.com/paizai/monte][1]
Do you have any idea how to move the marker with the coordinates or URL? now when I click on 'Google' down on the map Photo the marker disappears.
I have an example here:
var map;
function initialize() {
var myLatlng = new google.maps.LatLng(48.8164526,-4.140963);
var mapOptions = {
zoom: 15,
center: myLatlng
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Compacc Complete Accountancy'
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html, body, #map-canvas {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false" type="text/javascript"></script>
`
How can I show the marker on "The original Google map"?
I need to allow travelers to use google maps to plot a route, and then query my database of points of interest (let's say, McDonald's locations) and then show all of these locations that are within a mile or two of the route they will be taking. The question is, how do I efficiently take the "driving directions" information that comes back from google (essentially an array of lat/long pairs), and turn that into an sql query to get locations that fall within a certain distance from the route?
It does not have to be super precise, and "as the bird flies" distances from the routes are just fine. I'm most concerned about it being reasonably efficient.
In the database, things are set up pretty basically with each entry having a latitude and longitude, but I can change the database schema as needed.
As an example, this site does what I want to do (if you give a starting point and ending point, it will show chevron stations that are near the highway you will be taking):
http://www.chevron.com/products/stations/stationfinder/planyourroute.aspx
(source: karmatics.com)
Check this out
http://google-maps-utility-library-v3.googlecode.com/svn/tags/routeboxer/1.0/examples/routeboxer-v3.html
Here's the documentation: http://google-maps-utility-library-v3.googlecode.com/svn/tags/routeboxer/1.0/docs/examples.html
You could get the box coordinates from RouteBoxer and send that to a serverside script for processing
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Polygon arrays</title>
<style>
#map {
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 19.2570, lng: 72.8712},
zoom: 10,
});
var directionService = new google.maps.DirectionsService();
var directionsRenderer = new google.maps.DirectionsRenderer({ map: map });
var request = {
origin: "<?php echo $source;?>",
destination: "<?php echo $destination;?>",
travelMode: google.maps.DirectionsTravelMode.DRIVING
}
directionService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
var path = result.routes[0].overview_path;
var poly = new google.maps.Polyline({
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 3,
map: map,
});
poly.setPath(path);
var myTollLocations = [
<?php
isset($hello); //$hello is array which comes from database
foreach ($hello as $key => $value) {
?>
new google.maps.LatLng(<?php echo $hello[$key]->latitude;?>, <?php echo $hello[$key]->longitude;?>),
<?php
}
?>
];
for (var i = 0; i < myTollLocations.length ; i++) {
if (google.maps.geometry.poly.isLocationOnEdge(myTollLocations[i], poly,0.005)) {
console.log("found");
}else{
console.log("Not Found!");
}
};
<?php
$markersLocation = array($source, $destination);
foreach ($markersLocation as $key => $values) {
?>
//Source Marker( convert address to LatLng for marker)
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': '<?php echo $markersLocation[$key]?>'}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
}
console.log(latitude);
console.log(longitude);
var myLatLng = {lat: latitude, lng: longitude};
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: 'source',
icon: 'http://innowrap.com/clients/digitoll/ic_red_marker.png'
});
});
<?php
}
?>
} else {
alert("Directions query failed: " + status);
}
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=ADD YOUR API KEY&libraries=geometry&callback=initMap"
async defer></script>
</body>
</html>