Search code examples
javascriptcanvasswitch-statementstate-machine

Using a switch case statement state machine to draw shapes in javascript


I'm trying to modify some getElementById code I found on the internet to write a function that uses a switch/case statement so that I can draw different shapes using the same function. Basically, I want to create a tiny state machine for shape drawing commands. JavaScript is still new to me, so I'm probably missing something glaringly obvious. Cheers!

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset=utf-8 />
    <title>Draw a circle</title>
    <script src="draw_shapes.js"></script>
</head>
<body onload="draw01();">
    <canvas id="circle" width="150" height="150"></canvas>
</body>
</html>

draw_shapes.js

function draw01() {
    var canvas = document.getElementById('circle');
    if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
        var X = canvas.width / 2;
        var Y = canvas.height / 2;
        var R = 45;
        ctx.beginPath();
        ctx.arc(X, Y, R, 0, 2 * Math.PI, false);
        ctx.lineWidth = 3;
        ctx.strokeStyle = '#000000';
        ctx.stroke();

    }
}

function draw02() {
    const canvas = document.getElementById(canvas.id);
    const ctx = canvas.getContext('2d');
    switch (canvas.id) {
        case "circle":
            var X = canvas.width / 2;
            var Y = canvas.height / 2;
            var R = 45;
            ctx.beginPath();
            ctx.arc(X, Y, R, 0, 2 * Math.PI, false);
            ctx.lineWidth = 3;
            ctx.strokeStyle = '#000000';
            ctx.stroke();
            break;
    }
}

Second iteration. Still not quite working right, but I've got the setup more as I was envisioning.

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset=utf-8 />
    <title>Draw a circle</title>
    <script src="draw_shapes_02.js"></script>
</head>
<body onload="draw(CIRCLE);">
</body>
</html>

draw_shapes_02.js

//shape enumeration (an object with constant variables with immutable property values)
const shapes = {
    CIRCLE: "circle",
    RECTANGLE: "rectangle",
    TRIANGLE: "triangle",
    HOUSE: "house",
    DEFAULT:"default",
}

Object.freeze(shapes);

// shape default setting and error
let shape = shapes.DEFAULT;

if (!shape) {
    throw new Error("Shape is not defined");
}

// shape state machine
function draw(shapes) {
    var canvas = document.getElementById("shape");
    var ctx = canvas.getContext('2d');
    switch ("shape") {
        case shapes.CIRCLE:
            ctx.beginPath();
            ctx.fillStyle = "black";
            ctx.arc(150, 60, 50, 0, 2 * Math.PI);
            ctx.closePath();
            ctx.fill();
            break;
        case shapes.RECTANGLE:
            ctx.beginPath();
            ctx.fillStyle = "green";
            ctx.rect(100, 130, 100, 50);
            ctx.fill();
            ctx.closePath();
            break;
        case shapes.TRIANGLE:
            ctx.beginPath();
            ctx.fillStyle = "yellow";
            ctx.moveTo(150, 200);
            ctx.lineTo(200, 250);
            ctx.lineTo(100, 250);
            ctx.lineTo(150, 200);
            ctx.fill();
            ctx.closePath();
            break;
        case shapes.HOUSE:
            ctx.lineWidth = 10;
            ctx.strokeRect(75, 140, 150, 110);
            ctx.fillRect(130, 190, 40, 60);
            ctx.beginPath();
            ctx.moveTo(50, 140);
            ctx.lineTo(150, 60);
            ctx.lineTo(250, 140);
            ctx.closePath();
            ctx.stroke();
            break;
        case shapes.DEFAULT:
            break;
    }
}

Solution

  • I have simplified a bit but you can complicate again as you wish :)

    function draw(shape) {
     
        var canvas = document.getElementById("CIRCLE");
        var ctx = canvas.getContext('2d');
       console.log(shape);
        switch (shape) {
            
            case  "CIRCLE":
                ctx.beginPath();
                ctx.fillStyle = "black";
                ctx.arc(150, 60, 50, 0, 2 * Math.PI);
                ctx.closePath();
                ctx.fill();
                break;
            case "RECTANGLE":
                ctx.beginPath();
                ctx.fillStyle = "green";
                ctx.rect(100, 130, 100, 50);
                ctx.fill();
                ctx.closePath();
                break;
            case "TRIANGLE":
                ctx.beginPath();
                ctx.fillStyle = "yellow";
                ctx.moveTo(150, 200);
                ctx.lineTo(200, 250);
                ctx.lineTo(100, 250);
                ctx.lineTo(150, 200);
                ctx.fill();
                ctx.closePath();
                break;
            case "HOUSE":
                ctx.lineWidth = 10;
                ctx.strokeRect(75, 140, 150, 110);
                ctx.fillRect(130, 190, 40, 60);
                ctx.beginPath();
                ctx.moveTo(50, 140);
                ctx.lineTo(150, 60);
                ctx.lineTo(250, 140);
                ctx.closePath();
                ctx.stroke();
                break;
           default:
                ctx.fillStyle = "#FF0000";
                ctx.fillRect(0,0,150,75);
                break;
        }
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset=utf-8 />
        <title>Draw a circle</title>
     </head>
    <body onload="draw('HOUSE');">
     <canvas width="240" height="297" style="border:1px solid #d3d3d3;" id="CIRCLE"></canvas>
    </body>
    </html>