Drawing onto a canvas with vue.js

后端 未结 3 1751
情深已故
情深已故 2020-12-28 16:08

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

相关标签:
3条回答
  • 2020-12-28 16:19

    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

    0 讨论(0)
  • 2020-12-28 16:20

    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/

    0 讨论(0)
  • 2020-12-28 16:35

    Here's an easy way that works with Vuejs 2:

    1. Add the canvas to you template with a reference attribute:

      ref="myCanvas"

    2. You can then access it anywhere inside your component using

      var canvas = this.$refs.myCanvas

    0 讨论(0)
提交回复
热议问题