Taylor
Taylor

Reputation: 1253

Why won't my canvas clear

I have a canvas that I draw a rect on that I want to clear from the screen when a condition is met, the condition fires but does not clear the rect from the screen. What am I doing wrong? I should also mention that I redraw the rects a couple times because they are draggable, not sure if that makes a difference. So far I have tried:

this.ctx.clearRect(this.ctx.rect.startX, this.ctx.rect.startY, this.ctx.rect.w, this.ctx.rect.h);

this.ctx.clearRect(0, 0, this.ctx.rect.w, this.ctx.rect.h);

draw rect on double click

dclick: function (e) {
            e.preventDefault();
            this.ctx.rect = {
                startX: 25,
                startY: 100,
                w: (this.canvas.width - 50),
                h: 300,
            }
            this.draw();

HTML

    <div class="cv">
        <canvas  v-on:mousedown="mouseDown" v-on:mousemove="mouseMove" v-on:mouseup="mouseUp" v-on:dblclick="dclick" :id="'cv' + emp.id" class="canvas"  width="150" height="700"></canvas>
        <canvas  class="back" :id="'back' + emp.id"   width="150" height="700"></canvas>
    </div>
</template>

draw:

function () {

            for (let  i = 0; i < this.st; i+=this.ic) {
                this.ctx.beginPath();
                this.ctx.moveTo(0, i);
                this.ctx.lineTo(500, i);
                this.ctx.stroke();
                this.ctx.closePath(); 
                this.ctx.fillStyle = "#222222";
                this.ctx.fillRect(this.ctx.rect.startX, this.ctx.rect.startY, this.ctx.rect.w, this.ctx.rect.h);
                this.drawHandles();
            }
        },

vue watcher to clear rect

this.save();
this.ctx.clearRect(0, 0, canvas.width, canvas.height);
this.draw();'

Pen

Here is a Pen of whats happening. The rect clears but doesn't stay cleared. The box should be draggable vertically and should clear and stayed cleared when the button is clicked. To make the box appear you must double click the canvas. https://codepen.io/tjquinn/pen/BYZQqo

Upvotes: 0

Views: 2919

Answers (2)

Kamal Singh
Kamal Singh

Reputation: 1000

To read about the canvas and the different types of context refer to MDN. We are using 2d context. For more details and available method in CanvasRenderingContext2D, you can visit the link.

Note: When you run the snippet, make sure to scroll down the output, if not visible properly. There is a "Clear" button to erase.

The key point in your code, I have added is

mounted: function() {
    var canvas = document.getElementById("canvasId");
    var ctx = canvas.getContext("2d");
    this.canvas = canvas;
    this.ctx = ctx;
}

new Vue({
  el: '#app',
  data: {
    st: 50,
	ic: 10
  },
  mounted: function() {
    var canvas = document.getElementById("canvasId");
    var ctx = canvas.getContext("2d");
    this.canvas = canvas;
    this.ctx = ctx;
  },
  methods: {
    dclick: function(e) {
      this.ctx.rect = {
        startX: 25,
        startY: 100,
        w: (this.canvas.width - 50),
        h: 300,
      }
      this.draw();
    },
    draw: function() {
      for (let i = 0; i < this.st; i += this.ic) {
        this.ctx.beginPath();
        this.ctx.moveTo(0, i);
        this.ctx.lineTo(500, i);
        this.ctx.stroke();
        this.ctx.closePath();
        this.ctx.fillStyle = "#222222";
        this.ctx.fillRect(this.ctx.rect.startX, this.ctx.rect.startY, this.ctx.rect.w, this.ctx.rect.h);
        //this.drawHandles();
      }
    },
    clear: function() {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }
  }
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
  <div class="cv">
    <canvas style='border:1px solid;' v-on:dblclick="dclick" id="canvasId" class="canvas" width="400" height="200"></canvas>
    <canvas class="back" width="150" height="700" style="border:1px solid red"></canvas>
    <button v-on:click="dclick">
      Draw
    </button>
    <button v-on:click="clear">
      Clear
    </button>
  </div>
  <p style='margin-top: 100px'>-- Spacer--</p>
</div>

You can update all your code as per need based upon the above code snippet. Hope this helps!!

Update: Modified code as per your code pen. Added one flag cleared to redraw control.

<html>
    <head>
        <title>Test</title>
        <script src="vue.min.js"></script>
    </head>
    <body>
        <div id="app">
         The CANVAS DEMO

            <div class="cv">
                <canvas style='border:1px solid;'  v-on:mousedown="mouseDown" v-on:mousemove="mouseMove" v-on:mouseup="mouseUp" @dblclick="dclick" id="rect" class="rect"  width="150" height="700"></canvas>
                <button v-on:click="clear">
            Clear
            </button>
            </div>
        </div>
        <script>
         new Vue({
          el: '#app',
          data: function() {
                return {

                    rect : {},
                    drag : false,
                  closeEnough : 10,
                    st : 0,
                    ic : 0,
                    mouseX : 0,
                    mouseY : 0,
                    dragTL : false,
                    dragBL : false,
                    dragTR : false,
                    dragBR : false,
                    cv2: '',
                    ln: 0,
                cleared: true
                }
            },
            mounted: function () {
                this.getVal(10);
                this.draw();
            },                
            methods: {
               checkCloseEnough: function (p1, p2) {
                    return Math.abs(p1 - p2) < this.closeEnough;
                },
                getVal: function (x) {
                    this.canvas2 = document.getElementById('rect');
                    this.ctx2 = this.canvas2.getContext('2d');
                    this.st = this.canvas2.height;
                    this.ic = (this.st / x);           
                },
                draw: function () {
                        this.ctx2.fillStyle = "#222222";
                        this.ctx2.fillRect(this.ctx2.rect.startX, this.ctx2.rect.startY, this.ctx2.rect.w, this.ctx2.rect.h);
                        this.drawHandles();

                },
                drawHandles: function () {
                    this.drawCircle(this.ctx2.rect.startX + this.ctx2.rect.w/2, this.ctx2.rect.startY, this.closeEnough); //top left corner
                    //drawCircle(rect.startX + rect.w, rect.startY, closeEnough);
                    //drawCircle(rect.startX + rect.w, rect.startY + rect.h, closeEnough);
                    this.drawCircle(this.ctx2.rect.startX + this.ctx2.rect.w/2, this.ctx2.rect.startY + this.ctx2.rect.h, this.closeEnough);
                },
                drawCircle: function (x, y, radius) {
                    this.ctx2.fillStyle = "#FF0000";
                    this.ctx2.beginPath();
                    this.ctx2.arc(x, y, radius, 0, 2 * Math.PI);
                    this.ctx2.closePath();
                    this.ctx2.fill();

                },
                checkCloseEnough: function (p1, p2) {
                    return Math.abs(p1 - p2) < this.closeEnough;
                },
                mouseDown: function (event) {
                    if(this.cleared) return;
                    this.mouseX = event.pageX - this.canvas2.offsetLeft;
                    this.mouseY = event.pageY - this.canvas2.offsetTop;
                      // if there isn't a rect yet
                    if (this.ctx2.rect.w === undefined) {
                        this.ctx2.rect.startX = this.mouseY;
                        this.ctx2.rect.startY = this.mouseX;
                        this.dragBR = true;
                    }
                    if (this.checkCloseEnough(this.mouseX, this.ctx2.rect.startX + this.ctx2.rect.w/2) && this.checkCloseEnough(this.mouseY, this.ctx2.rect.startY)) {
                        this.dragTL = true;

                    }
                    else if (this.checkCloseEnough(this.mouseX, this.ctx2.rect.startX + this.ctx2.rect.w/2) && this.checkCloseEnough(this.mouseY, this.ctx2.rect.startY + this.ctx2.rect.h)) {
                        this.dragBR = true;

                    }
                    else {
                        // handle not resizing
                    }



                    this.ctx2.clearRect(0, 0, this.canvas2.width, this.canvas2.height);
                    this.draw();

                },
                mouseMove: function (event) {
                if(this.cleared) return;
                    this.mouseX = event.pageX - this.canvas2.offsetLeft;
                    this.mouseY = event.pageY - this.canvas2.offsetTop;
                    if (this.dragTL) {
                        //rect.w += rect.startX - mouseX;
                        this.ctx2.rect.h += this.ctx2.rect.startY - this.mouseY;
                        //rect.startX = mouseX;
                        this.ctx2.rect.startY = this.mouseY;
                    }
                    else if (this.dragBR) {
                        //rect.w = Math.abs(rect.startX - mouseX);
                        this.ctx2.rect.h = Math.abs(this.ctx2.rect.startY - this.mouseY);
                    }
                    this.ctx2.clearRect(0, 0, this.canvas2.width, this.canvas2.height);
                    this.draw();
                },
                mouseUp: function () {
                if(this.cleared) return;
                    this.dragTL = false;
                    this.dragTR = false;
                    this.dragBL = false; 
                    this.dragBR = false;
                },

                dclick: function (e) {
                this.cleared = false;
                    console.log("Fires");

                    e.preventDefault();
                    this.ctx2.rect = {
                        startX: 25,
                        startY: 100,
                        w: (this.canvas2.width - 50),
                        h: 300,
                    }
                    this.draw();

                    this. ln = this.lines;
                    this.getVal(10);
                },

                clear: function () {
                this.cleared = true;
                    this.cv2 = 'rect';
                    this.canvas2 = document.getElementById(this.cv2);
                    this.ctx2 = this.canvas2.getContext('2d');
                   console.log(this.ctx2.clearRect(0, 0, this.canvas2.width, this.canvas2.height));
                    console.log("Clear should run");
                },
            }

          })

        </script>
    </body>
</html>

Upvotes: 1

Dayley
Dayley

Reputation: 301

The correct method is:

context.clearRect(0, 0, canvas.width, canvas.height);

Rather than clearing the rectangle, you need to clear the canvas.

Dealing with transformed coordinates If you have modified the transformation matrix (e.g. using scale, rotate, or translate) then context.clearRect(0,0,canvas.width,canvas.height) will likely not clear the entire visible portion of the canvas.

Here is how to do it:

// Store the current transformation matrix
context.save();

// Use the identity matrix while clearing the canvas
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);

// Restore the transform
context.restore();

Hope this helps! ;)

Upvotes: 3

Related Questions