1

这是我的第一个 Stack Overflow 问题,因为我通常会在谷歌上找到答案,所以请耐心等待...

我正在从事一个涉及大量操作画布元素的项目。为此,我导入并使用了 jQuery 和 jCanvas。我也在 E​​CMAScript 6 中编写代码。为了更简单的日志记录方法,我使用了 loglevel(因此是“log.debug”和“log.info”等,而不是“console.log”)。

目前,我的问题是事件处理程序与我用于存储有关每个画布的数据的对象进行了一些奇怪的交互。基本上,在我的 mousedown 和 mousemove 处理程序中,我使用 getCanvasData 函数来检索特定画布的数据对象,我显然成功地检索到了,但是当我访问“拖动”参数时,它始终为空。在代码的其他部分,我成功地将该值更改为一个对象,但是每当事件处理程序访问它时,无论如何它仍然是 null。我已经通过为属性创建一个 getter 和 setter 来测试它是否真的为 null,该属性会在其更改时打印出其状态(我在最后提供了该代码片段,它是 getCanvasData 函数中“数据”赋值的替代品)。

如果您想查看当前形式的完整代码,您可以查看我当前托管的项目。这是一个实时版本,这意味着它与我的工作环境同步。当我在家里修改一些东西时,它会更新网站(所以如果你来自未来 - 它可能已经关闭或完全不同)。

在网站上,移动处理程序应该负责在您生成一个(通过单击输入或输出之一)时移动电线/连接器的一端。由于处理程序无法检索“拖动”,因此电线永远不会跟随鼠标。但是,当您单击另一个输入/输出(请记住,输入仅连接到输出,反之亦然)时,它将在它们之间连接线 - 通过访问“拖动”属性(“拖动”是参考电线本身)并对其执行操作。由于您可以连接电线,这意味着在处理程序外部成功引用了“拖动”,但不在处理程序内部。

getCanvasData() 函数:

var canvasData = []; // (among other declarations)

function getCanvasData(canvas) {
    var data, i, tmp;
    // Retrieve the stored data
    for (i = 0; i < canvasData.length; i++) {
        tmp = canvasData[i];
        if (canvas === tmp.canvas) {
            // We got the data for our canvas!
            data = tmp;
            // We no longer need to go through the rest of the list, let's break out of the loop
            break;
        }
    }
    // Check if we got anything back
    if (!data) {
        // No data for this canvas is stored yet. We need to initialize it!
        log.info("New canvas data set is being created. Index: " + canvasData.length);
        data = {
            canvas: canvas, // The canvas this data belongs to
            gates: [],      // An array of all the logic gates on the canvas
            wires: [],      // An array of all the wires on the canvas
            spawners: [],   // An array of all the spawners on the canvas
            dragged: null,  // Currently dragged wire which should follow our mouse
            gateWidth: GATE_WIDTH,  // Width of all logic gates on this canvas
            gateHeight: GATE_HEIGHT // Height of all logic gates on this canvas
        };
        // Store the data in our storage.
        canvasData.push(data);
    }
    return data;
}

我将不同的处理程序分配给某个类的所有画布的部分代码:

var canvasList = $('.logicExercise'), canvas;

/* some code */

// Initialize each canvas
canvasList.each(function (i, obj) {
    canvas = $(this);
    // Initialize the data stored for the canvas
    getCanvasData(canvas);
    // Draw the UI for the canvas
    drawUI(canvas);
    // Assign mouse handlers (for spawning new wires)
    canvas.mousemove(function(event) {
        mouseMoveHandler(event, canvas);
    });
    canvas.mousedown(function(event) {
        mouseDownHandler(event, canvas);
    });
    // Prevent right-click from firing up the context menu when over the canvas
    canvas.bind('contextmenu', function(e){
        e.preventDefault();
        return false;
    });
});

mousedown 和 mousemove 处理程序:

function mouseMoveHandler(event, canvas) {
    var x = event.pageX - canvas.offset().left,
        y = event.pageY - canvas.offset().top,
        data = getCanvasData(canvas);
    if (data.dragged) {    // <--- ALWAYS NULL, AND THEREFORE FAILS
        if (data.dragged.inputs[0].type) {
            data.dragged.outputs[0].x = x;
            data.dragged.outputs[0].y = y;
            data.dragged.updateCoords();
        } else {
            data.dragged.inputs[0].x = x;
            data.dragged.inputs[0].y = y;
            data.dragged.updateCoords();
        }
    }
}

function mouseDownHandler(event, canvas) {
    var data = getCanvasData(canvas);
    if (event.which === 3) {
        // Right click detected!
        if (data.dragged) {    // <--- ALWAYS NULL, AND THEREFORE FAILS
            // We are dragging something! Right click means we need to remove it.
            data.dragged.remove();
            data.dragged = null;
        }
    }
}

我用来检查“拖动”状态的代码片段:

data = {
    canvas: canvas, // The canvas this data belongs to
    gates: [],      // An array of all the logic gates on the canvas
    wires: [],      // An array of all the wires on the canvas
    spawners: [],   // An array of all the spawners on the canvas
    gateWidth: GATE_WIDTH,  // Width of all logic gates on this canvas
    gateHeight: GATE_HEIGHT,// Height of all logic gates on this canvas
    _dragged: null,
    set dragged(obj) {
        log.info("'dragged' is changing to '" + obj + "'.");
        this._dragged = obj;
    },
    get dragged() {
        log.info("'dragged' is being retrieved when it's '" + this._dragged + "'.");
        return this._dragged;
    }
};

当上面的代码生效时,我得到一个打印输出通知我“拖动”更改为“对象对象”,但是当我移动鼠标(触发 mousemove 事件)时,我得到一个打印输出告诉我它是“空”(不是甚至未定义)。当我的项目的其他部分使用它时,它会成功使用它并实际检索对象。

4

1 回答 1

1

您应该使用if (canvas[0] === tmp.canvas[0])来引用实际的画布对象,而不是传入的 jQuery 选择器getCanvasData()

当您检查时,if (canvas === tmp.canvas)您正在检查 jQuery 选择器,不是实际的画布对象。因此,您可能会在一个地方经过$("canvas#foo"),而您正在经过$("canvas .foo")的其他地方具有不同的上下文并且不会==彼此。

于 2016-02-02T01:39:28.357 回答