So in my Rails app I am building out a region show page with multiple locations. Users are able to insert new locations and map markers need to be dynamically placed based on the latitude and longitude that they enter. In my Region show page I have the following:
<div class="container-fluid">
<div class="row">
<div class="banner" id="region-banner" data-region-name="<%=#region.name.downcase%>">
<script>document.addEventListener('DOMContentLoaded',app.regions);</script>
Then in my region.js file I have the following:
import { tns } from 'tiny-slider/src/tiny-slider.module';
import { mapStyle } from './styles/mapStyle';
app.regions = () => {
function init() {
startGoogleMap();
}
let startGoogleMap = () => {
let map = new google.maps.Map(document.getElementById('region-banner'), {
zoom: 3,
minZoom: 3,
disableDefaultUI: true,
gestureHandling: 'cooperative',
styles: mapStyle
});
var mapElement = document.getElementById('region-banner');
const regionName = mapElement.getAttribute('data-region-name');
let bounds = new google.maps.LatLngBounds();
let promise = $.getJSON('/locations.json');
promise.done(function(data) {
return $.each(data, function() {
return new google.maps.Marker({
position: {
lat: parseFloat(data.lat),
lng: parseFloat(data.lng) },
map: map,
icon: "/marker.png"
});
});
});
console.log(promise);
map.fitBounds(bounds);
};
return init();
};
Then in my controller I have:
def show
#locations = Location.all
respond_to do |format|
format.json { render json: #locations }
format.html
end
end
So no real errors are applying however...nothing appears. The console shows the responseText:“[{“id”: 5, “name”: “Chicago”, “abbreviation”: “CHI”, “lat”: “44.222”, “lng”: “-22.111”}, {“id”: 6, “name”: “Frankfort”, “abbreviation”: “FKT”, “lat”: “41.3232”, “lng”: “-19.5221”} ]”. Which really on this page I should only need/use the first.
Shouldn't it also be applying the markers at this stage since I put in the position?
this is the code responsible for setting your Markers.
I would focus on understanding why promise.done() does not run create the new google.maps.Marker() for each row in your (data) from your response.
Maybe the problem is connected to the /marker.png
promise.done(function(data) {
return $.each(data, function() {
return new google.maps.Marker({
position: {
lat: parseFloat(data.lat),
lng: parseFloat(data.lng) },
map: map,
icon: "/marker.png"
});
});
});
Related
I am using the google-map-react NPM package to create a Google Map and several markers.
The information for the coordinates, infowindow, icon, etc. will come from a JSON file.
I have added onGoogleApiLoaded and yesIWantToUseGoogleMapApiInternals.
This is what my code currently looks like, with the markers being inside this file for the time being
import React, { useEffect } from 'react'
import GoogleMapReact from 'google-map-react'
let mapOptions = {
center: { lat: 39.56939, lng: -40.0000 },
zoom: 3.5,
disableDefaultUI: true,
gestureHandling: 'none',
zoomControl: false,
scaleControl: false,
zoomControlOptions: false,
scrollwheel: false,
panControl: false,
};
function ModelsMap({ data, state }) {
console.log(data.models)
function initMap() {
let markers = [
/.../
];
function Marker(props) {
let marker = new google.maps.marker({
position: props.coords,
content: props.content,
icon: props.icon,
map: map
});
let infoWindow = new google.maps.InfoWindow({
content: props.content
});
Marker.addListener('click', function () {
infoWindow.open(map, marker);
})
}
}
// useEffect(initMap, []); it will only render once
return (
<div style={{height: '100vh', width: '100%' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: "YOUR_API_KEY" }}
defaultCenter={{lat: 39.56939, lng: -40.0000 }}
defaultZoom={3.5}
options={mapOptions}
yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map, maps }) => ModelsMap(map, maps)}
>
</GoogleMapReact>
</div>
);
}
export default ModelsMap;
I have followed the solution listed on This other stack overflow post, but that didn't work either.
Base on the answers on the StackOverflow you provided they uses new maps.Marker() to create a new Google Maps marker. If you want to get the value of your coordinates,icons and different properties of marker from a json data, you need to put this new maps.Marker() to loop through each json data. Below should be the value of your ModelsMap. Don't for get to import your json file.
const ModelsMap = (map, maps) => {
//instantiate array that will hold your Json Data
let dataArray = [];
//push your Json Data in the array
{
data.map((markerJson) => dataArray.push(markerJson));
}
//Loop through the dataArray to create a marker per data using the coordinates in the json
for (let i = 0; i < dataArray.length; i++) {
let marker = new maps.Marker({
position: { lat: dataArray[i].lat, lng: dataArray[i].lng },
map,
label: dataArray[i].id,
});
}
};
Here is a sample code that shows this. Please use your own API key for this to work.
Side Note: I removed the API Key in your question. Please don't share your API keys in public sites in the future.
enable javascript map api from your google cloud console
Anyone know why the map is shown tilted instead of a top view? I am using arcgis js with WMS for the map. Inside the body you will need to put a div:
<div id="viewDiv"></div>
This is my js code:
var map, view, layer;
require([
"esri/tasks/Locator",
"esri/Map",
"esri/views/MapView",
"esri/layers/WMSLayer"
], function (Locator, Map, MapView, WMSLayer) {
layer = new WMSLayer({
url: 'https://geoservices.informatievlaanderen.be/raadpleegdiensten/GRB-basiskaart/wms'
});
var locatorTask = new Locator({
url:
"https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer"
});
map = new Map({
basemap: {
baseLayers: [layer]
}
});
view = new MapView({
map: map,
container: "viewDiv",
constraints: {
rotationEnabled: false
}
});
});
I'm trying to set up an on page load function for dynamic pages (shows) that will only display certain variables that meet the requirements. For example if someone clicks on West Coast the map will only display California, Washington, and Idaho. If they click on Great Plains the map shows Iowa, Nebraska, Kansas. And so on.
Right now I have it set up, in my region.js file:
app.regions = () => {
function init() {
startGoogleMap();
}
let startGoogleMap = () => {
let map = new google.maps.Map(document.getElementById("region-banner"), {
zoom: 7,
// The latitude and longitude to center the map (always required)
disableDefaultUI: true,
gestureHandling: "cooperative",
styles: mapStyle
});
const cali = new google.maps.Marker({
position: new google.maps.LatLng(x, y),
map: map,
icon: '/icon.jpg',
title: 'California',
region: 'West Coast'
});
return init();
};
Then in my regions I actually have a list of regions with the following in the table:
create_table "regions", force: :cascade do |t|
t.string "name"
t.string "url_name"
end
So in a nutshell I need to compare a variable against the region name on page load.
UPDATE:
This is what is currently in my show:
<div class="container-fluid">
<div class="row">
<div class="banner" id="region-banner">
</div>
</div>
</div>
<script>document.addEventListener('DOMContentLoaded', app.regions);</script>
EDIT:
I applied the following in my show > script:
let regionContainer = document.getElementById('region-banner');
regionContainer.dataset.region
Then changed my show to:
<div class="banner" id"region-banner"><%= #region.name %></div>
Nothing happened. No errors though.
One way to achieve this is to use data attributes on the container in which your map is loaded (although you could really use any element).
Assuming you have a variable #region for the current region in your show view, and assuming you're going to load the map in a div with a "map" id, you could do something like this in the markup:
<div id="map" data-region="<%= #region.name %>"></div>
And then you could retrieve that attribute in your JS file with something like this:
var mapContainer = document.getElementById('map');
mapContainer.dataset.region // Would be the result of #region.name
So the fix for future reference I did with both JS and Rails.
In JS
const markers = {
"west/coast": [{
position: [x,y],
title: 'California'
}]};
app.regions = () => {
function init () {
startGoogleMap();
}
let startGoogleMap = () => {
let map = new google.maps.Map(document.getElementById("region-banner"), {
zoom: 3,
minZoom: 3,
disableDefaultUI: true,
gestureHandling: "cooperative",
styles: mapStyle
});
var mapElement = document.getElementById("region-banner");
const regionName = mapElement.getAttribute('data-region-name')
let bounds = new google.maps.LatLngBounds();
markers[regionName].forEach(({ position, ...opts }) => {
const marker = new google.maps.Marker({
...opts,
position: new google.maps.LatLng(...position),
map
});
bounds.extend(marker.position);
});
Then in the show:
<div class="banner" id="region-banner" data-region-name=<%=#region.name.downcase%></div>
I have been trying to use google map with angularJS.
I have learned how to use it through https://angular-ui.github.io/angular-google-maps/#!/.
Everything goes well.
For each marker, I can show InfoWindow which has an element information of myList.
But I have got stuck in InfoWindow with cluster.
When cluster is clicked, I want to show the information list of markers in cluster.
Even I can't show simple InforWindow when clicking the cluster.
Below sources are my code.
Please tell me if it is not enough to solve my problem.
Please tell me what is wrong and how to solve this.
Have a nice day.
* javascript
$scope.map.map = {
center: { latitude: $scope.map.myList[0].lat, longitude: $scope.map.myList[0].lng },
zoom: 17,
events : {
tilesloaded: function (map) {
$scope.$apply(function () {
google.maps.event.addDomListener(window, 'resize', function() {
var lat = $scope.map.myList[$scope.map.markerPosition-1].lat;
var lng = $scope.map.myList[$scope.map.markerPosition-1].lng;
var center = new google.maps.LatLng(lat, lng);
map.setCenter(center);
});
});
}
},
markersEvents: {
click: function(marker, eventName, model) {
model.show = !model.show;
return;
}
},
clusterOptions : { // options of cluster
gridSize: 40,
ignoreHidden: true,
zoomOnClick : false,
averageCenter : true,
styles: [
{
height: 53,
url: "http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/images/m3.png",
width: 53,
textColor : 'white'
}
]
},
clusterEvent: { // when cluster's clicked
click: function(map, markers) {
var contentString = 'ABCD';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, markers);
return;
}
}
};
$scope.map.options = {
streetViewControl : false
};
$scope.map.markers = [];
* html
<ui-gmap-google-map center='map.map.center' zoom="map.map.zoom" options="map.options" events="map.map.events">
<ui-gmap-markers models="map.markers" coords="'self'" icon="a" events="map.map.markersEvents" options="'options'"
doCluster="true" clusterOptions="map.map.clusterOptions" clusterEvents="map.map.clusterEvent">
<ui-gmap-windows show="show">
<div ng-non-bindable>{{id}}</div>
</ui-gmap-windows>
</ui-gmap-markers>
Answer myself.
var infoWindowOptions = {
content: "asdfasdf"
};
var infowindow = new google.maps.InfoWindow(infoWindowOptions);
infowindow.open(map.map_, *marker*);
I have a model Locations with two columns latitude and longitude. I want to find a way where I can get the list of locations and pass them to google maps using Ajax and javascript. So far my code is as follows:
map.js:
function initialize()
{
var map;
var latlng = new google.maps.LatLng(37.09, -95.71);
var options = {
zoom: 5,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true,
disableDoubleClickZoom: true,
noClear: true,
navigationControl: true,
navigationControlOptions: {
position: google.maps.ControlPosition.TOP_RIGHT
}
};
map = new google.maps.Map(document.getElementById('map'), options);
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: 'Click me',
});
}
locations_controller.rb
def show
#location = Location.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #location }
end
end
Page displaying the map:
<div id="map" onload="initialize();">
</div>
SO now I want to find a way to make an AJAX request from map.js so I can get the locations from the Location model and pass it to the marker object so that when a map is loading all the locations pre-existing in the database are passed to marker and those markers appear.
Thank you.
Oh I was able to find my way to get the list of locations. The controller and view are left untouched.
I added the following ajax in map.js which did the work for me.
$.ajax({
type: "GET",
dataType: "json",
url: "/locations",
success: function(data){}
});
Now data can be passed to the marker object in google maps.