html2canvas on esri Map - layers moves - html

I am trying to create a function in the Angular system which will produce an image of the map using html2canvas
The following is the current function:
window.emapComponent.service.getMap('mapApi').then((map) => {
html2canvas(document.getElementById("mapApi"), { useCORS: true }).then(function (canvas) {
canvas.screenshotDataURI = canvas.toDataURL("image/jpg", 0.5);
canvas.toBlob(function (blob) {
saveAs(blob, oRequest.fileName)
});
});
})
What happens is that in the system itself, as soon as I drag the map with the mouse, the photo comes out weird (file attached)-
I noticed in the elements of html that although I see the objects of the layers adjusted to the map, in practice the div itself is dragged from place to place and this is what I get in the picture
I would be happy to help with this

Related

Vue 3 google map circle is not being removed from the map

Vue 3 google map circle is not being removed from the map
I am currently migrating from Vue 2 to Vue 3.
In Vue 2 I could remove circles,
but in Vue 3 I run into the problem that the circles first disappear when removed.
But when zoom-in and zoom-out they reappear.
I do use the .setMap(null) method for removing the circles.
I use the circles to show a geofence for a POI (point of interest) and
This geofence also has a marker in the centre and I can remove the marker without any problems.
Has anyone else encountered the same problem?
Is this a problem people also run into in other frameworks?
How I create the map circles and markers
public LoadPoiMarkersAgain (
googleMapLoader: IGoogleMapLoader
): HTMLMapMarker[] {
const markers: HTMLMapMarker[] = []
for (let i = 0; i < googleMapLoader.mapPoiData.length; i++) {
const marker = createHTMLMapMarker({
latlng: new google.maps.LatLng(
{
lat: googleMapLoader.mapPoiData[i].latitude,
lng: googleMapLoader.mapPoiData[i].longitude
},
null,
true
),
map: googleMapLoader.map,
data: googleMapLoader.mapPoiData[i],
html: this.CreatePoiMarkerHTML(
googleMapLoader,
googleMapLoader.mapPoiData[i]
)
})
const markerCircle = new google.maps.Circle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: googleMapLoader.map,
center: new google.maps.LatLng(
{
lat: googleMapLoader.mapPoiData[i].latitude,
lng: googleMapLoader.mapPoiData[i].longitude
},
null,
true
),
radius: googleMapLoader.mapPoiData[i].radius
})
this.AddClickListenerToPoiMarker(marker, map)
markers.push(marker)
markerCircle.set('poiId', googleMapLoader.mapPoiData[i].poiId)
googleMapLoader.mapCircles.push(markerCircle)
}
return markers
}
How I remove the circles
public RemoveMapMarkersData (
googleMapLoader: IGoogleMapLoader
): void {
if (googleMapLoader.mapCircles.length > 0) {
googleMapLoader.mapCircles.forEach(
(element: google.maps.Circle) => {
element.setMap(null)
}
)
googleMapLoader.mapCircles = []
}
// Some more code to remove markers
}
What i have tried
attempt 1
I tried using
element.setVisible(false)
This does not work either.
attempt 2
I tried changing the order for when the circle is removed versus the marker.
This does not work either.
attempt 3
I also tried removing the circle
Immediately after, I added them to the map.
That does seem to work.
public LoadPoiMarkersAgain (
googleMapLoader: IGoogleMapLoader
): HTMLMapMarker[] {
// previous code
googleMapLoader.mapCircles.forEach((circle: google.maps.Circle) => {
circle.setMap(null)
})
// previous code
}
Could it be that Vue 3,
Is not passing the references correctly to my method?
Package
enter link description here
Google documentation
Google docs remove circle
Google docs remove marker
Extra
I have a gif that demonstrates the problem.
When I drag the map it should remove the circle.
But when zooming in and out, the circle reappears.
https://i.gyazo.com/b7310cc4d748da36e026104aff6cb2fe.gif
I have also created two sandboxes to demonstrate the problem:
(When you move your mouse out of the map, the circles will be removed)
Vue 2
Vue 2 + google maps
Vue 3
Vue 3 + google maps
I believe I encountered the same issue whilst migrating from Vue 2 to Vue 3, where markers were successfully being removed upon setVisible(false) but were then reappearing upon zoom.
Seeing console errors relating to Proxy led me to believe that the cause of the issue was due to the differences in the reactivity systems of Vue 2 and Vue 3 (helpful article on Vue 3 reactivity).
For me the fix was to use markRaw() when creating the map, which essentially returns the Map Object itself without converting to a proxy.
<script>
import { markRaw } from 'vue'
export default {
methods: {
initMap () {
map = markRaw(new google.maps.Map(document.getElementById("map"), {...}))
}
}
}
</script>
Sadly enough I could not fix the problem in proper way,
but I have a place holder solution for now.
My place holder solution is to remove the map when removing the circles and markers. After removing the map I render / reinitialise the map again.
Vue 3 - remove map when removing circles
If I can remove the circles and markers as intended by google,
Then I will post an update on this again.

How do can I load model and change materials before showing it in the Forge Viewer

I want to be able to show a model in the forge viewer but before the model shows I need to change the materials from its defaults. Currently I register the Autodesk.Viewing.GEOMETRY_LOADED_EVENT and when I receive the event I hide the model, change the materials and then show the model. This works except that the default model displays in the viewer for a second or two before I can hide it. How can I prevent that from happening?
After initializing the viewer here is code that loads the document. If I try and hide the model as indicated in the commented code below the viewer returns this error. I have to wait for the geometry loaded event before I can hide it.
wgs.js?v=v3.3:17876 Uncaught TypeError: Cannot read property 'getGeometryList' of undefined
at RenderScene.getGeometryList (wgs.js?v=v3.3:17876)
at Viewer3DImpl.onLoadComplete (viewer3D.js?v=v3.3:32002)
Here is the code I'm, running:
Autodesk.Viewing.Document.load(
documentId, (doc) => {
var geometryItems = Autodesk.Viewing.Document.getSubItemsWithProperties(doc.getRootItem(), { 'type': 'geometry' }, true);
if (geometryItems.length > 0) {
viewer.load(doc.getViewablePath(geometryItems[0]), null, (model) => {
// Document loaded
// Can't hide model here, viewer returns an error because geometry
// is not loaded
//viewer.hideModel(model.id);
resolve(model.id);
}); // show 1st view on this document...
}
},
function (errorMsg) { // onErrorCallback
console.log('Load Document returned error message: ' + errorMsg);
}
)
I would simply show a pre-canned jpg image preview in place of the forge canvas.
ie.
1. Hide the forge canvas with style 'display:none'
2. Show your preview-jpg in place of the forge canvas
3. wait for TEXTURES_LOADED_EVENT event, like this...
https://github.com/wallabyway/forge-pdf-report/blob/6babb6d7332b6cdb983f57e7d140ff59a5136705/docs/index.html#L44
Hide the forge canvas with style 'display:block'
Hide your preview-jpg.

framework7 cordova-plugin-googlemaps v2 z-index issue

I'm trying to use https://github.com/mapsplugin/cordova-plugin-googlemaps in framework7 project
but I'm facing a problem
as i navigate to the map page The image is loaded but wasn't displayed
I think the issue is z-index
I tried that solution
https://github.com/mapsplugin/cordova-plugin-googlemaps/issues/2028
but doesn't work
this is the page before map page
the red div is the place where image should display
after functions run i see that instead of map
I use this code to navigate to the map page
success: function (response) {
var responseObj = JSON.parse(response)
console.log(responseObj);
this.$root.navigate("/theMapPage/")
}
I found the solution
as I posted in comment that the plugin make the map behind the application
so I hide all pages and show the current page only
map.one(plugin.google.maps.event.MAP_READY, function () {
$$('.page').hide()
$$('.page.page-current').show()
map.clear();
map.getMyLocation(onSuccess, onError);
});
at end just show all pages again
pageAfterOut: function () {
// page has left the view
$$('.page').show()
}

Cordova Admob causing google map rendering "grey" screen in Ionic tabs

Running ionic tabs. My maps works fine until I click to another tab and then click back to the map. When returning to the map tab, most of the map is greyed out with a little bit of the map still appearing in the upper left corner. If I grab the visible section of the map and drag into the center view I see the visible maps is about 2/3rd of the screen - but the moment I let go the visible part shoots back up to upper left corner - and now all the previously greyed out section is just a blank white.
In addition, if I simply rotate my device from portrait to landscape - the map completely redraws itself correctly. And then from landscape back to portrait mode and the full maps is showing again.
For the life of me though, I can't get the 'grey' out from happening.
In my apps.js:
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
globalGPS() ;
});
})
.config(function($stateProvider,$urlRouterProvider) {
'$compileProvider',
function( $compileProvider )
{
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?||tel):/);
// Angular before v1.2 uses $compileProvider.urlSanitizationWhitelist(...)
}
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html",
controller: 'TabsCtrl'
})
// Each tab has its own nav history stack:
.state('tab.map', {
url: '/map',
views: {
'tab-map': {
templateUrl: 'templates/tab-map.html',
controller: 'MapCtrl'
}
}
})
The gps functions take place outside of the state/controllers loaded from a standard javascript file, and when all the gps that same external function sets the map as a global var:
setMap = new google.maps.Map(document.getElementById("mapBody"), myOptions);
In my controller is defined:
.controller('MapCtrl', function($scope,$rootScope,constants) {
// runs this code on EVERY return to map tab
$scope.$on('$ionicView.beforeEnter', function(){
if (setMap) {
google.maps.event.addListener(setMap, "idle", function(){
google.maps.event.trigger(setMap, "resize");
}) ;
// $scope.refreshMap() ; // see note below
}
});
$scope.refreshMap = function() {
setTimeout(function () {
$scope.refreshMap_();
}, 1);
};
$scope.refreshMap_ = function() {
var div = document.getElementById("mapBody");
reattachMap(setMap,div);
};
reattachMap() is an external function:
function reattachMap(map,div) {
if (!isDom(div)) {
return map;
} else {
map.set("div", div);
while(div.parentNode) {
div.style.backgroundColor = 'rgba(0,0,0,0)';
div = div.parentNode;
}
return map;
}
}
In place of the google.maps.event.trigger(setMap, "resize"), I tried using reattaching the map div thinking it had been removed from the DOM. Neither method works or even indicates I am onto the correct fix. In my div's that hold the maps I even hard set width/heigh css values as I had read that fixed some ppl's issues (whereas width/height percentages was causing the problem):
<div id="mapWrapper" style="position:absolute;width:100%;height:100%">
<div id="mapBody" data-tap-disabled="false"></div>
</div>
</div>
and
#mapBody {
border:2px solid #4e8cf9;
text-align:center;
height:700px;
width:400px;*/
flex: 1;
}
Well, I solved the issue. Turns out when moving away from the map tab to another tab, those other tabs are loading ads by AdMob. AdMob ads are not a part of the main DOM, they are a sub-view and thus they are persistent. If you navigate to another tab, the ad stays in the same place on the new tab. When navigating back to the map tab, the ad follows and somehow interferes with google maps ability to properly display itself.
In my app, the first default view is the map tab which doesn't show ads, so no map issues until user returns to the map tab (...and the persistent AdMob ad followed)
Sooo...i now used the above function to remove the ad from the map view completely.
.controller('MapCtrl', function($scope,$rootScope,constants) {
$scope.$on('$ionicView.beforeEnter', function(){
// this function will run EVERY time user goes back to this tab
if (setMap) { // only attempt to remove ad if 'map' is defined
removeAd() ; // global external function
});

Keep a Google Maps v3 Map hidden, show when needed

Is there a way of preventing a Google Maps (JS, v3) map being displayed from the get-go? I'm doing some pre-processing and would like to show my 'Loading' spinner until everything is good to go (more eloquently put, hide the map -- e.g. the container div – until all pre-processing is complete – at which point, show the map).
Hooking up the map's idle event doesn't help that much, since the map is already displayed when this event hits.
I know that the container div gets inline-styled by GMaps after loading, my first idea was to clear out the style attribute (whilst listening to the idle event), but it would be interesting to see if there is a way of creating the map and not displaying it until all pre-processing is done.
Maybe by using an argument to the new google.maps.Map constructor, or a MapOption ?
Any thoughts on this?
Thank you in advance!
Also remember to call:
google.maps.event.trigger(map, 'resize');
if you have changed the size of the <div>. A display:none <div> has no size.
Or you could just hide it like with css visablility or css opacity.
$("#GoogleMap").css({ opacity: 0, zoom: 0 });
initialize();
google.maps.event.addListener(map,"idle", function(){
$('#Loader').hide();
$("#GoogleMap").css({ opacity: 1, zoom: 1 });
});
This works for me. I'm using the JQuery library.
$(document).ready(function(){
$('#Checkbox').click(function(){
$('#googleMapDiv').toggle();
initialize(); // initialize the map
});
});
another way to show the hidden map when map is first time rendering the <div> is to set style: visibility.
When firstly hidden, use visibility = hidden; to show use visibility = visible
the reason is: visibility:hidden means that the contents of the element will be invisible, but the element stays in its original position and size.
this works fine for me, I use jquery tabs
setTimeout(function() {
google.maps.event.trigger(map, "resize");
map.setCenter(new google.maps.LatLng(default_lat, default_lng));
map.setZoom(default_map_zoom);
}, 2000);
om this link https://code.google.com/p/gmaps-api-issues/issues/detail?id=1448
This will work
google.maps.event.addListener(map, "idle", function ()
{
google.maps.event.trigger(map, 'resize');
});
better way:
gmap.redraw = function() {
gmOnLoad = true;
if(gmOnLoad) {
google.maps.event.trigger(gmap, "resize");
gmap.setCenter(gmlatlng);
gmOnLoad = false;
}
}
and in show click event:
$("#goo").click(function() {
if ($("#map_canvas").css("display") == "none") {
$("#YMapsID").toggle();
$("#map_canvas").toggle();
if (gmap != undefined) {
gmap.redraw();
}
}
});
depending on what you are doing another posibility could be to have multiple bools you set to true when each process is done.
For example:
if you have a geocode service running which you want to wait for, you could have a var called
GeoState
and in the result part of the geocoder set GeoState to true,
then have a timed function check if all the services have returned true, when they have, make the map visible.