Openlayer and vuejs - Error on addEventlistener - vue.js

I'm trying to integrate openlayer with vuejs.
Whatever i try i still have the following error : Uncaught TypeError: target.addEventListener is not a function
After some research i found some example in vuejs but don't really help me.
I have also try vuelayers. I got the same error.
Any idea ?
EDIT :
openlayers version : "ol": "^6.4.3",
vuejs version : "vue": "^2.6.11",
<template>
<div class="w3-content">
<div ref="map-root" id="map"></div>
</div>
</template>
<script>
import 'ol/ol.css';
import { Map, View } from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
export default {
data() {
return {
}
},
methods: {
initMap() {
const map = new Map({
target: this.$refs['map-root'],
layers: [
new TileLayer({
source: new OSM()
})
],
view: new View({
center: [0, 0],
zoom: 0
})
});
}
},
mounted() {
this.initMap();
}
}
</script>

Related

How to Implement leaflet toolbar with vue3?

I am trying to install leaflet toolbar with vue3 but it not working
there are package available for vue2 but nothing available related to vue3.
I tried to implement the same using javascript but it is not helping
So if any have used it leaflet with vue3 using package or javascript code please let me know
Below is the screenshot of what I am trying to achieve using leaflet
enter image description here
Below is the code using which I got leaflet map working
`
<template>
<div id="mapContainer"></div>
</template>
<script>
import 'leaflet/dist/leaflet.css';
import "leaflet-draw/dist/leaflet.draw.css";
import L from 'leaflet';
import "leaflet-draw/dist/leaflet.draw-src.js";
export default {
name: "LeafletMap",
data() {
return {
map: null,
};
},
mounted() {
this.map = L.map("mapContainer").setView([51.5072, 0.1276], 5);
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
attribution:
'© OpenStreetMap contributors',
}).addTo(this.map);
//use a mix of renderers
var customPane = this.map.createPane("customPane");
var canvasRenderer = L.canvas({ pane: "customPane" });
customPane.style.zIndex = 399; // put just behind the standard overlay pane which is at 400
},
onBeforeUnmount() {
if (this.map) {
this.map.remove();
}
},
};
</script>
`

Vue - Change root component using Vue.componet or Async component

I want to have a dynamic/async component which will be loaded based on menu click. There will be a lot of links and components.
My problem is :
Cannot find test-component even I registered globally using Vue.Component
Can the component1 in root be changed? If it is possible, I will call component file using Ajax.
Thanks in advance.
Index.html
<script src="~/bundle/site.js"></script>
<div id="app">
<input type="button" v-on:click="changeComponent('test-component')" value="Click me"/>
<component v-bind:is="view"></component>
</div>
site.js
import Vue from 'vue';
import axios from 'axios';
global.Vue = Vue;
global.axios = axios;
var vm = new Vue({
el: '#app',
data: {
view: 'component1'
},
components: {
'component1': {
template: '<div>Dynamic Component master</div>'
}
},
methods: {
changeComponent: function (parComp) {
this.component1 = parComp;
},
}
});
Vue.component('test-component', {
template: '<div v-on:click = "changeName()"><h1>{{msg}}</h1></div>',
data: function () {
return {
msg: "Test Componet"
}
},
methods: {
changeName: function () {
this.msg = "mouse clicked";
},
}
})
Update
change vm = new Vue().... to global.vm = new Vue().....
call vm.changeComponent('test-component')
It works now.
Vue.options.components["test-component"] can access it.
But test-component cannot be access in html like :
<test-component></test-component>
The problem solved by :
change vm = new Vue().... to global.vm = new Vue().....
declare Vue.component('test-component'.... before new Vue()
Thanks
Wilson

Create dynamic Google Map Markers with SVGs

I am trying to create Google Map Markers with dynamic information in it. For that feature I am using a Vuejs-Component with a SVG as template and add a "text"-Tag.
Example:
<template>
<svg width="40px" height="56px" viewBox="0 0 40 56" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<text>{{ text }}</text>
</svg>
</template>
<script>
export default {
name: "DynamicGMapMarker",
props: {
text: {
type: String,
required: true
}
}
}
</script>
Then I am creating the SVG via a helper function and create a base64 data url:
import Vue from 'vue'
import DynamicGMapMarker from './DynamicGMapMarker'
const DynamicGMapMarkerConstructor = Vue.extend(DynamicGMapMarker)
export const getDynamicMarkerIcon = (text) => {
const iconComponent = new DynamicGMapMarkerConstructor({
propsData: {
text
}
});
iconComponent.$mount();
const iconDom = iconComponent.$el;
const iconString = new XMLSerializer().serializeToString(iconDom);
return 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(iconString);
}
Now, I can use the getDynamicMarkerIcon() function. This is working in vue.js, but not in nuxt.js. In nuxt.js we need to add a XML-Serializer from npm, since nuxt can not use the Browser's XMLSerializer. For that I am using teclone/xml-serializer.
Now, the Problem seems to be that Nuxt can not create a DOM, because of SSR. When I am trying to use this method:
<template>
<div id="app">
<GmapMap
:center="center"
:zoom="15"
:options="options"
id="map"
>
<GmapCluster :zoomOnClick="true">
<GmapMarker
:key="index"
v-for="(marker, index) in markers"
:position="marker.coordinates"
:clickable="true"
:draggable="false"
:title="marker.name"
:icon="getMarker(marker)"
/>
</GmapCluster>
</GmapMap>
</div>
</template>
<script>
import GmapCluster from 'vue2-google-maps/dist/components/cluster'
import {getMarkerIcon} from "./MapIconUtil"
export default {
name: 'App',
components: {
GmapCluster
},
methods: {
getMarker(marker) {
return getDynamicMarkerIcon(marker.text);
}
},
data() {
return {
options: {
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
rotateControl: false,
fullscreenControl: false,
disableDefaultUi: true,
clickableIcons: false
},
center: {
lat: 11,
lng: 11
},
"markers": [
{
coordinates: {
name: "Test",
lat: 11.0001,
lng: 11.0001,
text: "101"
}
}
]
}
}
}
</script>
I get an error that iconComponent.$el is undefined. I can not mount the SVG inside a DOM.
Are there any possibilities to tell Nuxt, that this component should run on browser side only?
I have already tried to wrap GmapMarker in <client-only>-Tag. That did not work. Can I use something like a "virtual DOM"? Any other ideas how to make it work?
I did it. You can selectively change the "mode" in which nuxt will render a specific url. Here you can see what configurations are possible.
You have to create a server middleware and tell nuxt if a path should be rendered in spa. Otherwise just default to your mode specified in your nuxt.config.js.
Check this out for an example.

set default map centering with props in vue

I'm using vue to make an arc gis driven application, because the map's center can changed based on user location, I am setting the default location to some props then passing them into my map component to be called in the map components mounted() hook for rendering.
I think i'm pretty close to doing this correctly but when I log my props in my map component in the console it says they're undefined.
I'm not sure if my app code is at fault or my child component code?
as you can see in my app.vue I am even trying to pass in plain integers to test the values and they are still undefined.
app.vue
<template>
<div id="app">
<web-map v-bind:centerX="-118" v-bind:centerY="34" />
<div class="center">
<b-button class="btn-block" #click="getLocation" variant="primary">My Location</b-button>
</div>
</div>
</template>
<script>
import WebMap from './components/webmap.vue';
export default {
name: 'App',
components: { WebMap },
data(){
return{
lat: -118,
long: 34
}
},
};
</script>
webmap.vue
<template>
<div></div>
</template>
<script>
import { loadModules } from 'esri-loader';
export default {
name: 'web-map',
props:['centerX, centerY'],
data: function(){
return{
X: this.centerX,
Y: this.centerY
}
},
mounted() {
console.log(this.X,this.Y)
// lazy load the required ArcGIS API for JavaScript modules and CSS
loadModules(['esri/Map', 'esri/views/MapView'], { css: true })
.then(([ArcGISMap, MapView]) => {
const map = new ArcGISMap({
basemap: 'topo-vector'
});
this.view = new MapView({
container: this.$el,
map: map,
center: [this.X,this.Y], ///USE PROPS HERE FOR NEW CENTER
zoom: 8
});
});
},
beforeDestroy() {
if (this.view) {
// destroy the map view
this.view.container = null;
}
}
};
</script>
There is a typo. Change:
props:['centerX, centerY'],
to:
props:['centerX', 'centerY'],

Highmaps(HighCharts) loads same map when drilling down

I'm faced with a problem while implementing Highmaps.
In my vue project with Webpack, I followed each step explained https://github.com/highcharts/highcharts-vue to use Highmaps.
Here's my main.js file
//highchart
import HighchartsVue from 'highcharts-vue'
import Highcharts from 'highcharts'
import WorldMap from '#highcharts/map-collection/custom/world.geo.json'
import USMap from '#highcharts/map-collection/countries/us/us-all.geo.json'
import mapInit from 'highcharts/modules/map.js'
import DrillDown from 'highcharts/modules/drilldown.js'
mapInit(Highcharts);
DrillDown(Highcharts);
Highcharts.maps['world'] = WorldMap;
Highcharts.maps['us'] = USMap;
And, here's my vue file
<template>
<div>
<mymap :mapOptions="mapOptions.options"></mymap>
</div>
</template>
<script>
export default{
data(){
return {
mapOptions: {
options: {
chart: {
map: 'us',
events: {
drilldown: function(e){
var chart = this;
this.addSeriesAsDrilldown(e.point, {
data: 'world',
dataLabels: {
enabled: true,
format: '{point.name}'
}
})
},
drillup: function(){
}
}
},
series: [{
data: data,
joinBy: ['postal-code', 'code'],
dataLabels: {
enabled:true,
color: '#FFFFFF',
format: '{point.name}'
}
}],
}
}
}
},
}
</script>
Because the chart has 'chart': 'us' option, it renders US map first. Then, when I click any state (just for a test) it switches US map to world map.
It renders world map. However, it also render US map too. That is, it renders both two maps. How can I fix it??