I don\'t think this is necessarily a Vue based issue, but I\'m running into some trouble.
I\'d like to write to the canvas a Vue variable. If I remove vue, my initia
As detailed in @Mani's Answer, Vue removes and re-renders the DOM element that a Vue instance is invoked upon.
If you abstract your canvas updating into a Vue instance method
, you can trigger it at the mounted
lifecycle hook (to get the initial value of exampleContent
), the re-invoke it in your watch
when exampleContent
changes.
var v = new Vue({
el: '#app',
data: {
'exampleContent': 'This is TEXT'
},
methods: {
updateCanvas: function (){
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "black";
ctx.font="20px Georgia";
ctx.fillText(this.exampleContent,10,50);
}
},
watch: {
exampleContent: function(val, oldVal) {
this.updateCanvas();
}
},
mounted: function (){
this.updateCanvas();
}
});
canvas{
background:red;
width:800px;
height:600px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.1/vue.min.js"></script>
<div id="app">
<canvas id="canvas" width="800" height="600"></canvas>
<input type="text" v-model="exampleContent" />
<span>{{ exampleContent }}</span>
</div>
The preceding SO Code Snippet was created from forked version of OP's CodePen
Please check this jsFiddle: https://jsfiddle.net/mani04/r4mbh6nu/
EDIT: updated with dynamic text: https://jsfiddle.net/mani04/r4mbh6nu/1/
In the above example, I am able to write into canvas, and also ensure that the input
text goes into span
as you would expect, all using Vue.js
Coming back to your example, the HTML is:
<div id="app">
<canvas id="canvas" width="800" height="600"></canvas>
<input type="text" v-model="exampleContent" />
<span>{{ exampleContent }}</span>
</div>
Vue.js reads the elements inside #app
and keeps it as the template for your Vue app. So your canvas
, input
and span
elements will now be re-rendered by Vue.js when it constructs the DOM.
During this process, your original canvas text - the one you set before initiating the Vue application gets lost.
There is no clear way to solve this issue other than using a directive
, as in my jsFiddle example. A Vue directive helps you capture the DOM element.
In my example, I define a Vue directive called insert-message
which I use on canvas as v-insert-message
. This allows me to capture the DOM element and then do the other steps: getContext
and fillText
. There is no id
required, or no javascript code to getElementById
.
One more thing - your canvas is just too large, and therefore you were not able to see your input
and span
elements. They were working normally in your example also!
EDIT: example for directive bindings
I just found a way to use directives and still write dynamic stuff into canvas.
Check the updated jsFiddle: https://jsfiddle.net/mani04/r4mbh6nu/1/
Here's an easy way that works with Vuejs 2:
Add the canvas to you template with a reference attribute:
ref="myCanvas"
You can then access it anywhere inside your component using
var canvas = this.$refs.myCanvas