Ответ 1
Примечание. Для перетаскивания и изменения размера вам придется делать отдельные случаи для некоторых разных типов элементов. Посмотрите пример, который я предоставляю позже, который обрабатывает перетаскивание как эллипсов, так и прямоугольников в одном наборе функций.
Чтобы создать элемент, можно использовать:
element.drag(move, start, up);
Три аргумента - это ссылки на функции, которые обрабатывают перемещение (перетаскивание), запуск (мышь вниз) и остановку (mouseup).
Например, чтобы сделать перетаскиваемый круг (из документации):
window.onload = function() {
var R = Raphael("canvas", 500, 500);
var c = R.circle(100, 100, 50).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5
});
var start = function () {
// storing original coordinates
this.ox = this.attr("cx");
this.oy = this.attr("cy");
this.attr({opacity: 1});
},
move = function (dx, dy) {
// move will be called with dx and dy
this.attr({cx: this.ox + dx, cy: this.oy + dy});
},
up = function () {
// restoring state
this.attr({opacity: .5});
};
c.drag(move, start, up);
};
Пример jsFiddle
В приведенном выше примере свойства ox
и oy
привязаны к элементу, чтобы отслеживать его местоположение, и эти свойства в сочетании с dx
и dy
используются для изменения местоположения элемент при его перетаскивании.
Более сложное перетаскивание, чтобы ответить этот вопрос.
Чтобы сделать объект изменчивым, вы просто создадите второй набор методов перетаскивания для resizer и просто настройте целевые элементы height
и width
на основе перетаскивания resizer.
Здесь вы найдете полный перетаскиваемый и изменяемый размер ящик:
Пример jsFiddle окна перетаскивания и изменения размера
window.onload = function() {
var R = Raphael("canvas", 500, 500),
c = R.rect(100, 100, 100, 100).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5,
cursor: "move"
}),
s = R.rect(180, 180, 20, 20).attr({
fill: "hsb(.8, .5, .5)",
stroke: "none",
opacity: .5
}),
// start, move, and up are the drag functions
start = function () {
// storing original coordinates
this.ox = this.attr("x");
this.oy = this.attr("y");
this.attr({opacity: 1});
this.sizer.ox = this.sizer.attr("x");
this.sizer.oy = this.sizer.attr("y");
this.sizer.attr({opacity: 1});
},
move = function (dx, dy) {
// move will be called with dx and dy
this.attr({x: this.ox + dx, y: this.oy + dy});
this.sizer.attr({x: this.sizer.ox + dx, y: this.sizer.oy + dy});
},
up = function () {
// restoring state
this.attr({opacity: .5});
this.sizer.attr({opacity: .5});
},
rstart = function () {
// storing original coordinates
this.ox = this.attr("x");
this.oy = this.attr("y");
this.box.ow = this.box.attr("width");
this.box.oh = this.box.attr("height");
},
rmove = function (dx, dy) {
// move will be called with dx and dy
this.attr({x: this.ox + dx, y: this.oy + dy});
this.box.attr({width: this.box.ow + dx, height: this.box.oh + dy});
};
// rstart and rmove are the resize functions;
c.drag(move, start, up);
c.sizer = s;
s.drag(rmove, rstart);
s.box = c;
};
Включенные обработчики событий (вы можете использовать больше, конечно, в сочетании с .node()
) и описание перетаскивания находится в нижней части страницы в документации.
Вы просто сделали бы один холст Рафаэля, и тогда каждый элемент был бы другим элементом. Просто назначьте их переменным, чтобы вы могли их обрабатывать, как в приведенном выше примере (c
использовался для ссылки на созданный элемент окружения).
В ответ на комментарии здесь можно просто перетащить и изменить размер круга. Фокус в том, что круги используют атрибуты cx
и cy
для позиционирования и r
для размера. Механика почти такая же... эллипс будет немного усложняться, но опять же это вопрос работы с правильными атрибутами.
jsFiddle пример перетаскивания и масштабируемого круга
window.onload = function() {
var R = Raphael("canvas", 500, 500),
c = R.circle(100, 100, 50).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5
}),
s = R.circle(125, 125, 15).attr({
fill: "hsb(.8, .5, .5)",
stroke: "none",
opacity: .5
});
var start = function () {
// storing original coordinates
this.ox = this.attr("cx");
this.oy = this.attr("cy");
this.sizer.ox = this.sizer.attr("cx");
this.sizer.oy = this.sizer.attr("cy")
this.attr({opacity: 1});
this.sizer.attr({opacity: 1});
},
move = function (dx, dy) {
// move will be called with dx and dy
this.attr({cx: this.ox + dx, cy: this.oy + dy});
this.sizer.attr({cx: this.sizer.ox + dx, cy: this.sizer.oy + dy});
},
up = function () {
// restoring state
this.attr({opacity: .5});
this.sizer.attr({opacity: .5});
},
rstart = function() {
// storing original coordinates
this.ox = this.attr("cx");
this.oy = this.attr("cy");
this.big.or = this.big.attr("r");
},
rmove = function (dx, dy) {
// move will be called with dx and dy
this.attr({cx: this.ox + dy, cy: this.oy + dy});
this.big.attr({r: this.big.or + Math.sqrt(2*dy*dy)});
};
c.drag(move, start, up);
c.sizer = s;
s.drag(rmove, rstart);
s.big = c;
};