2012-01-12 66 views
0

使用Raphael,我希望能夠拖拽包含文本對象的形狀(下面的例子中的一個橢圓形),拖拽形狀或文本。我希望通過設置傳遞給文本元素的drag()方法的函數來委託給關聯的形狀(嘗試使用更多態的方法來訪問this other one)。但是,當調用text.drag(...)時,會導致錯誤「obj.addEventListener不是函數」。在Raphael中委託拖拽函數

我是JavaScript新手,所以我可能犯了一個非常明顯的錯誤,但我無法發現它。我是否在我的授權功能moveTextdragTextupText中誤用了call()?或者這是拉斐爾的事情?任何幫助將不勝感激。

<html> 
<head> 
<title>Raphael delegated drag test</title> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<script src="js/raphael.js" type="text/javascript" charset="utf-8"></script> 
</head> 
<body> 
<script type="text/javascript"> 
window.onload = function initPage() { 
    'use strict'; 
    var paper = Raphael("holder", 640, 480); 
    var shape = paper.ellipse(190,100,30, 20).attr({ 
      fill: "green", 
      stroke: "green", 
      "fill-opacity": 0, 
      "stroke-width": 2, 
      cursor: "move" 
     }); 
    var text = paper.text(190,100,"Ellipse").attr({ 
      fill: "green", 
      stroke: "none", 
      cursor: "move" 
     }); 

    // Associate the shape and text elements with each other 
    shape.text = text; 
    text.shape = shape; 

    // Drag start 
    var dragShape = function() { 
     this.ox = this.attr("cx"); 
     this.oy = this.attr("cy"); 
    } 
    var dragText = function() { 
     dragShape.call(this.shape); 
    } 

    // Drag move 
    var moveShape = function (dx, dy) { 
     this.attr({cx: this.ox + dx, cy: this.oy + dy}); 
     this.text.attr({x: this.ox + dx, y: this.oy + dy}); 
    } 
    var moveText = function (dx,dy) { 
     moveShape.call(this.shape,dx,dy); 
    } 

    // Drag release 
    var upShape = function() { 
    }  
    var upText = function() { 
     upShape.call(this.shape); 
    } 

    shape.drag(moveShape, dragShape, upShape); 
    text.drag(moveText, dragText, upText); 
}; 
</script> 
    <div id="holder"></div> 
</body> 
</html> 

解決方案

正如this answer指出,這個問題從屬性名稱的選擇出現了:

​​

這些更改爲更詳細的名稱(並不太可能發生衝突與拉斐爾)使問題消失,但將它們設置爲data屬性更安全:

// Associate the shape and text elements with each other 
shape.data("enclosedText",text); 
text.data("parentShape",shape); 

// Drag start 
var dragShape = function() { 
    this.ox = this.attr("cx"); 
    this.oy = this.attr("cy"); 
} 
var dragText = function() { 
    dragShape.call(this.data("parentShape")); 
} 

// Drag move 
var moveShape = function (dx, dy) { 
    this.attr({cx: this.ox + dx, cy: this.oy + dy}); 
    this.data("enclosedText").attr({x: this.ox + dx, y: this.oy + dy}); 
} 
var moveText = function (dx,dy) { 
    moveShape.call(this.data("parentShape"),dx,dy); 
} 

回答

3
​​

您正在將屬性添加到R​​aphael對象中。不知道拉斐爾是如何工作的(或者將來會工作的),這是非常危險的,顯然也是導致問題的原因。如果你真的想把它們聯繫起來,我推薦使用Raphaels Element.datahttp://raphaeljs.com/reference.html#Element.data

+0

你會如何使拖動工作的包裝?如果能夠增加Javascript的功能,那麼添加屬性似乎就是一種,我不認爲它是如此明顯是核心問題。我使用的是拉斐爾的固定版本,所以未來的打樣對我來說不是這樣的問題。 – beldaz 2012-01-12 06:22:33

+0

對不起,我的意思是'明顯',因爲'事實證明'。添加這樣的屬性是一個強大的特性,但我強烈建議您不要在除了您自己的代碼或您明確鼓勵的地方進行任何操作。關於拖拉的事情;除了'set'外,Raphael缺乏任何支持。所以這取決於項目需求。一個簡單的解決方案是將橢圓和文本對象注入到閉包中,並將處理程序綁定在內部。缺點是很多對象意味着很多函數/處理程序。另一種方法是使用相互的類名並通過對象進行查找(用作字典/散列表)。 – bennedich 2012-01-12 07:46:20

+0

我可以通過替換您確定爲問題區域的兩行代碼中的屬性名稱來完成所有工作(編輯顯示如下)。所以確實是對的。我會堅持這個方法,並且記住將來會更加註意屬性名稱。你的替代品聽起來對我來說太高級了) – beldaz 2012-01-12 09:06:03