0

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

Taylor
  • 1,223
  • 1
  • 15
  • 30
  • Possible duplicate of https://stackoverflow.com/questions/2142535/how-to-clear-the-canvas-for-redrawing – Kamal Singh Feb 12 '18 at 02:42
  • I think the OP just wants to "remove" a single rectangle and not clear the entire canvas. – Ray Toal Feb 12 '18 at 02:43
  • @Taylor what do see happening? – Ray Toal Feb 12 '18 at 02:44
  • @KamalSingh I tried that method it does not work – Taylor Feb 12 '18 at 02:46
  • @RayToal I would like to clear a single rect if possible but will clear the entire thing and redraw it if it easier. Nothing happens that I can see. I have to different canvas layer over each other. What is supposed to happen when the condition is met the first canvas should clear either the rect in question or the entire thing and redraw the bottom. Right now the bottom canvas redraws but does not clear the top canvas – Taylor Feb 12 '18 at 02:46
  • Any error message? – Kamal Singh Feb 12 '18 at 02:47
  • In general you should clear and redraw; that is how canvas is designed to work. It is not like a drawing engine that keeps track of all of your objects and automatically redraws them – Ray Toal Feb 12 '18 at 02:48
  • @KamalSingh no error messages – Taylor Feb 12 '18 at 02:49
  • Can you please write complete code fragment with sequence of steps you are using?And also the browser and its version? – Kamal Singh Feb 12 '18 at 02:50
  • @KamalSingh added what I think is relevant – Taylor Feb 12 '18 at 02:56
  • In my top canvas I draw some lines as well as the rect. Could that be causing problems? Would it be better to layer a third canvas and draw the lines and rects separately? – Taylor Feb 12 '18 at 03:01
  • I am not sure what exactly flow your application has for this. The code fragments do not give clear idea on this. Can you check this blog https://alligator.io/vuejs/vue-html5-canvas/ ? And another code pen at https://codepen.io/getflourish/pen/EyqxYE – Kamal Singh Feb 12 '18 at 03:04
  • @Taylor I have added an answer with code snippet. Hope that helps you in resolving your issue!! – Kamal Singh Feb 12 '18 at 06:42

2 Answers2

3

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

Dayley
  • 166
  • 1
  • 2
  • 13
1

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/vue@2.5.13/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>
Kamal Singh
  • 990
  • 8
  • 13
  • I tried this and no luck. I added a code pen example above that shows what is going on – Taylor Feb 12 '18 at 20:14
  • This didn't work as well, I added a link to a code pen with an example of whats going on – Taylor Feb 13 '18 at 00:27
  • @Taylor the original question seemed that `clearRect` is not working for you. However in your code pen it looks, the problem was because of the logic. The UI was getting redraw when mouse move was detected even after clearing. So, to work around this I updated my answer with `cleared` flag. Refer to the updated section. Hope this helps you!! – Kamal Singh Feb 13 '18 at 03:07
  • Thanks Kamal that was the issue, learned something new. My confusion about clearRect came from the fact that the rect would redraw in the same place even if it was stretched so I thought it must not be working since it was redrawing in the same place. I thought it would have redrawn in the start position if it had cleared. – Taylor Feb 13 '18 at 05:57
  • Welcome!! Glad to know it helped!! – Kamal Singh Feb 13 '18 at 06:07