Question

I've created HTML and JavaScript files to display bulletgraphs, using the 'canvas' HTML5 tag. I've tried it in Chrome and it works nicely and changes width along with the size of the browser. I have to have this working in IE8, too, so I've used Excanvas, which is working in all except one way: when I resize the browser I get remnants of the valueIndicator. This only happens on IE8.

I've tried looking round for information on redrawing the canvas but I don't think this is the issue. Can anyone see where I'm going wrong, please?

EDIT I'm keeping the complete code at the bottom, however, following advice I've cut my code down somewhat.

In IE8 it looks like this:

http://dl.dropbox.com/u/6985149/MessedUp.bmp

In Chrome it looks like this:

enter image description here

When I refresh the IE8 page it looks OK again.

Cut-down Bulletgraph.html:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Bulletgraph</title>
        <!--[if IE]><script src="excanvas.js"></script><![endif]-->
    </head>
    <body>
        <canvas id="graph1"></canvas>
        <script src="Scripts.js"></script>
        <script>
            drawGraphs();
            window.onresize=function() { drawGraphs() };

            function drawGraphs() {
                drawBulletGraph(getScreenWidth(),300,1000,350,"graph1");
            }
        </script>
    </body>
</html>

Complete code:

Cut-down Scripts.js:

function drawBulletGraph (cwidth, left, right, loValue, id) {
    var canvas=document.getElementById(id);
    var cheight=30;

    var multiplier=cwidth/(right-left);
    canvas.width=cwidth;
    canvas.height=cheight;

    var valueIndicator=canvas.getContext("2d");
    valueIndicator.lineWidth="1";
    valueIndicator.moveTo((loValue-left)*multiplier,0);
    valueIndicator.lineTo((loValue-left)*multiplier,cheight);
    valueIndicator.fill();
    valueIndicator.stroke();
}

function getScreenWidth () {
    return (window.innerWidth || document.documentElement.clientWidth)/7;
}

Bulletgraph.html:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Bulletgraph</title>
        <!--[if IE]><script src="excanvas.js"></script><![endif]-->
    </head>
    <body>
        <canvas id="graph1"></canvas><br>
        <canvas id="graph2"></canvas>
        <script src="Scripts.js"></script>
        <script>
            drawGraphs();
            window.onresize=function() { drawGraphs() };

            function drawGraphs() {
                drawBulletGraph(bgWidth(getScreenWidth()),300,400,450,600,700,1000,800,350,850,"graph1");
                drawBulletGraph(bgWidth(getScreenWidth()),250,450,500,650,700,1200,600,350,850,"graph2");
            }
        </script>
    </body>
</html>

Scripts.js:

function drawBulletGraph (cwidth, left, loRed, loAmber, hiAmber, hiRed, right, value, loValue, hiValue, id) {
    var canvas=document.getElementById(id);
    var cheight=16;
    var colour="#008000";
    if (value <= loRed || value >= hiRed)
        {
            colour="#FF0000";
        }
    else if (value <= loAmber || value >= hiAmber)
        {
            colour="#FFA500";
        }
    var multiplier=cwidth/(right-left);
    canvas.width=cwidth;
    canvas.height=cheight;
    var red=canvas.getContext("2d");
    red.fillStyle="#F4C3C6";
    red.fillRect(0,0,cwidth,cheight);
    var amber=canvas.getContext("2d");
    amber.fillStyle="#F4F6C6";
    amber.fillRect((loRed-left)*multiplier,0,(hiRed-loRed)*multiplier,cheight);
    var green=canvas.getContext("2d");
    green.fillStyle="#CCE5CC";
    green.fillRect((loAmber-left)*multiplier,0,(hiAmber-loAmber)*multiplier,cheight);
    var valueIndicator=canvas.getContext("2d");
    valueIndicator.fillStyle=colour;
    valueIndicator.strokeStyle=colour;
    valueIndicator.lineWidth="2";
    valueIndicator.moveTo((loValue-left)*multiplier,0);
    valueIndicator.lineTo((loValue-left)*multiplier,cheight);
    valueIndicator.moveTo((loValue-left)*multiplier,cheight/2);
    valueIndicator.lineTo((hiValue-left)*multiplier,cheight/2);
    valueIndicator.moveTo((hiValue-left)*multiplier,0);
    valueIndicator.lineTo((hiValue-left)*multiplier,cheight);
    valueIndicator.moveTo(((value-left)*multiplier)-(cheight/2),cheight/2);
    valueIndicator.stroke();
    valueIndicator.lineWidth="1";
    valueIndicator.lineTo((value-left)*multiplier,cheight);
    valueIndicator.lineTo(((value-left)*multiplier)+(cheight/2),cheight/2);
    valueIndicator.lineTo((value-left)*multiplier,0);
    valueIndicator.lineTo(((value-left)*multiplier)-(cheight/2),cheight/2);
    valueIndicator.fill();
    valueIndicator.stroke();
}

function getScreenWidth () {
    return window.innerWidth || document.documentElement.clientWidth;
}

function bgWidth (screenWidth) {
    var graphWidth=screenWidth/7;
    if (graphWidth<70) {graphWidth=70;}
    if (graphWidth>260) {graphWidth=260;}
    return graphWidth;
}
Was it helpful?

Solution

I've managed to get a solution. It feels like a bit of a hack but it does the trick. Basically it involves drawing a white line round the canvas and filling it each time it's drawn again. The following code goes between the var valueIndicator=canvas.getContext("2d"); and the valueIndicator.lineWidth="1"; lines:

valueIndicator.fillStyle="#FFFFFF";
valueIndicator.strokeStyle="#FFFFFF";
valueIndicator.moveTo(0,0);
valueIndicator.beginPath();
valueIndicator.lineTo(0,cheight);
valueIndicator.lineTo(cwidth,cheight);
valueIndicator.lineTo(cwidth,0);
valueIndicator.closePath();
valueIndicator.fill();
valueIndicator.stroke();
valueIndicator.strokeStyle="#000000";

I've tried it in the full code and it works. If anyone has a more elegant solution, and I'm sure there must be many, I would still love to see them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top