initializing 'marker-animate-unobtrusive' in Vue fails - javascript

I am trying to use marker-animate-unobtrusive but I keep getting this error:
I found another post on SO that talked about requiring the file after google has loaded but I do not know how to do that. in my component I have this:
import SlidingMarker from 'marker-animate-unobtrusive'
In my mounted method I have this:
SlidingMarker.initializeGlobally()
Any help is greatly appreciated

This is expected error since SlidingMarker extends google.maps.Marker class, GoogleMaps JavaScript API library needs to be loaded first, one option would to add a reference via index.html file:
<script src="https://maps.googleapis.com/maps/api/js?key=--KEY-GOES-HERE--"></script>
Another option would to utilize async JavaScript loader, e.g. scriptjs. The example for loading GoogleMaps JavaScript API and marker-animate-unobtrusive module could look like this:
created: function(){
get("https://maps.googleapis.com/maps/api/js?key=", () => {
const SlidingMarker = require('marker-animate-unobtrusive')
SlidingMarker.initializeGlobally()
const map = new google.maps.Map(document.getElementById('map'), this.mapOptions);
const marker = new SlidingMarker({
position: this.mapOptions.center,
map: map,
title: 'Im sliding marker'
});
});
}
Here is a demo for your reference
Update
With vue-google-maps library marker-animate-unobtrusive plugin could be integrated like this:
<template>
<div>
<GmapMap :center="center" :zoom="zoom" ref="mapRef"></GmapMap>
</div>
</template>
<script>
/* global google */
export default {
data() {
return {
zoom: 12,
center: { lat: 51.5287718, lng: -0.2416804 },
};
},
mounted: function() {
this.$refs.mapRef.$mapPromise.then(() => {
this.initSlidingMarker(this.$refs.mapRef.$mapObject)
})
},
methods: {
initSlidingMarker(map){
const SlidingMarker = require('marker-animate-unobtrusive')
SlidingMarker.initializeGlobally()
const marker = new SlidingMarker({
position: map.getCenter(),
map: map,
title: 'Im sliding marker'
});
google.maps.event.addListener(map, 'click', (event) => {
marker.setDuration(1000);
marker.setEasing('linear');
marker.setPosition(event.latLng);
});
}
}
}
</script>
<style>
.vue-map-container {
height: 640px;
}
</style>

Install the package google from npm this should fix it.

Related

Access Variables Created During onMount in Svelte

I'm working my first Svelte app which includes an embedded Google Map.
Setup Google Maps With Svelte 3 provided a good starting point for creating a component which asynchronously loads a Google Map. However, I can't figure out how to access the map object outside the initial onMount call, and without access to that object I can't add in functionality I want (for example, re-centering the map based on a button the user clicks).
main.js
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
ready: false,
}
});
window.initMap = function ready() {
app.$set({ ready: true });
}
export default app;
App.svelte
<script>
import Map from './Map.svelte';
export let ready;
</script>
<svelte:head>
<script defer async src="https://maps.googleapis.com/maps/api/js?key={}&callback=initMap"></script>
</svelte:head>
{ #if ready }
<Map></Map>
{ /if }
Map.svelte
<script>
// Imports
import { onMount } from 'svelte';
// Globals
let map;
let container;
// Load the map async
onMount(async () => {
map = new google.maps.Map(container, {
zoom: 6,
center: { lat: 0, lng: 0 },
});
});
// This function has no access to the `map` variable created above!!
function recenterMap() {
map.setCenter({lat: 1, lng: 1});
}
</script>
<div class="full-screen" bind:this={container}></div>
<button on:click="{recenterMap}"></button>
Running the above gives an error for trying to invoke the setCenter call on an object that does not exist. I've searched for how other frameworks (React, Vue) might handle this, but the solutions are specific to the frameworks and are not applicable here.
Any help would be greatly appreciated!

Error: Module build failed (from ./node_modules/babel-loader/lib/index.js): SyntaxError:

I am tring to use the Google Map Javascript API into my VueJs project WITHOUT using this package https://www.npmjs.com/package/vue2-google-maps (because it's too limited as I see it).
So here what I have done, after having register my Vue component in app.js:
require('./bootstrap');
window.Vue = require('vue');
const app = new Vue({
el: '#app',
});
Vue.component(
'map-component',
require('./components/MapComponent.vue').default
);
In MapComponent.vue
<template>
<div id="map"></div>
</template>
<script>
export default {
data: function() {
return {
}
},
created() {
let googleApi = document.createElement('script');
googleApi.setAttribute('src', 'https://maps.googleapis.com/maps/api/js?key=AIzaSyA.......S-3SvLw_-twW72Zg&callback='+this.initMap+'');
document.head.appendChild(googleApi);
},
mounted() {
initMap: function() {
var map;
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8
});
}
},
}
</script>
I also tried to switch created() with mounted(), but it shows the same error
The result without error should show a Google map on the page.
Thanks for your help
Aymeric
Try this in Created this.initMap() = function() { ... }
Your code will not work because you are trying to access a variable that is not initialized yet. In Vue First created method is executed then mounted method.
More info here: https://v2.vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks

Repeat function failed in Angular

For my Angular Project, I generated a geolocation component and want to repeat a function findMe() to show the current location.
Part of code in the component.ts is given as below.
...
export class GeolocationComponent implements OnInit{
#ViewChild('gmap') gmapElement: any;
map: google.maps.Map;
isTracking = false;
marker: google.maps.Marker;
constructor(public globalvar: GlobalvarService) { }
ngOnInit() {
var mapProp = {
center: new google.maps.LatLng(-27.542211, 153.1226333),
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.map = new google.maps.Map(this.gmapElement.nativeElement, mapProp);
setInterval(this.findMe(), 3000);
}
findMe() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
this.showPosition(position);
console.log("find me");
});
} else {
alert("Geolocation is not supported by this browser.");
}
}
showPosition(position) {
this.globalvar.latitude = position.coords.latitude;
this.globalvar.longitude = position.coords.longitude;
let location = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
this.map.panTo(location);
if (!this.marker) {
this.marker = new google.maps.Marker({
position: location,
map: this.map,
title: 'Got you!'
});
}
else {
this.marker.setPosition(location);
}
}
...
In
ngOnInit(),
I use
setInterval(this.findMe(), 3000);
By checking the log, I see the findMe() is only called once, but not be repeated as that I expect.
I also tried changing findMe() ==> findMe
setInterval(this.findMe, 3000);
this time, the log repeatedly appears, however there is always a error:
ERROR TypeError: _this.showPosition is not a function
Could you please help how can I repeatedly calling findMe() and why the error happens?
The correct way to invoke the interval is with the function declaration setInterval(this.findMe, 3000);. As you noted, if you include the () it is only executed once.
One of the issues that comes up with setInterval is that it changes the this context of the executing function. To fix this, you need to force it to be constant.
constructor(public globalvar: GlobalvarService) {
this.findMe = this.findMe.bind(this);
}
Additional info:
Documentation
StackOverflow Question
You can just use an arrow function that preserves this context :
setInterval(() => this.findMe(), 3000);
You can use arrow function syntax to make it work.
ngOnInit() {
setInterval(() => {
this.findMe()
}, 4000);
}
findMe = () => {
console.log('found');
}
Arrow function is referencing this as Component at all times.
Example - https://stackblitz.com/edit/angular-wkv2he
Try
setInterval(() => {
this.findMe()
}, 3000);
But I think than better solution is to use Observable interval.
interval(3000).subscribe(res => {
this.findMe()
})
Or in older versions of Angular :)
Observable.interval(3000).subscribe(res => {
this.findMe()
})

VueJS Mixins Methods

I want to use a mixin within my VUEJS module:
Module
<script>
var GoogleMaps = require('../mixins/GoogleMaps');
export default {
mixins: [GoogleMaps],
events: {
MapsApiLoaded: function(data) {
GoogleMaps.initGISMap(data);
}
},
}
</script>
Mixin
export default {
methods: {
initGISMap(selector) {
map = new google.maps.Map(selector, {
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP,
});
// Set initial Location and center map to this location
initialLocation = new google.maps.LatLng(48.184845, 11.252553);
map.setCenter(initialLocation);
// Create a searchmarker
searchMarker = createMarker();
// Init Autocomplete for GIS
initAutoComplete();
}
}
}
But I get an error, that GoogleMaps.initGISMap is not a function. How do I use a method of a mixin within a component?
-- edit to correct mistake I made in interpreting your needs
When using mixins, you don't reference the methods MixinName.method() - it's just 'this' - those methods and properties returned by your mixin and are first order, so to speak, so they are bound to 'this'.
<script>
var GoogleMaps = require('../mixins/GoogleMaps');
export default {
mixins: [GoogleMaps],
events: {
MapsApiLoaded: function(data) {
this.initGISMap(data);
}
},
}
</script>

Taking Screenshot Ionic framework

I'm building Ionic application that have geolocation (Google Api), but that's irelevant, in upper right corner is button which i want to make to take screenshot and automatically make popover with options to send that screenshot image via email, viber..., but i don't have an idea how to take that screenshot, I googled and googled without any luck, please help.
app.controller('MapCtrl', function($scope, $cordovaGeolocation, $ionicLoading, $ionicPlatform) {
$ionicPlatform.ready(function() {
$ionicLoading.show({
template: '<ion-spinner icon="bubbles"></ion-spinner><br/>Acquiring location!'
});
var posOptions = {
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 0
};
$cordovaGeolocation.getCurrentPosition(posOptions).then(function (position) {
var lat = position.coords.latitude;
var long = position.coords.longitude;
var myLatlng = new google.maps.LatLng(lat, long);
var mapOptions = {
center: myLatlng,
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
$scope.map = map;
$ionicLoading.hide();
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Lokacija'
});
}, function(err) {
$ionicLoading.hide();
console.log(err);
});
});
});
Two options, as far as I can tell:
Use a third-party Cordova plugin, such as https://github.com/gitawego/cordova-screenshot - this will most likely include the application's UI elements too, though, which might not be what you want.
Perhaps a better idea would be to use the Google Static Maps API - you can pass the current parameters from your dynamic map to it, and it'll return an image version.
This should get you started: How to take a screen shot in ionic
After you received the picture from the plugin, you can just use ionic's popover service to display it there.
This below code should help
*The function will take screenshot and share popup
For More details you can visit SocialSharing and Screenshot Ionic offical page
import { SocialSharing } from '#ionic-native/social-sharing/ngx';
import { Screenshot } from '#ionic-native/screenshot/ngx';
constructor(
private socialSharing: SocialSharing,
private screenshot: Screenshot
) { }
share(){
this.platform.ready().then(() => {
this.screenshot.URI(80)
.then((res) => {
//this.socialSharing.share('df',res.URI,null)
this.socialSharing.share('',null,res.URI,null)
.then(() => {},
() => {
alert('SocialSharing failed');
});
},
() => {
alert('Screenshot failed');
});
});
}

Categories

Resources