使用Raphael,我希望能够拖拽包含文本对象的形状(下面的例子中的一个椭圆形),拖拽形状或文本。我希望通过设置传递给文本元素的drag()
方法的函数来委托给关联的形状(尝试使用更多态的方法来访问this other one)。但是,当调用text.drag(...)
时,会导致错误“obj.addEventListener不是函数”。在Raphael中委托拖拽函数
我是JavaScript新手,所以我可能犯了一个非常明显的错误,但我无法发现它。我是否在我的授权功能moveText
,dragText
和upText
中误用了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);
}
你会如何使拖动工作的包装?如果能够增加Javascript的功能,那么添加属性似乎就是一种,我不认为它是如此明显是核心问题。我使用的是拉斐尔的固定版本,所以未来的打样对我来说不是这样的问题。 – beldaz 2012-01-12 06:22:33
对不起,我的意思是'明显',因为'事实证明'。添加这样的属性是一个强大的特性,但我强烈建议您不要在除了您自己的代码或您明确鼓励的地方进行任何操作。关于拖拉的事情;除了'set'外,Raphael缺乏任何支持。所以这取决于项目需求。一个简单的解决方案是将椭圆和文本对象注入到闭包中,并将处理程序绑定在内部。缺点是很多对象意味着很多函数/处理程序。另一种方法是使用相互的类名并通过对象进行查找(用作字典/散列表)。 – bennedich 2012-01-12 07:46:20
我可以通过替换您确定为问题区域的两行代码中的属性名称来完成所有工作(编辑显示如下)。所以确实是对的。我会坚持这个方法,并且记住将来会更加注意属性名称。你的替代品听起来对我来说太高级了) – beldaz 2012-01-12 09:06:03