Как предполагает Амадан, обычно хорошей идеей является создание функций, когда несколько вещей имеют одинаковые (начальные) атрибуты / свойства.Это действительно ответ на ваш первый вопрос.Что касается второго вопроса, это немного сложнее.
Когда вращается объект Рафея, то же самое происходит и с координатной плоскостью.По некоторым причинам, Дмитрий и несколько других источников в Интернете, похоже, согласны с тем, что это правильный способ его реализации.Я, как и ты, не согласен.Мне не удалось найти хорошее решение, но я сумел создать обходной путь.Я кратко объясню, а затем покажу код.
- Создайте пользовательский атрибут для хранения текущего состояния вращения
- В зависимости от этого атрибута вы решаете, как обрабатывать перемещение.
При условии, что вы будете поворачивать фигуры только на 90 градусов (если это не станет намного сложнее), вы можете определить, как следует манипулировать координатами.
var R = Raphael("paper", "100%", "100%");
//create the custom attribute which will hold the current rotation of the object {0,1,2,3}
R.customAttributes.rotPos = function (num) {
this.node.rotPos = num;
};
var shape1 = insert_rect(R, 100, 100, 100, 50, { fill: "red", stroke: "none" });
var shape2 = insert_rect(R, 200, 200, 100, 50, { fill: "green", stroke: "none" });
var shape3 = insert_rect(R, 300, 300, 100, 50, { fill: "blue", stroke: "none" });
var shape4 = insert_rect(R, 400, 400, 100, 50, { fill: "black", stroke: "none" });
//Generic insert rectangle function
function insert_rect(paper,x,y, w, h, attr) {
var angle = 0;
var rect = paper.rect(x, y, w, h);
rect.attr(attr);
//on createion of the object set the rotation position to be 0
rect.attr({rotPos: 0});
rect.drag(drag_move(), drag_start, drag_up);
//Each time you dbl click the shape, it gets rotated. So increment its rotated state (looping round 4)
rect.dblclick(function(){
var pos = this.attr("rotPos");
(pos++)%4;
this.attr({rotPos: pos});
angle -= 90;
rect.stop().animate({transform: "r" + angle}, 1000, "<>");
});
return rect;
}
//ELEMENT/SET Dragger functions.
function drag_start(e) {
this.ox = this.attr("x");
this.oy = this.attr("y");
};
//Now here is the complicated bit
function drag_move() {
return function(dx, dy) {
//default position, treat drag and drop as normal
if (this.attr("rotPos") == 0) {
this.attr({x: this.ox + dx, y: this.oy + dy});
}
//The shape has now been rotated -90
else if (this.attr("rotPos") == 1) {
this.attr({x:this.ox-dy, y:this.oy + dx});
}
else if (this.attr("rotPos") == 2) {
this.attr({x: this.ox - dx, y: this.oy - dy});
}
else if (this.attr("rotPos") == 3) {
this.attr({x:this.ox+dy, y:this.oy - dx});
}
}
};
function drag_up(e) {
}
Я не могу придумать ясного краткого способа объяснить, как работает drag_move.Я думаю, что лучше всего посмотреть код и посмотреть, как он работает.По сути, вам просто нужно понять, как переменные x и y теперь обрабатываются из этого нового повернутого состояния.Без меня, рисующего много графики, я не уверен, что смог бы быть достаточно ясным.(Я много поворачивал голову в сторону, чтобы понять, что делать).
У этого метода есть несколько недостатков:
- Он работает только на 90 градусовповороты (для выполнения 45 градусов потребовалось бы больше вычислений, не обращая внимания на какой-либо заданный градус)
- При начале перетаскивания после поворота наблюдается небольшое движение.Это связано с тем, что перетаскивание принимает старые значения x и y, которые были повернуты.Это не большая проблема для такого размера фигуры, но большие фигуры вы действительно начнете замечать, как фигуры прыгают по холсту.
Я предполагаю, что причиной использования трансформации является то, чтоВы можете анимировать вращение.Если в этом нет необходимости, вы можете использовать функцию .rotate()
, которая всегда вращается вокруг центра элемента и, таким образом, устранит второй упомянутый мной недостаток.
Это не полное решение, но онодолжно определенно заставить вас идти по правильному пути.Мне было бы интересно увидеть полную рабочую версию.
Я также создал эту версию на jsfiddle, которую вы можете посмотреть здесь: http://jsfiddle.net/QRZMS/3/
Удачи.