How to create mapbox gl with vuejs - vue.js

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<MglMap :accessToken="accessToken" :mapStyle="mapStyle" />
</template>
<script>
import Mapbox from "mapbox-gl";
import { MglMap } from "vue-mapbox";
export default {
components: {
MglMap
},
data() {
return {
accessToken: "pk.eyJ1IjoiYWlzaHdlcnlhIiwiYSI6ImNrYzVyYXBlNzBrZGgzMG8wc3FtZjU5NDAifQ.u4azaXjkh41xSMC1NJLhTw", // your access token. Needed if you using Mapbox maps
mapStyle: "mapbox://styles/aishwerya/ckc5ufmlw0nu11ip289o79bkl" // your map style
};
},
created() {
// We need to set mapbox-gl library here in order to use it in template
this.mapbox = Mapbox;
}
};
</script>
I created the mapbox-gl map but it showing blank screen
I have tried with this link but it didnt worked
I dont what Im missing it clearly shows me blank screen

Here is a simple way to integrate the mapbox application using Vue 2. This example doesn't require NPM or import statements. I would be careful about including your api key on public forums. I have included your api key in order for this example to work.
<script src="https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<style>
#project { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
<div id="project"></div>
<script>
var mapping = new Vue({
el: '#project',
data: {
map: ''
},
mounted(){
mapboxgl.accessToken = 'pk.eyJ1IjoiYWlzaHdlcnlhIiwiYSI6ImNrYzVyYXBlNzBrZGgzMG8wc3FtZjU5NDAifQ.u4azaXjkh41xSMC1NJLhTw';
//create a new mapbox instance
this.map = new mapboxgl.Map({
container: 'project',
'style' : 'mapbox://styles/mapbox/light-v10'
});
//fit the united states to the screen
this.map.fitBounds([[-135, 47], [-60, 25]]);
}
});
</script>

Related

Add Vue component to canvas with fabric.js library

Instead of creating custom object shape, I already have it as a Vue component. Here is what I have tried:
<template>
<div>
<canvas ref="canvas"></canvas>
<button type="button" #click="addVueComponent()">Add to canvas</button>
</div>
</template>
<script>
import { fabric } from 'fabric';
import CustomComponent from "CustomComponent.vue";
export default {
mounted() {
this.canvas = new fabric.Canvas(this.$refs.canvas);
},
methods:
{
addVueComponent() {
var vueComponent = new Vue({
template: '<custom-component ref="customComp"></custom-component>',
components: { 'custom-component': CustomComponent},
});
vueComponent.$mount();
var customObj = new fabric.Rect({
width: 100,
height: 100,
left: 50,
top: 50,
});
customComponent._element = vueComponent.$refs.customComponent.$el;
this.canvas.add(customComponent);
}
}
}
but instead of a rendered component I am just getting black rectangle as a result.
Is it even possible to add Vue component to canvas and what is the way to do it?

re-using Vuetify theme colors

Vuetify provides a configurable theme which defines a set of color that may be overridden when constructing the Vuetify object, e.g.
const vuetify = new Vuetify({
theme: {
themes: {
light: {
primary: '#3f51b5',
secondary: '#b0bec5',
error: '#b71c1c',
}
}
}
})
In the example above, I've overridden 3 of the theme colors. How can I use these theme colors in my own components, e.g. if I want to set the background color of a div to match the primary color
<template>
<div id="container"></div>
</template>
<script>
// detail omitted
</script>
<style lang="scss" scoped>
#container {
background-color: '#3f51b5';
}
</style>
In the example above I've hard-coded the primary color, but I assume Vuetify provides a way of avoiding this repetition, e.g. a SASS/SCSS variable?
If you don't need to support IE11 you can tell the theme system to use CSS custom properties instead:
new Vuetify({
theme: {
options: { customProperties: true },
},
})
Then you can access the colors directly in your stylesheet:
#container {
background-color: var(--v-primary-base);
}
https://vuetifyjs.com/en/features/theme/#custom-properties
Vuetify 3 doesn't support IE so this is always enabled, and the custom properties are r,g,b lists so you need to use rgb() or rgba() to access them:
#container {
background-color: rgb(var(--v-theme-primary));
color: rgba(var(--v-theme-on-primary), 0.8);
}
You can simply achieve that by applying the CSS as per your custom theme. Please follow the below steps.
Add a wrapper element <v-app> around your component content and then by using computed property get the theme colors.
<v-app :style="getColors">
computed: {
getColors () {
let themeColors = {}
Object.keys(this.$vuetify.theme.themes.light).forEach((color) => {
themeColors[`--v-${color}`] = this.$vuetify.theme.themes.light[color]
})
return themeColors;
}
}
And then in CSS, You can achieve like this :
#container {
color: var(--v-primary);
}
Live demo :
new Vue({
el: "#app",
opts: {
theme: {
themes: {
light: {
primary: '#3f51b5',
secondary: '#b0bec5',
error: '#b71c1c',
}
}
}
},
vuetify: new Vuetify(this.opts),
computed: {
getColors () {
let themeColors = {}
Object.keys(this.$vuetify.theme.themes.light).forEach((color) => {
themeColors[`--v-${color}`] = this.$vuetify.theme.themes.light[color]
})
return themeColors
}
}
});
.container {
color: var(--v-primary);
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css"/>
<div id="app">
<v-app :style="getColors">
<h4 class="container">Hello</h4>
</v-app>
</div>

OpenLayers with VueJS - empty div in place of map

I'm trying to implement a simple world map in a Vue application. I have created a MapContainer component that is then imported into my main app. Below is the code for MapContainer.vue:
<template>
<div
ref="map-root"
style="width: 100%, height: 100%">
</div>
</template>
<script>
import View from 'ol/View';
import Map from 'ol/Map';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import 'ol/ol.css';
export default {
name: 'MapContainer',
components: {},
props: {},
mounted() {
new Map({
target: this.$refs['map-root'],
layers: [
new TileLayer({
source: new OSM()
})
],
view: new View({
zoom: 0,
center: [0, 0],
constrainResolution: true
})
});
}
}
</script>
<style>
</style>
I am registering the MapContainer component and then simply placing it inside a div in the parent component. When I import this component and try to use it, I get an empty div in place of the map. Does anyone know what I'm doing wrong?
Here is the parent component's code:
<template>
<div>
<map-container></map-container>
</div>
</template>
<script>
import MapContainer from '../mapping/MapContainter.vue';
export default {
components: {
'map-container': MapContainer
}
}
</script>
I fixed this by adding the following class to the div with the ref:
.map {
width: 100% !important;
height: 600px !important;
}
(The !important's might not be strictly necessary).

Using custom model objects as provider for v-for in Vue?

new to Vue - learning as I go about exploring.
I'm trying to use a custom object as data source for a v-for situation. So far, not working - I admit I'm not sure how to access data by name in a Vue component.
main.js
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import VueKonva from "vue-konva";
Vue.use(VueKonva);
import RoomBuilder from "#/model/RoomBuilder";
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App),
data: () => ({
roomBuilder: new RoomBuilder()
})
}).$mount("#app");
The custom object, which may not be wired right into the data provider, is roomBuilder.
Then, in the component where I want to reference this object, I have this code:
<template>
<v-stage ref="stage" :config="stageSize">
<v-layer>
<v-rect ref="background" :config="backgroundConfig"></v-rect>
<v-rect
v-for="room in roomBuilder.getRooms()"
:key="room.id"
:config="room.config"
></v-rect>
</v-layer>
</v-stage>
</template>
<script>
export default {
name: "RoomGrid",
data() {
return {
stageSize: {
width: 1000,
height: 1000
},
backgroundConfig: {
width: 50,
height: 50,
fill: "#2B2B2B"
}
};
},
mounted() {
this.$nextTick(function() {
window.addEventListener("resize", this.fitStageIntoParentContainer);
this.fitStageIntoParentContainer();
});
},
methods: {
fitStageIntoParentContainer() {
const parentElement = this.$parent.$el;
const background = this.$refs.background.getNode();
background
.setAttr("width", parentElement.clientWidth)
.setAttr("height", parentElement.clientHeight);
}
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss"></style>
The two POJOs are:
RoomBuilder.js
import Room from "#/model/Room";
class RoomBuilder {
construct() {
this.rooms = [new Room(1)];
}
drawOnto(konvaStage) {
console.log(konvaStage);
}
getRooms() {
return this.rooms;
}
}
export default RoomBuilder;
and
Room.js
class Room {
construct(id) {
this.id = id;
this.config = {
x: 10,
y: 10,
fill: "white",
width: 10,
height: 10
};
}
}
export default Room;
Thanks, and go easy on me. I'm typically a server-side guy! I clearly have wired something wrong... have tried
v-for="room in this.$data.roomBuilder.getRooms()"
v-for="room in roomBuilder.getRooms()"
etc.
Clearly there's some magic afoot I don't understand!
Thank you!

How to compute styles on <body> or <html> using vue.js?

I am using vuejs style bindings to render changes dynamically as the styles are computed.
This works great for everything within the scope of my Vue instance but how can I compute styles for body or html tags?
This used to be possible when you could bind the vue instance to but vue no longer lets you do it.
I want to dynamically update the background color of using my computed variables in vue.
edit: added code snippet to demonstrate
var app = new Vue({
el: '#app',
data: {
color: '#666666'
},
computed: {
backgroundColor: function() {
return {
'background-color': this.color
}
}
},
methods: {
toggleBackground: function() {
if(this.color=='#666666'){
this.color = '#BDBDBD'
} else {
this.color = '#666666'
}
}
}
})
<script src="https://vuejs.org/js/vue.min.js"></script>
<html>
<body>
<div id="app" :style="backgroundColor">
<div>
lots of content...
</div>
<button #click="toggleBackground"> Click to toggle </button>
</div>
</body>
</html>
If you really need to style body itself, you'll need to do it with plain JavaScript in a watcher. A simple example is below.
You should (not something I've tried, but I'm hypothesizing) be able to defeat overscrolling effects by making body and your outer container non-scrolling. Put a scrollable container inside that. When it overscrolls, it will show your outer container, right?
The reasons for not binding to body are here (for React, but applies to Vue).
What’s the problem with ? Everybody updates it! Some people have
non-[Vue] code that attaches modals to it. Google Font Loader will
happily put elements into body for a fraction of second, and
your app will break horribly and inexplicably if it tries to update
something on the top level during that time. Do you really know what
all your third party scripts are doing? What about ads or that social
network SDK?
new Vue({
el: '#app',
data: {
isRed: false
},
watch: {
isRed() {
document.querySelector('body').style.backgroundColor = this.isRed ? 'red' : null;
}
}
});
#app {
background-color: white;
margin: 3rem;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<input type="checkbox" v-model="isRed">
</div>
I think I found better solution than using jQuery/querySelector
You can add tag style right in your Vue template.
And add v-if on this, smth like that:
<style v-if="true">
body {
background: green;
}
</style>
Thus you can use computed/methods in this v-if and DOM always will update when you need.
Hope this will help someone ;)
UPD:
Using tag "style" in templates is not best idea, but you can create v-style component, then everything will be fine:
Use style tags inside vuejs template and update from data model
My snippet:
Vue.component('v-style', {
render: function (createElement) {
return createElement('style', this.$slots.default)
}
});
new Vue({
el: '#app',
data: {
isRed: false,
color: 'yellow',
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="checkbox" v-model="isRed">
<v-style v-if="isRed">
body {
background: red; /*one more benefit - you can write "background: {{color}};" (computed)*/
}
</v-style>
</div>