How to use capacitor camera preview in a Vue.js app? - vue.js

I have a Vue.js app and I want to use capacitor camera preview plugin.
But when I run the app on web I get this error on the console
Also it does not work in IOS as well.
Here is the documentation of the plugin
https://github.com/capacitor-community/camera-preview#readme
Here is my component
<template>
<div>
</div>
</template>
<script>
import '#capacitor-community/camera-preview'
import { CameraPreview } from '#capacitor-community/camera-preview';
const cameraPreviewOptions = {
position: 'rear',
height: 1920,
width: 1080
};
export default {
created() {
CameraPreview.start(cameraPreviewOptions);
}
}
</script>

I added id="cameraPreview" and my problem is fixed
<template>
<div id="cameraPreview">
</div>
</template>

Related

How to use Swiper.js(version 8+) in Nuxt(2.15.8)

First I tried this as showed in official Swiper.js website for Vue 3 demo
<template>
<swiper
:effect="'coverflow'"
:grabCursor="true"
:centeredSlides="true"
:slidesPerView="'auto'"
:coverflowEffect="{
rotate: 50,
stretch: 0,
depth: 100,
modifier: 1,
slideShadows: true,
}"
:pagination="true"
:modules="modules"
class="mySwiper"
>
<swiper-slide v-for="card in cards"
><img
:src="card.image" /></swiper-slide>
</swiper>
</template>
<script>
// Import Swiper Vue.js components
import { Swiper, SwiperSlide } from "swiper/vue";
// Import Swiper styles
import "swiper/css";
import "swiper/css/effect-coverflow";
import "swiper/css/pagination";
import "./style.css";
// import required modules
import { EffectCoverflow, Pagination } from "swiper";
export default {
props: ['cards']
setup() {
return {
modules: [EffectCoverflow, Pagination],
};
},
};
</script>
And it did not work.
Then I tried to import it as a plugin in plugins folder of nuxt:
import Vue from 'vue';
import { Swiper, EffectCoverflow, Pagination } from "swiper";
const swiper = {
install(Vue, options) {
Vue.prototype.$swiper = Swiper;
Vue.prototype.$swiperModules = {
EffectCoverflow,
Pagination,
};
}
};
Vue.use(swiper);
And registred it in nuxt.js.config as: src: './plugins/swiper.client.js', mode: 'client'
And tried to use it in my component like this:
<template>
<Swiper>
<SwiperSlide v-for="card in cards" :key="card.id">
<NuxtLink :to="`products/${card.id}`" class="card">
<img
:src="require(card.image)"
alt="image"
class="image"
/>
<h3 class="header">{{ card.title }}</h3>
<p class="snippet">{{ card.snippet }}</p>
</NuxtLink>
</SwiperSlide>
</Swiper>
</template>
<script>
export default {
props: ['cards'],
mounted() {
this.swiper = new this.$swiper('.swiper', {
loop: true,
// configure Swiper to use modules
modules: [
this.$swiperModules.Pagination,
this.$swiperModules.EffectCoverflow,
],
})
},
}
</script>
And it is still not working, What am I doing wrong?
Can anyone help with it?
TLDR: Nuxt2 and Swiper8 are not compatible.
Swiper v8.0.0 is almost 1 year old: https://github.com/nolimits4web/swiper/releases/tag/v8.0.0
2 years ago, nolimits4web aka the main maintainer of the package said
Swiper Vue.js components are compatible only with new Vue.js version 3
Easy to say that the v8 of Swiper is definitely not compatible with Nuxt2 (using Vue2).
Even if there was a hack, it would be quite dirty and not the thing that I would recommend overall.
swiper#8.4.5 is also 38.7kB gzipped, which is quite on the heavy side of things.
If you're using all of its features and ready to upgrade to Nuxt3 (which might not be trivial), then you could maybe proceed.
Otherwise, you could maybe design your own carousel component or check the ones available here: https://github.com/vuejs/awesome-vue#carousel
I'm guessing that there are some projects with Nuxt2 support still, not too heavy and still maintained that could satisfy your needs.

d3 graph rendering with vue

Because of non compatible dependencies, I have to downgrade from vue3 to vue2.
I have created a force directed graph with D3 library. Everything worked find with vue3 using composition api. I am not familiar with vue 2 and adapting my graph to vue2 has not been working out for me.
In vue3 it was very straitforward and ref() made it pretty easy to accomplish.
As for vue2, I have tried making good use of lifecycle hooks such as computed and watch
Any help is more than welcome
Here is a minimalistic representation of my working component in vue3. This component creates the graph in a svg and then renders it in the template.
<template>
<div class="col" style="position: absolute; width:100%; height:100%" >
<div class="main-map-container" style="overflow: hidden; width: 100%;">
<div ref="graph" class="canvas">
</div>
</div>
</div>
</template>
<script >
import {onMounted, onBeforeMount, ref} from 'vue'
export default {
setup(){
const graph = ref()
const links = [{src:"Amazon",target:"Aurora"},{src:"Amazon",target:"Aurora"},{src:"Amazon",target:"Zoox"},{src:"Amazon",target:"Rivian"}]
const nodes = [{id:"Amazon"},{id:"Aurora"},{id:"Zoox"},{id:"Rivian"}]
onBeforeMount( async ()=>{
const svgobj = ForceGraph(nodes, links)
graph.value.appendChild(svgobj);
})
function ForceGraph(
nodes,
links
){
// The code for the graph has been removed since it is much too long
return Object.assign( svg.node() );
}
return { graph }
}
}
</script>
<style></style>
This is the vue2 component that i have emptied for this post
<template>
<div class="col" style="position: absolute; width:100%; height:100%" >
<div class="main-map-container" style="overflow: hidden; width: 100%;">
<div ref="graph" class="canvas">
</div>
</div>
</div>
</template>
<script>
export default {
setup(){
},
methods: {
},
watch: {
},
props: {
},
computed: {
},
created() {
},
mounted() {
},
updated(){
},
data() {
return {
}}
}
</script>
<style>
</style>
You can use Vue3 composition API in vue 2. Install the composition api and then just keep your code the same, with the setup method exactly as it was.
The setup method, lifecycle hooks, and all the reactivity (refs and reactive objects) are made available to you, with very few incompatibilities.
We use d3 with Vue2 in this fashion all the time. 100% compatible.
https://github.com/vuejs/composition-api

How to create vertical slider with Swiper Vue.js?

I am creating simple app using Vue3, also I am using Swiprer.js for vue, documentation of swiper.js (for vue3) is incomprehensible to me, I have imported all modules in my application, but now i want to create vertical scrollable slider, like picture below, my swiper component looks like this:
but still can't create vertical scrollable slider, this what my template looks like, any solutions?
<template>
<div class="container-main-slider">
<div class="container-main-slider__inner" id="sliderBox">
<swiper
:slides-per-view="1"
:space-between="20"
:direction="vertical"
:pagination="{ clickable: true}"
>
<swiper-slide>
<img :src="dynamic content">
</swiper-slide>
</swiper>
</div>
</div>
</template>
<script>
/* swiper slider imports */
import { Swiper, SwiperSlide } from "swiper/vue";
import SwiperCore, { A11y, Autoplay, Pagination } from "swiper";
import "swiper/swiper.scss";
import "swiper/swiper.scss";
import 'swiper/components/pagination/pagination.scss';
SwiperCore.use([A11y, Autoplay,Pagination]);
export default {
data(){
return{
fixedheader:false,
}
},
components: {
Swiper,
SwiperSlide,
},
methods:{
showVideo(){
this.$store.commit("CheckvideoVisibility", false)
},
onSlideChange() {
console.log('slide change');
},
},
};
</script>
`
I have a solution
If someone faced the same problem: you just need to put 'vertical' in single quotes.
It will look like this in Vue template:
<swiper
:slides-per-view="1"
:space-between="0"
:direction="'vertical'"
>

Vue2-leaflet map not showing properly in BoostrapVue modal

Here's my problem - a Vue2 leaflet map does not render correctly in BootstrapVue modal.
Here's what it looks like visually (it should show just the ocean)
<template>
<div>
<b-modal size="lg" :visible="visible" #hidden="$emit('clear')" title="Event details">
<div class="foobar1">
<l-map :center="center" :zoom="13" ref="mymap">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker :lat-lng="center"></l-marker>
</l-map>
</div>
<template slot="modal-footer">
<b-btn variant="danger" #click="deleteEventLocal(event.id)">Delete</b-btn>
</template>
</b-modal>
</div>
</template>
<script>
import * as moment from "moment";
import { LMap, LMarker, LTileLayer } from "vue2-leaflet";
import { deleteEvent } from "./api";
import "vue-weather-widget/dist/css/vue-weather-widget.css";
import VueWeatherWidget from "vue-weather-widget";
export default {
data() {
return {
center: L.latLng(event.latitude, event.longitude),
url: "http://{s}.tile.osm.org/{z}/{x}/{y}.png",
attribution:
'© OpenStreetMap contributors'
};
},
props: {
visible: {
type: Boolean
},
event: {
required: true,
type: Object
}
},
methods: {
async deleteEventLocal(id) {
await deleteEvent(id);
this.$emit("refresh");
this.$emit("clear");
}
},
components: {
weather: VueWeatherWidget,
LMap,
LMarker,
LTileLayer
}
};
</script>
As you can see there aren't any CSS rules that could make the map spill outside the modal as it does. Which is weird.
I'm kinda asking this question to answer it myself as I couldn't find a solution before.
There were 3 issues because of which this was happening.
1. First - I forgot to load the leaflet css into main.js - this is why the leaflet map was somehow outside the modal.
//src/main.js
import '#babel/polyfill';
import Vue from 'vue';
import './plugins/bootstrap-vue';
import App from './App.vue';
import router from './router';
import store from './store';
//above imports not important to this answer
import 'leaflet/dist/leaflet.css'; //<--------------add this line
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');
2. Now the map may disappear. Set a width and height on the l-map component's container. I used a class but you can use style="" etc.
<div class="foobar1"> <!-- <--- Add a class on l-map's container -->
<l-map :center="center" :zoom="13">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker :lat-lng="center"></l-marker>
</l-map>
</div>
<style lang="scss">
.foobar1 { /* <--- class we added above */
width: 100%;
height: 400px;
}
</style>
3. Now your map will render within the modal but if you move the map's view, you'll see that leaflet does not download the map's squares in time.
You will see something like this:
To fix this:
create an event handler on b-modal for the #shown event.
<b-modal
#shown="modalShown"
#hidden="$emit('clear')"
size="lg"
:visible="visible"
title="Event details"
>
I called mine modalShown.
Then, add a ref attribute to your l-map. I called mine mymap.
<l-map :center="center" :zoom="13" ref="mymap"> <!-- ref attribute added to l-map -->
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker :lat-lng="center"></l-marker>
</l-map>
Then, create a modalShown method in the Vue methods for your view/component and call invalidateSize() inside.
export default {
data() {
//some data here
}
methods: {
modalShown() {
setTimeout(() => {
//mapObject is a property that is part of leaflet
this.$refs.mymap.mapObject.invalidateSize();
}, 100);
}
}
}
Now everything should be fine:
map should not spill outside the modal
map should be visible (duh)
map squares should be downloaded when within map body
Here's my full code, it contains some stuff specific to my app but overall it contains all of the code snippets above.
Addtional to Artur Tagisow answer
You can also use this approach to your parent component if your map is in child component.
export default {
data() {
//some data here
}
methods: {
modalShown() {
setTimeout(() => {
window.dispatchEvent(new Event("resize"));
}, 100);
}
}
}
For vue.js and nuxt.js developers , probably it's because of using v-show or v-if
!in your case display none happening by bootstrap modal
but dont worry the only thing u have to do is using client-only (its like ssr but for new version of js frameworks like nuxt or vue):
<client-only>
<div id="bootstrapModal">
<div id="map-wrap" style="height: 100vh">
<l-map :zoom=13 :center="[55.9464418,8.1277591]">
<l-tile-layer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"></l-tile-layer>
<l-marker :lat-lng="[55.9464418,8.1277591]"></l-marker>
</l-map>
</div>
</div>
</client-only>
ps: if still not loaded in iphone browsers it's probably because of geolocation

GSAP implementing to Vue.js app with webpack

i have a problem with implementing GSAP to my vue.js app which i created with vue-cli and webpack
What i wanna do?
1- I tried to create tween beforeComponent mounting, in some function.
What i tried?
1- I create my vue app,
2- I already installed this package, with:
npm install greensock --save
everything is was okey with installation, then;
3- I imported TweenMax to main.js with this way:
import { TweenMax } from 'greensock';
4- I created some div into my component for animating with TweenMax.
5- I create some functions into methods of my component which wrapping the Tween,
methods: {
animate: function() {
TweenMax.to(".rect", 1, {x:100, alpha:0, ease:Sine.easeIn});
console.log('test');
}
},
and then i call this function on before mounting component;
beforeMount(){
this.animate()
}
so my tween not working, i'm not getting some error in my console.
I print the console.log("test"); for testing the function is work or not?.
result is function work. I'm getting the test message on console. But tween is no there :) .
Where i make mistake ?
Fully code of my component:
<template>
<div class="container">
<div class="home">
<h1>
HELLO
</h1>
<h4>
How are u doing?
</h4>
</div>
<div class="rect">
</div>
</div>
</template>
<script>
export default {
name: 'Home',
methods: {
animate: function() {
TweenMax.to(".rect", 1, {x:100, alpha:0, ease:Sine.easeIn});
console.log('test');
}
},
beforeMount(){
this.animate()
}
}
</script>
<style lang="scss">
.rect {
background-color:blue;
width: 10vw;
height: 100px;
position: absolute;
z-index: -1;
}
</style>
FIX . ///////////
While i wait to answer :) found the solution myself,
everything is fine with code, just need to call function not on beforeMount(), need to call it on mounted();