switch camera using MediaDevices.getUserMedia() in vuejs 2 - vuejs2

I'm trying to develop a website where i can switch camera from chrome in mobile devices. Current im using vuejs 2 framework and using MediaDevices.getUserMedia() to take image. From here i understand how am i gonna use my code. Individually both of front and back camera working. But where im trying to switch between then its not working. Here is my code:
<template>
<div class="container" id="scanIdCardPage">
<div class="scanIdCardDiv">
<div class="scanCardContainer" v-show="afterTakingPhoto">
<video ref="video" id="video" :style="{width: divWidth}" autoplay></video>
<canvas ref="canvas" id="canvas" width="320" height="240" style="display: none;"></canvas>
</div>
</div>
</div>
<div class="takePhotoBtnDiv">
<div>
<button type="button" class="btn btn-info" #click="camera('environment')">Back Camera</button>
<button type="button" class="btn btn-info" #click="camera('user')">front Camera</button>
</div>
</div>
</div>
</template>
export default {
data() {
video: {},
front: true
},
methods: {
Camera() {
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: { facingMode: (this.front? "user" : "environment") }}).then(stream => {
this.video.src = window.URL.createObjectURL(stream);
this.video.play();
});
}
},
changeCamera() {
this.front = !this.front;
}
},
mounted() {
this.Camera();
}
}
Can anyone help me out how do i change the camera? TIA

I got my solution. MediaDevices.getUserMedia() can't directly change video facingMode. First you have to stop the running video stream. And then change the video facingMode. Here is my code:
export default() {
data() {
},
methods: {
camera(face) {
this.stop();
this.gum(face);
},
stop() {
return video.srcObject && video.srcObject.getTracks().map(t => t.stop());
},
gum(face) {
if(face === 'user') {
return navigator.mediaDevices.getUserMedia({video: {facingMode: face}})
.then(stream => {
video.srcObject = stream;
this.localstream = stream;
});
}
if(face === 'environment') {
return navigator.mediaDevices.getUserMedia({video: {facingMode: {exact: face}}})
.then(stream => {
video.srcObject = stream;
this.localstream = stream;
});
}
}
},
mounted() {
this.camera('environment');
},
}

Related

SwiperJS Lazy-Loading doesn't load images

I've followed these steps, but the images still won't load. I read somewhere, to load the swiper after the images are loaded. So I init the swiper after the data is successfully received. But are the images already loaded then?
<div class="swiper">
<div class="swiper-wrapper">
<div v-for="image in property.images" :key="image.id" class="swiper-slide">
<img :data-src="image.filePath" class="swiper-lazy" />
<div class="swiper-lazy-preloader"></div>
</div>
</div>
</div>
async fetch() {
try {
const property = await this.$axios.$get(
`/api/get-specific-property/${this.$route.params.id}`
)
if (property.success) {
this.property = property.data
this.initSwiper()
}
} catch (err) {
console.log(err)
}
},
methods: {
initSwiper() {
Swiper.use([Lazy]) // Not sure if it's really needed - saw this somewhere
this.swiper = new Swiper('.swiper', {
lazy: true,
preloadImages: false,
slidesPerView: 1,
loop: false,
})
}
}

No compatible source was found for this media

Get that error when try to get stream from any HLS source.
I tried to add videojs-contrib-hls lib , but its dont help.
Maybe should i try some other player, and what player will properly work with hls sources?
<script>
import 'video.js/dist/video-js.css'
import {videoPlayer} from 'vue-video-player'
import videojs from 'video.js'
window.videojs = videojs
export default {
components: {
videoPlayer
},
data () {
return {
playerOptions: {
height: '700',
width: '1820',
controls: true,
sourceOrder: true,
hls: true,
sources: [{
// type: "video/mp4",
type: "application/x-mpegURL",
// src: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
src: "http://127.0.0.1:8081/live/93UEctBmn/index.m3u8",
withCredentials: false,
}],
autoplay: false,
},
techOrder: ['html5'],
html5: { hls: { withCredentials: false } },
contentData: {}
}
},
mounted() {
this.$store.dispatch("content/getById", this.$route.params.contentId).then(
(res) => {
// this.message = data.message;
// this.snackbar = true;
if(res.data.error){
console.log(res.data.error);
return;
}
this.contentData = Array.isArray(res.data) ? res.data[0] : res.data;
},
(error) => {
// this.message = error.response.data.message || error;
// this.snackbar = true;
console.log(error)
}
);
}
}
</script>
<template>
<div class="content">
<div class="content-player">
<video-player class="vjs-custom-skin videoPlayer" :options="playerOptions" ></video-player>
</div>
<div class="content-info">
<div class="content-info_title">
{{contentData.streamTitle || 'loading'}}
</div>
</div>
<v-divider></v-divider>
<div class="content-author">
<div class="content-author_avatar">
<v-avatar
size="56"
>
<v-img
:src="'https://diploma-rtmp-bucket.s3.eu-central-1.amazonaws.com/'+contentData.author[0]._id || ''"
></v-img>
</v-avatar>
</div>
<div class="content-author_name">
{{contentData.author[0].username || 'undefined username'}}
</div>
</div>
</div>
</template>
Here is my page code. Can it be becouse of some CORS troubles?. I run it player on local machine
I used another player vue-vjs-hls. On this player hls work good, dont now why hls source not works at vue-video-player and video.js. What strange becouse vue-vjs-hls use video.js as core.

Vue JS - Clear Interval on mouseleave

I'm currently learning VueJS with a video course. I was doing an exercise on directives, but got carried away a little.
Anyway my goal is to get the "disco effect" by a mouseover on the "Disco Time"-button. That works fine, but I also want to clear the interval, when leaving the button.
I tried several things (e.g. calling clear interval in another method) and I'm pretty sure that the current solution isn't a nice one, but to my understanding it should at least work.
Can you tell me why it isn't working and how it would work? I also would be interested in nicer solutions (but using the directive, since this was my goal).
Thanks for helping a noobie (:
<script>
export default {
data() {
return {
showing: false,
color: 'lightgreen',
stopIt: false,
stopItt: false,
}
},
directives: {
'myEvent': {
bind(el, binding) {
const type = binding.arg
const fn = binding.value
el.addEventListener(binding.arg, binding.value)
}
}
},
methods: {
change() {
this.showing = !this.showing;
this.color == 'lightgreen' ? this.color = 'lightblue' : this.color = 'lightgreen';
},
disco() {
if (this.stopIt == false) {
var myDisco = setInterval(() => {
this.color == 'lightgreen' ? this.color = 'lightcoral' : this.color = 'lightgreen'
}, 100)
}
else if (this.stopIt == true) {
setTimeout(() => {
clearInterval(myDisco)}, 1000)
}
},
stopDisco() {
this.stopIt = true
//this.stopItt = true
this.disco();
},
}
}
</script>
<template>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
<div :style="{color: color}">
<h1>Directives Exercise</h1>
</div>
<button v-myEvent:click="change" class="btn btn-primary">Show me!</button>
<button v-myEvent:mouseover="disco" v-myEvent:mouseleave="stopDisco" class="btn btn-primary">Disco Time!</button>
<p v-if="showing">
Now you see me!
</p>
<p>
{{ stopIt }}, {{ stopItt }}
</p>
</div>
</div>
</div>
</template>
The reason your current approach isn't working is that the myDisco variable in disco() is scoped to that function, so when you call it again to try to clear the interval, you get a new, empty myDisco instead of the one containing the interval ID.
One simple way to fix this is to just put the interval ID itself in data(), instead of the separate stopIt boolean:
new Vue({
el: '.container',
data() {
return {
myDisco: undefined,
color: 'lightgreen',
}
},
directives: {
'myEvent': {
bind(el, binding) {
el.addEventListener(binding.arg, binding.value)
}
}
},
methods: {
disco() {
this.stopDisco(); // just in case there's any chance of calling disco() twice in a row...
this.myDisco = setInterval(() => {
this.color == 'lightgreen' ? this.color = 'lightcoral' : this.color = 'lightgreen';
}, 100)
},
stopDisco() {
clearInterval(this.myDisco); // will be a harmless no-op if myDisco is false
this.myDisco = undefined; // not strictly necessary, but just to be tidy
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container">
<div :style="{color: color}">
<h1>Directives Exercise</h1>
</div>
<button v-my-event:mouseover="disco" v-my-event:mouseleave="stopDisco" class="btn btn-primary">Disco Time!</button>
<div>Interval ID: {{myDisco}}</div>
</div>
Each time you call disco, myDisco is a different variable. You can't clear the old one that way. Instead, have the callback clear itself:
disco() {
this.stopIt = false;
const myDisco = setInterval(() => {
this.color == 'lightgreen' ? this.color = 'lightcoral' : this.color = 'lightgreen';
if (this.stopIt) {
clearInterval(myDisco);
}
}, 100)
},
stopDisco() {
this.stopIt = true
},
Demo runnable snippet below.
new Vue({
el: '.container',
data() {
return {
showing: false,
color: 'lightgreen',
stopIt: false,
}
},
directives: {
'myEvent': {
bind(el, binding) {
const type = binding.arg
const fn = binding.value
el.addEventListener(binding.arg, binding.value)
}
}
},
methods: {
change() {
this.showing = !this.showing;
this.color == 'lightgreen' ? this.color = 'lightblue' : this.color = 'lightgreen';
},
disco() {
this.stopIt = false;
const myDisco = setInterval(() => {
this.color == 'lightgreen' ? this.color = 'lightcoral' : this.color = 'lightgreen';
if (this.stopIt) {
clearInterval(myDisco);
}
}, 100)
},
stopDisco() {
this.stopIt = true
},
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
<div :style="{color: color}">
<h1>Directives Exercise</h1>
</div>
<button v-my-event:click="change" class="btn btn-primary">Show me!</button>
<button v-my-event:mouseover="disco" v-my-event:mouseleave="stopDisco" class="btn btn-primary">Disco Time!</button>
<p v-if="showing">
Now you see me!
</p>
<p>
{{ stopIt }}, {{ stopItt }}
</p>
</div>
</div>
</div>

Vue.js i cant display fetched data

Im fetching a feed with fetch, but somehow my vue app does not render it i have tried diffrent things but nothing seems to work for me.
<section id="vue-instagram" class="instagram">
<div class="instagram__col" v-for="item in feed">
<div class="instagram__col__picturebox">
<img v-if="item.media_url.indexOf('.mp4') == -1" v-bind:src="item.media_url"/>
<video v-if="item.media_url.indexOf('.mp4') > 0" loop preload muted controls style="width:100%;">
<source v-bind:src="item.media_url" />
</video>
</div>
<div class="instagram__col__description">
<div class="instagram__col__descroption--icon">
<img src="images/insta.png"/>
</div>
<div class="instagram__col__descroption--text">
{{item.caption.substring(0,90)}}...
<div class="hashtags bold-text">
{{item.caption.substring(item.caption.indexOf('#'), item.caption.length).split(' ').slice(0,5).join(' ')}}
</div>
</div>
</div>
</div>
</section>
var app = new Vue({
el: '#vue-instagram',
data:() => ({
loading: false,
feed: [],
}),
}, created: async () => {
var response = await fetch("URL_TOSERVER", {
method: "POST",
});
var {data} = await response.json();
this.feed = data;
console.log(data);
});
If I call this.feed in chrome it displays the data but if I drill into app.data its empty.
The solution was to extract the call as a method
new Vue({
el: '#vue-instagram',
data: {
loading: false,
feed: [],
},
created: function() {
this.fetchData();
},
methods: {
fetchData: function(){
var self = this;
fetch("http://727.dk.web81.curanetserver.dk/umbraco/api/instagram/index", {
method:"POST"
}).then(function(response){
return response.json();
}).then(function(data){
self.feed = data.data;
});
}
},
computed: {
posts: function() {
return this.feed;
}
}
});

export default issue with VueJS ES5

I am developing a website, partially in Vue using ES5.
I need to get data from a Vue Child component to be sent back up to the parent, the way explained to me was via using export default {} However I am constantly recieving syntax errors and I am not sure why because from what i see, I am following Mozillas recomendations.
My question component:
var question = Vue.component('question', {
props: {
scenarios: Array,
scenario: Object,
post: Boolean
},
data: function () {
return ({
choice: 0,
counter: 0,
finished: false
});
},
export default {
methods: {
onClickButton: function (event) {
this.$emit('clicked', 'someValue')
},
postResponse: function () {
var formData = new FormData();
formData.append(this.choice);
// POST /someUrl
this.$http.post('Study/PostScenarioChoice', formData).then(response => {
// success callback
}, response => {
// error callback
});
},
activatePost: function () {
if (this.counter < this.scenarios.length) {
this.counter++;
}
else {
this.finished = true;
}
}
}
},
template:
`<div>
<div v-if="this.finished === false" class="row justify-content-center">
<div class="col-lg-6">
<button class="btn btn-light" href="#" v-on:click="this.onClickButton">
<img class="img-fluid" v-bind:src="this.scenarios[this.counter].scenarioLeftImg" />
</button>
</div>
<div class="col-lg-6">
<button class="btn btn-light" href="#" v-on:click="this.onClickButton">
<img class="img-fluid" v-bind:src="this.scenarios[this.counter].scenarioRightImg" />
</button>
</div>
</div>
<finished v-else></finished>
</div >
});
I get the error in the browser console Expected ':' which is on the line export default {
Any assistance will be greatly appreciated.
You have written completely wrong syntax of JavaScript. What you are trying to do here is to put "export default" in the place where object key should go. I will provide correct code here, but I strongly suggest you go and learn the fundamentals of JavaScript including arrays and objects in order to be able to read and write correct and valid JavaScript. Here is some good learning material for beginners:
http://eloquentjavascript.net/
https://maximdenisov.gitbooks.io/you-don-t-know-js/content/
And here is the fixed Vue component:
export default Vue.component("question", {
props: {
scenarios: Array,
scenario: Object,
post: Boolean
},
data: function () {
return ({
choice: 0,
counter: 0,
finished: false
});
},
methods: {
onClickButton: function (event) {
this.$emit("clicked", "someValue");
},
postResponse: function () {
var formData = new FormData();
formData.append(this.choice);
// POST /someUrl
this.$http.post("Study/PostScenarioChoice", formData).then(response => {
// success callback
}, response => {
// error callback
});
},
activatePost: function () {
if (this.counter < this.scenarios.length) {
this.counter++;
}
else {
this.finished = true;
}
}
},
template:
`<div>
<div v-if="this.finished === false" class="row justify-content-center">
<div class="col-lg-6">
<button class="btn btn-light" href="#" v-on:click="this.onClickButton">
<img class="img-fluid" v-bind:src="this.scenarios[this.counter].scenarioLeftImg" />
</button>
</div>
<div class="col-lg-6">
<button class="btn btn-light" href="#" v-on:click="this.onClickButton">
<img class="img-fluid" v-bind:src="this.scenarios[this.counter].scenarioRightImg" />
</button>
</div>
</div>
<finished v-else></finished>
</div>`
});
The actual answer was a simple misunderstanding of the information presented here. The use of export default was irrelevant in my implementation however this was not easily visible until I started noticing the emit posting the parent element later on.
The actual implementation was as follows:
var question = Vue.component('question', {
props: {
scenarios: Array,
scenario: Object,
post: Boolean,
counter: Number
},
data: function () {
return ({
choice: 0,
finished: false
});
},
methods: {
onClickButton: function (event) {
this.$emit('clicked', 'someValue');
},
postResponse: function () {
var formData = new FormData();
formData.append(this.choice);
// POST /someUrl
this.$http.post('Study/PostScenarioChoice', formData).then(response => {
// success callback
}, response => {
// error callback
});
}
},
template:
`<div>
<div v-if="this.finished === false" class="row justify-content-center">
<div class="col-lg-6">
<button class="btn btn-light" href="#" v-on:click="this.onClickButton">
<img class="img-fluid" v-bind:src="this.scenarios[this.counter].scenarioLeftImg" />
</button>
</div>
<div class="col-lg-6">
<button class="btn btn-light" href="#" v-on:click="this.onClickButton">
<img class="img-fluid" v-bind:src="this.scenarios[this.counter].scenarioRightImg" />
</button>
</div>
</div>
<finished v-else></finished>
</div >`
});
The receiving method in the parent element is as follows:
onClickChild: function (value) {
console.log(value) // someValue
this.showTimer = true;
this.countdownTimer();
if (this.counter < this.scenarios.length) {
this.counter++;
}
else {
this.finished = true;
}
}