www.webdeveloper.com
Results 1 to 2 of 2

Thread: Canvas Context Drawing over Text

  1. #1
    Join Date
    Dec 2012
    Posts
    54

    Canvas Context Drawing over Text

    Hi. Thanks for taking time out to read this.

    I am developing a browser based version of a sudoku game I made in C++. I was working on my DrawBoard() function which worked fine, but then when I added the code to draw the value of the individual cell on top of the cell I ran into some problems. The way the code is working is not what I expect it to do, and I'm not exactly sure why.

    So my original code for drawing the board looked like this
    Code:
        this.Draw = function(){
          for(var x = 0; x < 9; x++){
            for(var y = 0; y < 9; y++){
              this.Rows[x][y].Draw();
            }
          }
        }
    So this.Rows[x][y] is a 2d array (an array of arrays) of object type cells that have their own draw method that looked like this

    Code:
        this.Draw = function(){
          var CNV = Get(CANVASID);
          var CTX = CNV.getContext('2d');
          CTX.fillStyle = this.Color;
          CTX.rect(this.Xloc, this.Yloc, this.Size, this.Size);
          CTX.fill();
          CTX.strokeStyle = this.BorderColor;
          CTX.lineWidth = 1;
          CTX.stroke();
          CTX.fillStyle = 'blue';
          CTX.font = "30px Arial";
          CTX.fillText(this.Value, this.Xloc+14, this.Yloc+33);
        }
    For some reason this works if you draw only one cell, but you can see the function Board.Draw() will draw all its cells (all 81) in its loop. My result wasn't as expected each new call to Cell.Draw() Draws over the text of the previously drawn cell. So the ending result is 81 cells but only the last one drawn (bottom right) has an actual value drawn on it.

    I was able to get my desired result by adding a new method into the object Cell() called DrawValue() and defined like this

    Code:
        this.DrawValue = function(){
          var CNV = Get(CANVASID);
          var CTX = CNV.getContext('2d');
          CTX.fillStyle = 'blue';
          CTX.font = "30px Arial";
          CTX.fillText(this.Value, this.Xloc+14, this.Yloc+33);
        }
    Then I changed the definition of the Board.Draw() method too

    Code:
          for(var x = 0; x < 9; x++){
            for(var y = 0; y < 9; y++){
              this.Rows[x][y].Draw();
            }
          }
          for(var x = 0; x < 9; x++){
            for(var y = 0; y < 9; y++){
              this.Rows[x][y].DrawValue();
            }
          }
    So this produces the desired result but breaks the number one rule of programming "Don't repeat yourself" because I have to make two identical loops back to back. I spent a bunch of time on W3 documentation page about the context and canvas but I can't seem to find the reason the first example isn't working. My only guess would be that the CTX (context) is queing all the rect drawings until the end and then drawing them all at once or the actual command CTX.rect(x, y, width, height) is an array of some sort that keeps popping in new values rather than writing over old values. Anyone have any ideas on this?

    Below is a picture of the undesireable result.
    Attached Images Attached Images

  2. #2
    Join Date
    Dec 2012
    Posts
    54
    So my workaround broke again when I started writing mouseover functions for the Cells. I wanted the "active" or mouseover cell to change in color so that the user visibly sees which cell is active, but I only wanted the cell that was active to be redrawn. Redrawing 81 cells for one change is really inefficient, but when I called just one Cell.Draw() function it redrew all cells and applied the color to all cells. This really confused me so I replaced the code:

    Code:
        this.Draw = function(){
          var CNV = Get(CANVASID);
          var CTX = CNV.getContext('2d');
          CTX.fillStyle = this.Color;
          CTX.fillRect(this.Xloc, this.Yloc, this.Size, this.Size);
          //CTX.fill();
          CTX.moveTo(this.Xloc, this.Yloc);
          CTX.lineTo(this.Xloc+this.Size, this.Yloc);
          CTX.lineTo(this.Xloc+this.Size, this.Yloc+this.Size);
          CTX.lineTo(this.Xloc, this.Yloc+this.Size);
          CTX.lineTo(this.Xloc, this.Yloc);
          CTX.strokeStyle = this.BorderColor;
          CTX.lineWidth = 1;
          CTX.stroke();
          CTX.fillStyle = 'blue';
          CTX.font = "30px Arial";
          CTX.fillText(this.Value, this.Xloc+14, this.Yloc+33);
        }
    So I removed the CTX.fill() command and just replaced the CTX.rect(x, y, w, h) with a CTX.fillRect(x, y, w, h). Then I had to manually draw the boarders on the squares and it all worked perfectly. I was able to migrate the drawvalue code back into the Cell.Draw() function and the code that only draw's the cell that changed rather than drawing the whole board works.

    What gives?

    Why does CTX.rect(x, y, w, h) + CTX.fill() break my code when I am drawing more than one rectangle?

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles