0

I draw time on a canvas, but when the time changes, it draws it again. I was thinking about erasing the canvas, but I have other things on it.

function startTime() {
  var today = new Date();
  var h = today.getHours();
  var m = today.getMinutes();
  var s = today.getSeconds();

  m = checkTime(m);
  s = checkTime(s);
  ctx.font="20px Arial";
  ctx.fillText(h + ':' + m, 4, 24); 
  var t = setTimeout(startTime, 500);
}

function checkTime(i) {
  if (i < 10) {i = "0" + i};
  return i;
}

Any help? Thanks!

Damon
  • 4,216
  • 2
  • 17
  • 27
Norbetto89
  • 65
  • 7
  • The approach I described [here](http://stackoverflow.com/a/29829625/285915) might work for this. – mrmcgreg Nov 25 '16 at 15:05
  • Just redraw everything, canvas API is fast. If you've got some slow things to render that aren't updated frequently, then draw these things on an offscreen canvas and call drawImage(canvas, 0,0) – Kaiido Nov 25 '16 at 15:15

3 Answers3

0

No need to wipe the entire canvas clean, instead use clearRect() to clear only the part of the canvas where new time is to be drawn

context.clearRect(x,y,width,height);

ctx.clearRect(4,24,100,50); // clear old time
ctx.font="20px Arial";
ctx.fillText(h + ':' + m, 4, 24);  //draw new time
Vinay
  • 7,442
  • 6
  • 25
  • 48
  • The second parameter to clearRect needs to be 4 or less. The text was drawn at y of 24 but that defines the bottom of the text, not the top. – Jon Nov 25 '16 at 15:02
  • Adjust values as per the need – Vinay Nov 25 '16 at 15:12
0

Here's how you can modify your code a bit. Note, you are never actually redrawing anything, simply drawing a number on top of another one. You will notice if you let your code run, the numbers stack on top of each other.

If you use clearRect you can redraw a part of the canvas defined by the desired pixel dimensions. Run this example snippet and you will see, only the time gets repainted (otherwise the rectangles would disappear)

var ctx = document.getElementById('time').getContext('2d');
ctx.rect(0, 75, 25, 25)
ctx.rect(75, 0, 25, 25)
ctx.rect(75, 75, 25, 25)
ctx.stroke()

function startTime() {
  var today = new Date();
  var h = today.getHours();
  var m = today.getMinutes();
  var s = today.getSeconds();

  m = checkTime(m);
  s = checkTime(s);
  ctx.clearRect(0, 0, 50, 30); // <- point of interest
  ctx.font="20px Arial";
  ctx.fillText(h + ':' + m, 4, 24); 
  var t = setTimeout(startTime, 500);
}

function checkTime(i) {
  if (i < 10) {
    i = "0" + i;
  }
  return i;
}

startTime()
<canvas id='time' width="100" height="100"></canvas>
Damon
  • 4,216
  • 2
  • 17
  • 27
0

Use clearRect to clear only part of the canvas. In the below example I have used measureText to get the exact width of the text that is displayed. I have hard-coded the height of the area cleared, it is possible to get the height but it is complicated.

N.B. I have also added seconds to the display just to get feedback quicker.

var canvas = document.getElementsByTagName('canvas')[0];
var ctx = canvas.getContext('2d');
var previousTextMetrics = null;

startTime();

function startTime() {
  //clear the previously displayed text
  if (previousTextMetrics) {
    ctx.clearRect(4, 4, previousTextMetrics.width, 20);
  }

  var today = new Date();
  var h = today.getHours();
  var m = today.getMinutes();
  var s = today.getSeconds();
  m = checkTime(m);
  s = checkTime(s);
  ctx.font = "20px Arial";
  var text = h + ':' + m + ':' + s;
  ctx.fillText(text, 4, 24);
  //read metrics, including the width of the text
  previousTextMetrics = ctx.measureText(text);

  var t = setTimeout(startTime, 500);
}

function checkTime(i) {
  if (i < 10) {
    i = "0" + i
  };
  return i;
}
<canvas></canvas>
Community
  • 1
  • 1
Jon
  • 361
  • 3
  • 10