Shawn Javadi Shawn Javadi - 17 days ago 7
Javascript Question

How to get vue template to run before script?

I'm setting up a ascii camera using vue, I've come across this problem while trying to access the canvas from template. in

bootCanvas()
when I try to access the canvas using
this.context = this.$ref.canvas.getContext('2d')
I get an error saying
"Cannot read property 'canvas' of undefined"
even though I've declared it in the template

I'm 90% sure that the cause of the error is that the script is running before the template, but I'm very new to vue so I might be missing out something very obvious here and this might not be the problem at all

my code is as follows :

<template>
<div v-if="error === null">
<p v-if = "stream === null">
Please allow acces to your camera when prompted
</p>
<p v-else>
<video class="video" v-bind:src="stream" ref:video autoplay></video>
<canvas class="canvas" ref:canvas ></canvas>
</p>
</div>
<div v-else>
{{ error }}
</div>
</template>

<script>
export default {
data () {
return {
//where out errors will be held
error: null,
//where our stream will be held
stream: null,
//for html canvas
context: null,
//ascii options
ascii: {
contrast: 30,
fps: 30
}
}
},
methods: {
//access webcam
initVideo () {
navigator.getUserMedia({
//we want video but not audio
video: true,
audio: false
}, (stream) => {
//get the webcam stream
this.stream = window.URL.createObjectURL(stream)

this.bootCanvas().then(() => {
this.startAsciiRendering()
})
//throw error if failed
}, this.setError)
},
startAsciiRendering () {
setInterval(() => {
alert('run')
// console.log('run')
}, Math.round(1000 / this.ascii.fps))
},
bootCanvas () {
return new Promise((resolve, reject) => {
this.context = this.$ref.canvas.getContext('2d')
//video dimensions
this.$refs.canvas.width = 200
this.$refs.canvas.height = 150
})

resolve()
},
//errors
setUnsupported () {
this.error = 'Your browser does not support video :(';
},
setError () {
this.error = 'Something went wrong, try refreshing the page';
}
},
//mounted = when page loads
mounted () {
//check if able to get webcam
if (navigator.getUserMedia) {
this.initVideo()
} else {
this.setUnsupported()
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="sass">
html, body
width: 100%
height: 100%
margin: 0
padding: 0

.video
width: 200px
position: fixed
top: 0
left: 0
z-index: 1
</style>

Answer

v-else was preventing element from rendering.

Comments