1

I've organized my jCanvas code into a render method which fires on window.resize:

<script type="text/javascript">
    var middleX;
    var middleY;
    var canvas;
    var ctx;

    var isLoaded = false;

    $(document).ready
    (
        function ()
        {
            init();
            isLoaded = true;

            render();

            $("canvas").fadeIn(2000);
        }
    );

    function scaleToWindowDimensions()
    {
        ctx.canvas.width = window.innerWidth;
        ctx.canvas.height = window.innerHeight;

        middleX = $canvas.width() / 2;
        middleY = $canvas.height() / 2;
    }

    function init()
    {
        $canvas = $('canvas');
        ctx = document.getElementById("canvas").getContext("2d");

        scaleToWindowDimensions();
    }

    $(window).resize
    (
        function ()
        {
            scaleToWindowDimensions();

            render();
        }
    );

    function render()
    {
        if (!isLoaded)
        {
            return;
        }

        $canvas.clearCanvas();

        // ctx.clearRect(0, 0, $canvas.width(), $canvas.height());

        $canvas.addLayer({
            method: 'drawArc',
            strokeStyle: "#000",
            strokeWidth: 1,
            fillStyle: '#c33',
            x: middleX,
            y: middleY,
            closed: true,
            radius: 50,
            // Event bindings
            mousedown: function (target)
            {
                alert('You pushed RED!');
            },
            mouseup: function (target)
            {
                target.fillStyle = '#c33';
            },
            mouseover: function (target)
            {
                target.fillStyle = "#888";
            },
            mouseout: function (target)
            {
                target.fillStyle = "#c33";
            }
        });

        $canvas.addLayer({
            method: "drawText",
            strokeStyle: "#000",
            fromCenter: true,
            strokeWidth: 1,
            fillStyle: "#333",
            fontSize: "18pt",
            fontFamily: "Verdana",
            x: middleX,
            y: middleY,
            text: "Man",
            data: { "id": 1, "word": "Man" },
            mousedown: function (target)
            {
                alert($(this).id);
            }
        });

        $canvas.addLayer({
            method: 'drawArc',
            strokeStyle: "#000",
            strokeWidth: 1,
            fillStyle: '#d88',
            x: 500,
            y: 100,
            closed: true,
            radius: 40,
            // Event bindings
            mousedown: function (target)
            {
                alert('You pushed RED!');
                target.fillStyle = '#333';
            },
            mouseup: function (target)
            {
                target.fillStyle = '#d88';
            },
            mouseover: function (target)
            {
                target.fillStyle = "#888";
            },
            mouseout: function (target)
            {
                target.fillStyle = "#d88";
            }
        });

        $canvas.addLayer({
            method: "drawText",
            strokeStyle: "#000",
            fromCenter: true,
            strokeWidth: 1,
            fillStyle: "#333",
            fontSize: "16pt",
            fontFamily: "Verdana",
            x: 500,
            y: 100,
            text: "Men",
            data: { "id": 2, "word": "Men" },
            mousedown: function (target)
            {
                alert($(this).id);
            }
        });

        $canvas.addLayer({
            method: 'drawLine',
            strokeStyle: "#222",
            strokeWidth: 1,
            x1: middleX,
            y1: middleY,
            x2: 500,
            y2: 100,
            radius: 40,
        });

        $canvas.drawLayers();
    }
</script>

This draws this image:

Output

The intent is for the first step when render is called to clear the entire canvas:

$canvas.clearCanvas();

// ctx.clearRect(0, 0, $canvas.width(), $canvas.height());

These are two separate attempts to clear the canvas, neither of which works. Without the canvas being cleared, the result is this:

enter image description here

I have a general idea that this has something to do with the layers rather than drawing directly, but I'm baffled why the canvas is not being cleared...

TIA.

Chris B. Behrens
  • 6,255
  • 8
  • 45
  • 71

1 Answers1

2

clearCanvas is working as intended, the issue here is that you are adding five layers to $canvas on each call to render. So, when drawLayers is called, all the layers added to $canvas are drawn; the five updated ones along with all those layers which were added in previous render calls.

One way to solve this issue would be to only alter the layers in the render method with setLayer, and add them in a method which is called only once, possibly init.

So, init becomes:

function init() {
    $canvas = $('canvas');
    ctx = document.getElementById("canvas").getContext("2d");

    scaleToWindowDimensions();

    console.log($canvas);

    //Adding layers in init
    //and defining all the 
    //static properties which
    //won't change on each render
    $canvas.addLayer({
        name: "l0",                  //Unique name for access
        visible: true,
        method: 'drawArc',
        strokeStyle: "#000",
        strokeWidth: 1,
        fillStyle: '#c33',
        x: middleX,
        y: middleY,
        closed: true,
        radius: 50,
        // Event bindings
        mousedown: function (target) {
            alert('You pushed RED!');
        },
        mouseup: function (target) {
            target.fillStyle = '#c33';
        },
        mouseover: function (target) {
            target.fillStyle = "#888";
        },
        mouseout: function (target) {
            target.fillStyle = "#c33";
        }
    })
        .addLayer({
        name: "l1",                  //Unique name for access               
        visible: true,
        method: "drawText",
        strokeStyle: "#000",
        fromCenter: true,
        strokeWidth: 1,
        fillStyle: "#333",
        fontSize: "18pt",
        fontFamily: "Verdana",
        x: middleX,
        y: middleY,
        text: "Man",
        data: {
            "id": 1,
            "word": "Man"
        },
        mousedown: function (target) {
            alert($(this).id);
        }
    })
        .addLayer({
        name: "l2",                  //Unique name for access
        visible: true,
        method: 'drawArc',
        strokeStyle: "#000",
        strokeWidth: 1,
        fillStyle: '#d88',
        x: 500,
        y: 100,
        closed: true,
        radius: 40,
        // Event bindings
        mousedown: function (target) {
            alert('You pushed RED!');
            target.fillStyle = '#333';
        },
        mouseup: function (target) {
            target.fillStyle = '#d88';
        },
        mouseover: function (target) {
            target.fillStyle = "#888";
        },
        mouseout: function (target) {
            target.fillStyle = "#d88";
        }
    })
        .addLayer({
        name: "l3",                  //Unique name for access
        visible: true,
        method: "drawText",
        strokeStyle: "#000",
        fromCenter: true,
        strokeWidth: 1,
        fillStyle: "#333",
        fontSize: "16pt",
        fontFamily: "Verdana",
        x: 500,
        y: 100,
        text: "Men",
        data: {
            "id": 2,
            "word": "Men"
        },
        mousedown: function (target) {
            alert($(this).id);
        }
    })
        .addLayer({
        name: "l4",                  //Unique name for access
        visible: true,
        method: 'drawLine',
        strokeStyle: "#222",
        strokeWidth: 1,
        x1: middleX,
        y1: middleY,
        x2: 500,
        y2: 100,
        radius: 40,
    });
}

And render becomes:

function render() {
    if (!isLoaded) {
        return;
    }

    $canvas.clearCanvas();

    // ctx.clearRect(0, 0, $canvas.width(), $canvas.height());

    //Here, use setLayer to change
    //properties which are supposed to change
    //with render

    //We use the unique name of each layer
    //set in init to access them.
    $canvas.setLayer("l0", {
        x: middleX,
        y: middleY,
    });

    $canvas.setLayer("l1", {
        x: middleX,
        y: middleY
    });

    //Layer l2 and l3 don't
    //change anything, so they are
    //not changed with render.

    $canvas.setLayer("l4", {
        x1: middleX,
        y1: middleY
    });

    $canvas.drawLayers();
}

Working Example.

Rikonator
  • 1,830
  • 16
  • 27
  • This makes sense...just so I understand the problem theoretically, what is wrong with my expectation that clearCanvas would clear the existing layers? – Chris B. Behrens May 02 '13 at 18:32
  • 1
    `clearCanvas` is essentially used to clear whole or part of the canvas. The layers are simply objects which facilitate a layer behavior, but do not extend the actual canvas beyond what it is - a 'dumb' pixel array. `clearCanvas` clears what *has been drawn* on this 'dumb' pixel array, but not the actual layer objects added. So, any call to `drawLayers` will iterate through all the layer objects, if any have been added, and draw them in order on this pixel array. You can try, in your example, to call `render` once, layers and all, and then `clearCanvas`. – Rikonator May 02 '13 at 18:45