I have this code to show a map using the Virtual Earth API:
<script type="text/javascript">
function GetMap() {
var map = map = new VEMap('myMap');
map.LoadMap(new VELatLong(47.6, -122.33), 10, 'h', false);
}
$(document).ready(function () {
GetMap();
});
</script>
Show Map
<div id="myMap" style="position:relative; width:400px; height:400px; display:none;"></div>
This doesn't work and displays a black box where the map should go. If I remove the display: none; style then it works just fine. But I don't want the map to be visible when the page loads, I want the user to toggle it. Can anyone see anything wrong with my approach?
Maybe the map needs to be on display when it initializes. It happens especially if the map has to measure the dimensions of the container in order to render properly.
Either go as Diodes suggested moving the map off visual area (you could also set visibility to false) or initialize the map when you actually have to show it.
Alternately, you could move it off-screen, with left:-2000px.
Related
When my mouse goes over an image, I want to display google maps for where the image was taken. Where in MapFunction am I going wrong? Are the arguments in div being used incorrectly?
I am a beginner in HTML. I wanted to create a website where an image is displayed but when my mouse is over the image, the location of where that image was taken is displayed (i have the lat and long already in the code). To do this, I use onmouseover and onmouseout. I'm not sure where I went wrong in the functions. I understand that I can use a screenshot of the map for display purposes, but I need to know how to display google maps for future knowledge.
On a side note, why do I need to put in my API key if I wont be using my location? The instructions shown in https://developers.google.com/maps/documentation/javascript/adding-a-google-map say that I need to do this but I'm not sure why the API itself is necessary.
Thanks for your help.
<head>
<style>
#MapAndImg {
width: 600px;
height: 400px;
background-color: lightblue;
background-image: linear-gradient(lightblue, white);
}
</style>
</head>
<body>
<em> May 30 </em><br>
<div onmouseover = "MapFunction()" onmouseout = "ImgFunction()" border = 5 id = "MapAndImg">
<script>
function MapFunction() {
var loc = {lat: 51.12722222, lon: 114.20194444};
var map = new google.maps.Map(document.getElementById('MapAndImg'), {zoom: 4, center: loc});
var marker = new google.maps.Marker({position: loc, map: map});
}
function ImgFunction() {
<img src = "https://www.istockphoto.com/resources/images/HomePage/FourPack/2018_05/Illustrations_499178960.jpg" alt = "editeted.jpg">
document.getElementById('MapAndImg');
}
</script>
<script async defer src = "https://maps.googleapis.com/maps/api/js?key=(INSERT API KEY HERE)&callback=initMap"></script>
</div>
</body>
The map itself isn't showing up when I open it on Firefox and Internet Explorer, even though a similar code found in https://developers.google.com/maps/documentation/javascript/adding-a-google-map does have the map show up.
I have a <google-map> inside a <app-drawer-layout>, and it works fine except the map displays a gray area to the right when the drawer is hidden.
All the discussions I've found about this issue say that the solution is to trigger the resize event of the map, but it doesn't work for me. I even tried adding a delay just to be on the safe side, but still it does nothing.
document.querySelector('app-drawer').addEventListener('app-drawer-transitioned', function(){
window.setTimeout(function(){
console.log( map.clientWidth );
google.maps.event.trigger(map, 'resize');
}, 100);
});
The console output confirms that the map width has indeed changed before triggering the resize event, but the gray area persists. Even if I pan and zoom the map, the gray area is still there (although it becomes wider or narrower depending on the pan). The only thing that seems to correct it is resizing the entire browser window.
This is in Chrome on Mac btw.
Turns out that I was trying to trigger the resize event on the DOM-element instead of the Maps API object. The Maps API object can be obtained via the .map property of the <google-map> DOM-element.
This works for me
<script>
var mapElem = document.querySelector('google-map');
mapElem.addEventListener('api-load', function(e) {
var mapObj = mapElem.map;
document.querySelector('app-drawer').addEventListener('app-drawer-transitioned', function(){
google.maps.event.trigger(mapObj, 'resize');
});
});
</script>
I'm having problems with the google map I'm embedding, I don't understand why on load the map not appears and only appear when I resize the window, I went through different solutions in stackoverflow but they don't work for me.
Here is my js code:
<script>
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 31.554606, lng: 74.357158},
zoom: 14
});
google.maps.event.addListenerOnce(map, 'idle', function() {
google.maps.event.trigger(map, 'resize');
});
}
</script>
my div
<div id="map"></div>
when i load application it appears like
and after re size browser window it appears perfectly like this
kindly tell me how to fix this problem ?
call google.maps.event.trigger(map, 'resize') when your "div id=map" will be visible.
Please see How do I resize a Google Map with JavaScript after it has loaded?
Nothing worked for me. I was using Model box in Bootstrap to load the map. I tried everything for hours. Every time I would load the map I would see a grey box, but as soon as i would resize the browser, it would display the map. Seemed it required resizing of window. So I put all the map functionality into a function called initmap2() and displayed the fresh map inside it. and upon clicking i used
setTimeout( initMap2, 200 );
So as soon as the Modal box would open, it would display the map, and I tried working will 100 milliseconds but I guess it works with 200+ milliseconds so I kept 500ms just to be safe.
I hope this helps
I found this working only after combine two things: setTimeout and google resize.
So, at the end of initMap, I set:
google.maps.event.addListener(map, "idle", function(){
google.maps.event.trigger(map, 'resize');
});
And create a setTimeout for the initMap like this:
$(document).ready(function(){
setTimeout(initMap, 1000);
});
--
Edit
To answer #LucaC.: my initMap is a separate js, that I link into the pages. The solution above is defined in this js (the setTimeout only).
But, after a while, I noticed this problem still happening with mobile devices.
Working around: keep the setTimeout for the initMap and on the page I load the map, I've set up
$(window).load(function(){
setTimeout(function(){
google.maps.event.trigger(map, "resize");
}, 250);
});
So: i) delay anything that break the map; ii) at the end of all, resize the map after page load :)
Nothing worked for me. I was using modal box in bootstrap to load the map. i did following code may it will help you
First i load map in body with display:none like below
<div style="display:none; overflow:hidden; width:100%; height:400px;" id="map"></div>
by initMap method, map will load properly but we used display=none so that map will not display.
For display that map in model i append the div which have id="map" to id="map-modal" which is in the model. like below
$('#modal-id').on('shown.bs.modal', function () {
document.getElementById('map').style.display = "";
var mapNode = map.getDiv();
$('#map-modal').append(mapNode);
});
May it will work.
Resize your map without javascript
step 1: Go to google maps and after searching your location, click on share and
Get the Google Maps Embed
Code
step 2: code will look something like this
<iframe src="/" width="600" height="450" frameborder="0" style="border:0"
allowfullscreen></iframe>
step 3: Add a div tag around the embed code. Use the CSS class map-responsive
<div class="map-responsive">
<iframe src="/" width="600" height="450" frameborder="0" style="border:0"
allowfullscreen></iframe>
</div>
step 4: Add your Google Maps CSS
.map-responsive{
overflow:hidden;
padding-bottom:56.25%;
position:relative;
height:0;
}
.map-responsive iframe{
left:0;
top:0;
height:100%;
width:100%;
position:absolute;
}
this will make your map responsive to any screen size.!!
I have a <div> containing a leaflet map. Upon certain events the height of the <div> will be altered. I'd like for the map to resize to the new dimensions of its surrounding <div> so that the old center is centered in the resized smaller or larger map. I tried using the invalidateSize() function, but it doesn't seem to work at all. How can I resize and center the map after that map-container-resize event?
$mapContainer.on('map-container-resize', function () {
map.invalidateSize(); // doesn't seem to do anything
});
Edit to give more context:
The map container is styled initially as
#map-container {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
transition: height 0.5s ease-in-out;
}
After a user clicks a certain button, another panel shows at the bottom of the page and the map-container's height will be reduced to something less than 100% (say 80%).
Upon click on this button, the map-container-resize event is triggered so that I can make the map resize and center on its old (i.e. before the resizing happened) center. The map itself should then also be resized to 80% of its initial height.
The APi doc for invalidateSize seemed to be what I wanted:
"Checks if the map container size changed and updates the map if so
[...]"
But having a look with the output of the getSize function before and after the call to invalidateSize, nothing is different, the map remains at its old size.
The problem is that the resizing of the #map-container div is done via a css transition. The transition hasn't started yet, let alone ended, when the call to invalidateSize happens so the leaflet map cannot recognize any change of dimensions of its surrounding div.
Triggering the map-container-resize event with a delay solved the problem. This way :
setTimeout(function(){ map.invalidateSize()}, 400);
L.Map.invalidateSize() only informs leaflet map object that its container size has been changed, and therefore is should draw less or more map tiles. It does not actually change any dimensions, e.g. of its containing <div>, and does not move the map. You should do it yourself.
I came across this question today and wanted to provide an updated answer based on 2020 Browser API. This example uses the Browser's ResizeObserver to monitor the size of the div that Leaflet is mounted too. Assuming the following HTML Snippet:
<div id="map" />
With the following JavaScript:
const mapDiv = document.getElementById("map");
const map = L.map(mapDiv).setView([51.505, -0.09], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
const resizeObserver = new ResizeObserver(() => {
map.invalidateSize();
});
resizeObserver.observe(mapDiv);
This should monitor the map div, and call the invalidateSize() method on the Leaflet map when the map div size changes. This approach allows you to handle the resizing "closer" to the map code, rather than trying to rely on window resize events or listening for changes triggered elsewhere in the application.
Obviously the CSS for the map div itself will need to ensure that it resizes in whatever way you want it to. This code snippet will ensure the Leaflet is appropriately updated when that happens.
You can use below code after resize that
map.invalidateSize()
https://github.com/Leaflet/Leaflet/issues/690
the accepted answer is a bit hacky in that it relies on the sleep being longer than the transition.
I have found this to work well:
$("body").on($.support.transition.end, '#main-navbar .nav-collapse', function(event){
console.log("end of the animation");
});
Just call resize window event rather than timing the map to load.
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
window.dispatchEvent(new Event('resize'));
// Triggers a window resize
// Thus your map automatically triggers invalidateSize().
Ran into this problem running VueJS, Leaflet 1.2.0. The resizing didn't appear complete as others mentioned above. My solution within VueJS was to call the nextTick function:
var vm = this
var container = vm.$refs.container
vm.mapStyle.width = `${vm.getElementContentWidth(container)}px`
vm.mapStyle.height = `${vm.getElementContentHeight(container)}px`
vm.$nextTick(() => {
if (vm.map) vm.map.invalidateSize()
if (vm.layerBase) vm.layerBase.redraw()
})
I believe pure javascript would be
I am using amCharts (which uses Raphaƫl behind the scenes) to render some charts as SVG; and have noticed that if the SVG is rendered in an initially-invisible div, the browser does not immediately render the image when the div becomes visible. If I modify the display however, e.g. by resizing the browser or Ctrl-mousewheel zooming, the SVG image is then rendered as expected when the page is redrawn.
The exact method of div visibility switching is via Bootstrap's tabbed navbar.
I admit to not being very experienced with SVG - is this an issue with the browsers' rendering, or amCharts' SVG markup, or am I required to explicitly call some sort of repaint method when I can tell the visibility of an SVG has changed?
Here's a jsFiddle which illustrates the problem; if you switch to Section 2 (in Chrome, Firefox) the chart isn't visible initially. Resizing the display causes it to appear.
I've found the reason for both the initial behaviour and the workaround - and it's all amCharts specific (nothing to do with SVG per se) so I'm rephrasing the title accordingly.
What happens is that when amCharts creates the SVG, it needs to (or at least, decides to) define the width and height in absolute terms. These are based on the size of the target div, obtained via the offsetWidth and offsetHeight properties.
The inactive tab has the display: none property set, and as a result this part of the DOM is not even rendered, so returns zero for both size properties. This ultimately leads to amCharts creating a 0x0 SVG chart when chart.write is called for the hidden div.
Resizing fixes things because each chart registers a listener to the onresize window event, which calls the chart's handleResize method. This forces a recalculation of the width and height based on the div's new (current) dimensions.
So in conclusion I think there are two alternative ways to handle this:
Call chart.write for a chart when and only when its tab becomes visible.
Call each chart's handleResize method when the tabs change.
(The first option avoids the initial hit of rendering an invisible chart, but then does a full redraw every time the tabs are changed. The latter takes a hit up-front but is likely quicker thereafter. For bonus marks, the best solution would be to render each chart exactly once between each resize, the first time it becomes visible, but that's a lot more complex as it would involve interfering with the default event listeners, amongst other things.)
Update: There's further complications with rendering an invisible chart; in particular, I found issues with the height calculations not taking into account the space required by the domain axis and so stretching the chart out of its div. This wasn't fixed by calling handleResize - calling measureMargins beforehand looked like it should work but didn't. (There's probably another method one could call after this to make it work such as resetMargins but at this point it started to feel very flaky...)
As such I don't think it's practical to render a chart for the first time on a non-visible div, so I went with some combination of the bullets above. I listen for when a chart's tab becomes visible for the first time and then call chart.write for the appropriate chart object - and whenever the tabs change, all previously-rendered charts are told to handle the resize.
* Edited *
Here is a updated fiddle. The Canvas will only be rendered once the tab is shown.
I store the chartdiv ids in an array and check whether there are in it or not.
* Edited *
The only solution I found was to show the Graph after the specific tab is shown.
As you see in this jsFiddle.
var tabs = $('.tabbable').tab()
tabs.on('shown', function(e){
id = $(e.target).attr('href');
chartdiv_id = $(id).find('.chartdiv').attr('id');
doChart(chartdiv_id, true);
});
I guess it isn't exactly what you are looking for, but i hope it helps for the moment.
I had the same problem, but my solution it's alternative to display:none, you can use this class in the css
.hidden {
position: absolute !important;
top: -9999px !important;
left: -9999px !important;
}
this dissapear of the screen but visible for the amchart, so the resolution of the chart never lose the size!!!!
I completely agree with Andrzej Doyle.
Issuing handleresize on the chart when clicking on the selected div (tab) works for me on cs-cart with custom tabs (not jquery ones).
The following works while cart beeing globally defined.
function refreshchart(){
chart.handleResize();
};
I also ran into the issue and fixed it by making the initializer a function. Working fiddle.
$("#button").click(function(){
$("#chartdiv").toggle();
makeChart();
});
function makeChart() {
var chart = AmCharts.makeChart("chartdiv", {
//all the stuff
});
}
This Might help you to resolve issue . I have my amchart showing in different tab pan . SVG Component does not allow them to show that div due to resizing issue .
$(window).resize(function() {
setTimeout(function() {
chart.write("chartdiv1");
}, 300);
});
resize again your window while you create your charts ..
Show me charts
<div class="charts_div" style="display:hidden;">
some charts here
</div>
<script>
$(document).on('click', '.show_charts', function(){
$('.charts_div').toggle();
//just redraw all charts available on the page
for(var i = 0; i < AmCharts.charts.length; i++) {
AmCharts.charts[i].validateData();
}
});
</script>
var chart = null;
AmCharts.ready(function () {
chart = AmCharts.makeChart('chart', .....);
});
$(document).ready(function(){
$("#view_chart").click(function(){
chart.validateSize();
});
});
<button type="button" id="view_chart">View Chart</button>
<div style="display:none;" id="chart"></div>
Another work around would be
drawTransactionTypeChart();
setTimeout(function(){hidePieCharts();},1);
Initially set display:inline to div which is chart container, it gets rendered .
Then set display:none using setTimeout() after 1ms.
Hope this helps...
I have two amcharts on different tabs.
A stock chart to be place on #chartdiv and a pie chart to be placed on #chartdivpie.
This is how I solved my problem.
My custom css - to overwrite bootstrap -
#chartdivpie { width: 1138px; height: 500px; }
.tab-content .tab-pane {
position: absolute;
top: -9999px;
left: -9999px;
display: inline;
}
.tab-content .tab-pane.active {
position: inherit !important;
}
JQuery call
$('#myTab a').click(function (e) {
e.preventDefault()
$(this).tab('show');
chart.invalidateSize();
chart.write('chartdiv');
})