Axel
Axel

Reputation: 467

HTML Canvas: Two clients writing at the same time

I'm having trouble implementing an online HTML5 Canvas with nodejs as a server between the clients.

One single user can paint alone with no problem, but when another clients comes in, and paints at the same time, the following happens: HTML5 Canvas problem with two clients

Client1 is the (X,Y) position of the mouse of the first client, and Client2 is the (X,Y) position of the second client. So when the second client paints, my program draws a line between the two points.

Here you can browse the client JS code, where the draw function is responsible for painting the data received from the nodejs server:

App.draw = function(x, y, type, color, clear) {

    if(clear != true) {

        App.ctx.strokeStyle = color;

        if (type === "dragstart") {

            App.ctx.beginPath();

    //alert("Me muevo a X: " + x + " e Y: " + y);

            return App.ctx.moveTo(x, y);

        } else if (type === "drag") {

            App.ctx.lineTo(x, y);

            return App.ctx.stroke();

        } else {

            return App.ctx.closePath();
        }

    } else {

        // Store the current transformation matrix
        App.ctx.save();

        // Use the identity matrix while clearing the canvas
        App.ctx.setTransform(1, 0, 0, 1, 0, 0);
        App.ctx.clearRect(0, 0, App.canvas.width, App.canvas.height);

        // Restore the transform
        App.ctx.restore();

    }

};

Upvotes: 2

Views: 1347

Answers (1)

user1693593
user1693593

Reputation:

As you are sharing the same path the path will consist of a mixed set of points including both the clients.

To avoid this you can use one of two techniques:

Solution 1

Complete a single stroke completely each time a new point is received (per client). This will reduce the current path to just that single stroke:

App.ctx.beginPath();
App.ctx.moveTo(oldX, oldY);  /// previous point for this client
App.ctx.lineTo(x, y);
App.ctx.strokeStyle = color;
App.ctx.stroke();

Solution 2

Use two canvases layered on top of each other. Assign one layer per client. This way they are completely independent of each other and you can, if needed, merge them to one if you need to save the result as an image:

HTML:

<div class="wrapper">
    <canvas id="client1" ... ></canvas>
    <canvas id="client2" ... ></canvas>
</div>

CSS:

.wrapper {
    position:relative;
    }
.wrapper > canvas {
    position:absolute;
    left:0;
    top:0;
    }

Then use different context variables assigned to each client. One way can be:

App.ctx = [ctx1, ctx2];

Then in your function use parameter client as an index (ie. 0 or 1 in this case):

App.draw = function(client, x, y, type, color, clear) {

    if(clear != true) {

        App.ctx[client].strokeStyle = color;

        if (type === "dragstart") {

            App.ctx[client].beginPath();

    //alert("Me muevo a X: " + x + " e Y: " + y);

            return App.ctx[client].moveTo(x, y);

        } else if (type === "drag") {

            App.ctx[client].lineTo(x, y);
            App.ctx[client].stroke();     /// this has no return value

            return;

        } else {

            App.ctx[client].closePath();
            return
        }

    } else {

        // Store the current transformation matrix
        App.ctx[client].save();

        // Use the identity matrix while clearing the canvas
        App.ctx[client].setTransform(1, 0, 0, 1, 0, 0);
        App.ctx[client].clearRect(0, 0, App.canvas.width, App.canvas.height);

        // Restore the transform
        App.ctx[client].restore();
    }
};

Hope this helps.

Upvotes: 3

Related Questions