javascript - Dibujo sobre un lienzo con vue.js
canvas (3)
Aquí hay una manera fácil que funciona con Vuejs 2:
Agrega el lienzo a tu plantilla con un atributo de referencia:
ref="myCanvas"
Luego puede acceder a él desde cualquier lugar dentro de su componente usando
var canvas = this. $ refs.myCanvas
No creo que esto sea necesariamente un problema basado en Vue, pero estoy teniendo algunos problemas.
Me gustaría escribir en el lienzo una variable de Vue. Si elimino vue, mi código inicial funciona bien, sin embargo, si agrego Vue, el lienzo no se inicia realmente.
Aqui esta mi codigo
var canvas = document.getElementById(''canvas'');
var ctx = canvas.getContext(''2d'');
ctx.fillStyle = "black";
ctx.font="20px Georgia";
ctx.fillText("Hello World!",10,50);
var v = new Vue({
el: ''#app'',
data: {
''exampleContent'': ''This is TEXT''
},
watch: {
exampleContent: function(val, oldVal) {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "black";
ctx.font="20px Georgia";
ctx.fillText(this.exampleContent,10,50);
}
}
});
Si comento /* var v = new Vue({ ...
el bit inicial funciona. Si registro el valor de exampleContent
en el observador también funciona. Pero algo sobre el lienzo no funciona.
Demostración para jugar con: http://codepen.io/EightArmsHQ/pen/EgGbgR?editors=1010
Como se detalla en la Respuesta de @Mani, Vue elimina y vuelve a representar el elemento DOM sobre el que se invoca una instancia de Vue.
Si abstraes la actualización de tu lienzo en un method
instancia de Vue, puedes activarlo en el gancho del ciclo de vida mounted
(para obtener el valor inicial de exampleContent
), y volver a invocarlo en tu watch
cuando exampleContent
cambie.
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>
El fragmento de código SO anterior se creó a partir de una versión bifurcada de CodePen de OP
Por favor revise este jsFiddle: https://jsfiddle.net/mani04/r4mbh6nu/
EDIT: actualizado con el texto dinámico: https://jsfiddle.net/mani04/r4mbh6nu/1/
En el ejemplo anterior, puedo escribir en el lienzo y también me aseguro de que el texto de input
entre en el span
tal como cabría esperar, todo ello utilizando Vue.js
Volviendo a su ejemplo, el HTML es:
<div id="app">
<canvas id="canvas" width="800" height="600"></canvas>
<input type="text" v-model="exampleContent" />
<span>{{ exampleContent }}</span>
</div>
Vue.js lee los elementos dentro de #app
y los mantiene como la plantilla para su aplicación Vue . Por lo tanto, Vue.js volverá a representar los elementos de su canvas
, input
y span
cuando construya el DOM.
Durante este proceso, el texto original del lienzo, el que configuró antes de iniciar la aplicación Vue, se pierde.
No hay una forma clara de resolver este problema, aparte de usar una directive
, como en mi ejemplo de jsFiddle. Una directiva Vue te ayuda a capturar el elemento DOM.
En mi ejemplo, defino una directiva Vue llamada insert-message
que uso en el lienzo como v-insert-message
. Esto me permite capturar el elemento DOM y luego hacer los otros pasos: getContext
y fillText
. No se requiere id
, o no hay código javascript para getElementById
.
Una cosa más: su lienzo es demasiado grande y, por lo tanto, no pudo ver sus elementos de input
y de span
. ¡Estaban trabajando normalmente en tu ejemplo también!
EDITAR: ejemplo para encuadernaciones directivas
Acabo de encontrar una manera de usar directivas y aún escribir cosas dinámicas en el lienzo.
Compruebe el jsFiddle actualizado: https://jsfiddle.net/mani04/r4mbh6nu/1/