这是我的第一个Stack Overflow问题,因为我通常在谷歌搜索时找到答案,所以请耐心等待......
我正在处理一个涉及对canvas元素进行大量操作的项目。为此,我导入并使用了jQuery和jCanvas。我也在ECMAScript 6中编写代码。为了更简单的记录方法,我使用了loglevel(因此" log.debug"和" log.info"等等,而不是"的console.log"。)
目前,我的问题是事件处理程序与我用于存储每个画布的数据的对象有一些奇怪的交互。基本上,在我的mousedown和mousemove处理程序中,我使用getCanvasData函数来检索该特定画布的数据对象,我显然已成功检索该数据对象,但是当我访问"拖动"参数,它总是为空。在代码的其他部分,我成功地将该值更改为对象,但只要事件处理程序访问它,无论如何它仍然为null。我已经通过为属性创建getter和setter来测试它是否真的为null,因为它在更改时打印出它的状态(我在最后提供了代码片段,它是'数据&#的替代品39;在getCanvasData函数中赋值。)
如果您希望查看当前表单中的完整代码,可以view my project where I'm currently hosting it。它是一个实时版本,这意味着它与我的工作环境同步。当我在家里修改一些东西时,它会更新网站(所以如果你来自未来 - 它可能会失败或完全不同)。
在网站上,移动处理程序应该负责在生成一个导线/连接器时移动一端(通过单击其中一个输入或输出)。由于处理程序无法检索'拖动',因此线路永远不会跟随鼠标。但是,当您单击另一个输入/输出时(请记住,输入仅连接到输出,反之亦然),它将连接它们之间的连线 - 该操作通过访问“拖动”来执行。属性('拖动'是对电线本身的引用)并对其执行操作。由于您可以连接电线,因此意味着“拖动”电线。在处理程序之外成功引用,但不在其中。
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;
}
};
当上面的代码生效时,我会打印出来告诉我“拖动”#39;更改为“对象对象”,但是当我移动鼠标(触发鼠标移动事件)时,我得到一个打印输出告诉我它的“空”&#39; (甚至没有定义)。当我项目的其他部分使用它时,它会成功使用它并实际检索对象。
答案 0 :(得分:0)
您应该使用if (canvas[0] === tmp.canvas[0])
来引用实际的canvas对象,而不是传递给getCanvasData()
的jQuery选择器。
当您检查if (canvas === tmp.canvas)
时,您正在检查jQuery选择器,不而不是实际的画布对象。因此,在一个地方,您可能会传递$("canvas#foo")
以及您正在传递$("canvas .foo")
的其他地方,这些地方有不同的背景,并且彼此之间相互胜利。