我几乎做了一个多用户的素描本。
我的问题是,由于我一次只能绘制一条线,所以如果有两个或更多用户同时绘制,则该线在鼠标之间跳跃。每个用户如何拥有自己的电话?

这是客户端JS代码。我知道它写得不好,但这是我第一次尝试。

document.addEventListener('DOMContentLoaded', function(event){
    var startMoveX = new Array();
    var startMoveY = new Array();
    var socket = io.connect();
    socket.on('draw',function(data){
       outDraw(data);
    });

    canvas = document.getElementById('myCanvas');
    ctx = canvas.getContext("2d");
    ctx.canvas.width  = window.innerWidth;
    ctx.canvas.height = window.innerHeight;
    var drawing = false;
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)) {
        canvas.addEventListener('touchmove', function(e){
            var mouseX = Math.round(e.targetTouches[0].clientX);
            var mouseY = Math.round(e.targetTouches[0].clientY);
            var status = document.getElementById('status');
            status.innerHTML = mouseX+" | "+mouseY;
            if(drawing) draw(e)
        }, false);
        canvas.addEventListener("touchstart", function (e) {
            moveBol = true;
            drawing = true;
            startMoveX.pop();
            startMoveY.pop();
            startMoveX.push(Math.round(e.targetTouches[0].clientX));
            startMoveY.push(Math.round(e.targetTouches[0].clientY));
            ctx.moveTo(startMoveX[0], startMoveY[0]);
        }, false);
        canvas.addEventListener("touchend", function (e) {drawing = false;}, false);
        canvas.addEventListener("mousecancel", function (e) {drawing = false;}, false);
    } else {
    canvas.addEventListener('mousemove', function(e){
        var mouseX = e.clientX - ctx.canvas.offsetLeft;
        var mouseY = e.clientY - ctx.canvas.offsetTop;
        var status = document.getElementById('status');
        status.innerHTML = mouseX+" | "+mouseY;
        if(drawing) draw(e)
    }, false);
        canvas.addEventListener("mousedown", function (e) {
            drawing = true;
            moveBol = true;
            startMoveX.pop();
            startMoveY.pop();
            startMoveX.push(e.clientX - ctx.canvas.offsetLeft);
            startMoveY.push(e.clientY - ctx.canvas.offsetTop);
            ctx.moveTo(startMoveX[0], startMoveY[0]);

        }, false);
    canvas.addEventListener("mouseup", function (e) {drawing = false;}, false);
    canvas.addEventListener("mouseout", function (e) {drawing = false;}, false);
    }
    function draw(e) {
        if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)) {
            cX = Math.round(e.targetTouches[0].clientX);
            cY = Math.round(e.targetTouches[0].clientY);
        } else {
            cX = e.clientX - canvas.offsetLeft;
            cY = e.clientY - canvas.offsetTop;
        }

        ctx.lineTo(cX, cY);
        ctx.stroke();
        if (moveBol){
            socket.emit('draw',{x:cX,y:cY, preX: startMoveX[0], preY: startMoveY[0]});
            console.log(moveBol);
            moveBol = false;
        } else {
            socket.emit('draw',{x:cX,y:cY});
            console.log(moveBol);
        }
    }
    function outDraw(e) {


        ctx.moveTo(e.preX, e.preY);
        ctx.lineTo(e.x, e.y);
        ctx.stroke();
    }

});

最佳答案

您有两个选择。

每帧一次重画所有当前活动的绘制路径,并以屏幕外的画布为背景。一条线完成后,将该线绘制到背景上。使用requestAnimationFrame更新显示。

要么

仅使用beginPath绘制线段,但您需要保留上一点。

例如

// creates named users that draw to the canvas context ctx
ctx = canvas.getContext("2d"); // I assume canvas is in scope
var users = {  // cant have users that start with _
    _addUser(name){
        if(typeof this[name] === "function"){
            throw new ReferenceError("Can not use the user name '"+name+"'");
        }

        this[name] = {
            lastX : null,
            lastY : null,
            draw(x,y){
                ctx.beginPath();
                ctx.moveTo(this.lastX,this.lastY);
                ctx.lineTo(x,y);
                ctx.stroke();
            },
            addPoint(x,y){
                if(this.lastX !== null){ // new line start
                    this.draw(x,y);
                }
                this.lastX = x;
                this.lastY = y;
            },
            endPoint(x,y){
                if(this.lastX === null){ // incase it is just a point
                    this.lastX = x;
                    this.lastY = y;
                }
                this.draw(x,y);
                this.lastX = null; // end the line
            }
        }
        return this[name];
    }
}

users._createUser("User1");
users._createUser("User2");


然后为任何用户绘制图形,您只需要用户名和点以及行结束的时间即可。

用于鼠标下移和跟随鼠标移动

user = "User1";
// mousemove and mousedown events should call
users[user].addPoint(x,y); // add a point if mouse is down
socket.send(JSON.stringify({user, x, y, type : "add"});


对于mouseup事件

// when the mouseup
users[user].endPoint(x,y);
socket.send(JSON.stringify({user, x, y, type : "end"});


用于获取套接字数据

// if from a socket (should have the user name or id passed with the packet)
// Assuming data is as a JSON string as above
socket.onmessage = function(event){
    var data = JSON.parse(event.data);  // should be wrapped in try catch and security checks

    user = data.user;  //
    if(users[user]){
        if(data.type === "add"){  // add point
            users[user].addPoint(data.x, data.y); // add a point
        }else if(data.type === "end"){
            users[user].endPoint(data.x, data.y);
        }
    }
}

关于javascript - 如何在一个2d Canvas 上下文中一次绘制多条线?多用户画板,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42013911/

10-16 18:35