1

我正在测试 Raphael javascript 库,我会遇到一个小问题。我正在画布上绘制四个形状。然后我允许一个对象通过单击成为当前选定的对象。然后我添加一个事件处理程序来监听删除键的按下。这工作正常,但我似乎无法调用函数。下面是说明我的问题的代码。

这是一个代表画布上每个圆圈的类:

var Shape = new Class({
    initialize: function(x, y, color)
    {
        this.shape = paper.circle(x, y, 25);
        this.shape.attr("fill", color);

        this.shape.click(function()
        {
            if(selectedObj == null)
            {
                selectedObj = this;
                selectedObj.attr({'stroke':'orange', 'stroke-width':'5'});
            }
            else if(selectedObj != this)
            {
                selectedObj.attr({'stroke':'orange', 'stroke-width':'0'});
                selectedObj = this;
                selectedObj.attr({'stroke':'orange', 'stroke-width':'5'});
            }
            else if(selectedObj == this)
            {
                selectedObj.attr({'stroke':'orange', 'stroke-width':'0'});
                selectedObj = null;
            }
        });
    },
    deleteThis: function()
    {
        alert("Inside The deleteThis() Function.");
    }
});

这将创建一个形状,单击它时会执行以下操作:

  1. 如果selectedObj为空,则单击的形状将设置为selectedObj并在形状周围绘制一个小的橙色边缘。
  2. 如果selectedObj不是被点击的形状,它会取之前选中对象的小边框,然后将新点击的形状设置为当前选中的项目。
  3. 如果形状是选定的对象,再次单击时,它会取消选择它。

然后我将四个形状推到画布上:

objShapes.push(new Shape(50, 50, "red"));   
objShapes.push(new Shape(250, 50, "blue")); 
objShapes.push(new Shape(50, 250, "yellow"));   
objShapes.push(new Shape(250, 250, "green"));

现在我可以成功选择和取消选择画布上的对象,我需要能够调用所选对象的函数。要触发我正在使用键盘的功能。以下代码是我使用的:

$(document).keydown(function(event)
{
    if(event.keyCode == 46)
    {
        if(selectedObj == null)
        {
            alert("nothing to delete");
        }
        else
        {
            alert("Deleting " + selectedObj.attr('fill') + " Circle.");
            selectedObj.deleteThis();
        }
    }
});

只有部分事件处理程序起作用。当我按下删除键并且没有选择任何内容时,警报窗口告诉我没有选择删除任何内容,但是,当我选择了一个对象并按下删除键时,会出现警报并告诉我我正在删除哪个圆圈但是然后它无法调用该deleteThis()函数。我不明白为什么它会调用.attr()函数而不是deleteThis()函数。

无法调用函数的原因是什么?

4

1 回答 1

1

问题是selectedObj引用内部shape变量,而不是类的对象。您可以使其引用对象本身(参见下面的代码;基本上将对象缓存在一个变量中,通常称为selfor that,然后在闭包内将其用作您要存储的对象)。然后引用形状 doselectedObj.shape而不是 just selectedObj。混淆是由于您的类已命名Shape 并且您有一个名为 的成员变量shape。也许考虑更改这些名称中的一个或另一个以避免这种混淆。

此外,您应该使用带有 javascript 控制台的调试器。如果是这样,您会看到一条错误消息,例如“deleteThis未在对象上定义”之类的内容,这将有助于您追踪这一点。

无论如何,这是具有上述更改的代码:

var Shape = new Class({
    initialize: function(x, y, color)
    {
        // To keep track of the object itself
        var self = this;

        this.shape = paper.circle(x, y, 25);
        this.shape.attr("fill", color);

        this.shape.click(function()
        {
            if(selectedObj == null)
            {
                selectedObj = self; // Assign the object, not the shape
                selectedObj.shape.attr({'stroke':'orange', 'stroke-width':'5'});
            }
            else if(selectedObj != self) // Compare the object, not the shape
            {
                selectedObj.shape.attr({'stroke':'orange', 'stroke-width':'0'});
                selectedObj = this; // Assign the object, not the shape
                selectedObj.shape.attr({'stroke':'orange', 'stroke-width':'5'});
            }
            else if(selectedObj == self) // Compare the object, not the shape
            {
                selectedObj.shape.attr({'stroke':'orange', 'stroke-width':'0'});
                selectedObj = null;
            }
        });
    },
    deleteThis: function()
    {
        alert("Inside The deleteThis() Function.");
    }
});

然后在另一部分进行同样的调整:

$(document).keydown(function(event)
{
    if(event.keyCode == 46)
    {
        if(selectedObj == null)
        {
            alert("nothing to delete");
        }
        else
        {
            alert("Deleting " + selectedObj.shape.attr('fill') + " Circle."); // Reference the shape here
            selectedObj.deleteThis(); // This is the object now
        }
    }
});
于 2012-04-16T23:44:00.117 回答