How to speedup canvas rendering for large number

Viewed 226

I was trying to draw ruler scale on canvas, if i draw huge scale with large number then it is taking more than 15s to render entire scale and browser gets struck

Scale Looks like below: enter image description here

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var cmm =0;
var count = 0
ctx.beginPath();
ctx.translate(200, 0);
for ( i = -33600, j=-336000; i<=46400&& j<=464000; i+=1, j+=10) {
        if (count === 0) { cmm = 0; count++; 
            const scaleVal = i;
          ctx.fillText(scaleVal.toString(), j, cmm+10);
        }
        else if (count === 5) { cmm = 5; count++; }
        else if (count === 9) {cmm = 10; count = 0}
        else { cmm = 10; count++; }
    ctx.moveTo(j , cmm);
ctx.lineTo(j, 15);

}

ctx.stroke(); 

ctx.stroke();
.top-div{
height:800px;
widht:800px;
position: absolute;
border: 1px solid red;
}
#myCanvas{
position:absolute;
top:300px;
}
#parentCanvas {
transform: scale(0.5);
border: 1px solid green;
}
<!DOCTYPE html>
<html>
<body>
<div class="top-div">
<canvas id="parentCanvas"  width="800" height="800"></canvas>
<canvas id="myCanvas" width="8000" height="15" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML canvas tag.</canvas>
</div>


</body>
</html>

HTML5 canvas would be quite fast. I'm used the above code and I would think it would take less time to render but it is taking long time to render.

It's supposed to draw Ruler Scale. But again, it's taking forever to render and would crash most people's browsers. Any hints as to how to speed this up?

2 Answers

A couple more tricks: you can use window.requestAnimationFrame() to avoid unnecessary re-renders. Also, you may want to ensure that whatever it is you're rendering would actually be on-screen.

You are drawing values completely off the canvas. Your canvas is only 800x800, but you are drawing things out in the -46400px - 46400px range. What you need to do is 'cull' out all the values that are not within canvas bounding box and only draw values you see. You will need to look at some linear algebra if you would like to support panning, zooming, ect. But the gist is you need to find the bounding rectangle that you see, and only render content within that. This should make your render time around 1ms.

If you need more performance, you can try more complicated techniques such as instancing. Notice how the scale is a repetitive pattern? You can stroke it once, and copy those pixels over and over again offsetting them each time.

Related