使用vue.js绘制到画布上

时间:2016-10-21 13:08:11

标签: javascript canvas vue.js

我认为这不一定是基于Vue的问题,但我遇到了一些麻烦。

我想在画布上写一个Vue变量。如果我删除了vue,我的初始代码工作正常,但是如果我添加Vue,画布实际上并没有启动。

这是我的代码

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);
    }
  }
});

如果我评论/* var v = new Vue({ ...,则初始位有效。如果我在观察者中记录exampleContent的值也可以。但是关于画布的一些东西不起作用。

演示: http://codepen.io/EightArmsHQ/pen/EgGbgR?editors=1010

3 个答案:

答案 0 :(得分:15)

请检查此jsFiddle:https://jsfiddle.net/mani04/r4mbh6nu/

编辑:使用动态文字进行了更新:https://jsfiddle.net/mani04/r4mbh6nu/1/

在上面的示例中,我可以写入画布,并确保input文本按照您的预期进入span,所有这些都使用Vue.js

回到你的例子,HTML是:

<div id="app">
    <canvas id="canvas" width="800" height="600"></canvas>
    <input type="text" v-model="exampleContent" />
    <span>{{ exampleContent }}</span>
</div>

Vue.js读取#app中的元素,并将其保留为 Vue应用的模板。因此,当构建DOM时,Vue.js现在将重新呈现您的canvasinputspan元素。

在此过程中,原始画布文本 - 您在启动Vue应用程序之前设置的文本文本将丢失。

除了使用directive之外,没有明确的方法来解决这个问题,就像在我的jsFiddle示例中一样。 Vue指令可帮助您捕获DOM元素。

在我的示例中,我定义了一个名为insert-message的Vue指令,我在画布上使用v-insert-message。这允许我捕获DOM元素,然后执行其他步骤:getContextfillText。没有id要求,或getElementById没有javascript代码。

还有一件事 - 你的画布太大了,因此你无法看到你的inputspan元素。他们在你的例子中也正常工作!

编辑:指令绑定的示例

我刚刚找到了一种使用指令的方法,并且仍然将动态内容写入画布。

检查更新的jsFiddle:https://jsfiddle.net/mani04/r4mbh6nu/1/

答案 1 :(得分:15)

这是一个适用于Vuejs 2的简单方法:

  1. 使用引用属性将画布添加到模板:

    ref="myCanvas"

  2. 然后,您可以使用

    在组件内的任何位置访问它

    var canvas = this。$ refs.myCanvas

答案 2 :(得分:6)

@Mani's Answer中所述,Vue删除并重新呈现调用Vue实例的DOM元素。

如果将画布更新抽象为Vue实例method,则可以在mounted生命周期挂钩(获取exampleContent的初始值)触发它,重新调用当watch发生变化时,exampleContent会发现它。

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>

前面的SO代码片段是从OP的CodePen

的分叉版本创建的