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