Делегирование функции перетаскивания в Рафаэле
Используя Рафаэля, я хотел бы иметь возможность перетаскивать фигуру (эллипс в примере ниже), содержащий текстовый объект, перетаскивая либо фигуру, либо текст. Я надеялся сделать это, установив функции, передаваемые текстовому элементу drag()
метод делегирования связанной фигуре (пробуя более полиморфный подход к другой). Однако это приводит к ошибке " obj.addEventListener не является функцией ", когда text.drag(...)
называется.
Я новичок в javascript, так что я, вероятно, сделал действительно очевидную ошибку, но я не могу определить это. Я неправильно использовал call()
в моих делегирующих функциях moveText
, dragText
, а также upText
? Или это вещь Рафаэля? Любая помощь будет принята с благодарностью.
<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>
Решение
Как указано в этом ответе, проблема возникает из-за выбора имен атрибутов:
// Associate the shape and text elements with each other
shape.text = text;
text.shape = shape;
Изменение их на более подробные имена (и с меньшей вероятностью конфликтовать с Рафаэлем) устраняет проблему, но безопаснее установить их как 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);
}
1 ответ
// Associate the shape and text elements with each other
shape.text = text;
text.shape = shape;
Вы добавляете атрибуты к объектам Raphael. Не зная, как Рафаэль работает (или будет работать в будущем), это опасно и, очевидно, также является причиной проблемы. Если вы действительно хотите связать их, я рекомендую использовать Raphaels Element.data
: http://raphaeljs.com/reference.html