很抱歉这是一个很长的问题。我想在这里修改demo的拖动形状:
http://raphaeljs.com/graffle.html
该演示工作正常。我想要做的是将单词放在形状中,并将形状和文本作为复合单个对象移动。
以下是创建对象的代码:
window.onload = function () {
var dragger = function () {
this.ox = this.type == "rect" ? this.attr("x") : this.attr("cx");
this.oy = this.type == "rect" ? this.attr("y") : this.attr("cy");
this.animate({"fill-opacity": .2}, 500);
},
move = function (dx, dy) {
var att = this.type == "rect" ? {x: this.ox + dx, y: this.oy + dy} : {cx: this.ox + dx, cy: this.oy + dy};
this.attr(att);
for (var i = connections.length; i--;) {
r.connection(connections[i]);
}
r.safari();
},
up = function () {
this.animate({"fill-opacity": 0}, 500);
},
r = Raphael("holder", 640, 480),
connections = [],
shapes = [ r.ellipse(190, 100, 30, 20),
r.rect(290, 80, 60, 40, 10),
r.rect(290, 180, 60, 40, 2),
r.ellipse(450, 100, 20, 20)
];
for (var i = 0, ii = shapes.length; i < ii; i++) {
var color = Raphael.getColor();
shapes[i].attr({fill: color, stroke: color, "fill-opacity": 0, "stroke-width": 2, cursor: "move"});
shapes[i].drag(move, dragger, up);
}
connections.push(r.connection(shapes[0], shapes[1], "#fff"));
connections.push(r.connection(shapes[1], shapes[2], "#fff", "#fff|5"));
connections.push(r.connection(shapes[1], shapes[3], "#000", "#fff"));
};
我试过这样的事情:
myWords = [ r.text(190, 100, "Hello"),
r.text(480,100, "Good Bye")
];
并在其他地方进行调整,以便它可以工作,但它只是移动文本和形状,但形状和文本从未被视为一个整体。我可以将文本与形状分开移动,反之亦然。我需要他们成为一个对象。所以他们一起移动我怎样才能做到这一点?谢谢你的帮助。
编辑:
我试过了:
st.push(r.text (190, 100, "node1"), r.ellipse(190, 100, 30, 20)),
st.push(r.text (290, 80, "Center"), r.rect(290, 80, 60, 40, 10)),
st.push(r.text (290, 180, "node2"), r.rect(290, 180, 60, 40, 2)),
st.push(r.text (450, 100, "node3"), r.ellipse(450, 100, 20, 20))
但是当我移动形状时,文字和形状并没有保持在一起。文本保持不动。
编辑:我无法在http://raphaeljs.com/graffle.html获得与Chrome合作的库存演示。 IE它有效。
答案 0 :(得分:55)
主要编辑以更优雅的方式关联元素。
Sets 适合分组Raphael对象,但是套装不会创建自己的元素,所以你不能拖放一组,因为当你点击画布时你要么选择形状或文本,但从不设置(因为没有设置元素)。
Here is a simple jsFiddle showing the properties of a set. 请注意,该集合没有x
或y
属性。
[set c]创建类似于数组的对象,以保持并同时操作几个元素。 警告:它不会在页面中为自己创建任何元素。
简单的解决方法是使文本和形状分别可拖动。然后将关联文本与形状...及相关形状以及文本一起移动。
像这样关联对象很简单......创建一个属性。在这种情况下,每个形状和每个文本都有一个名为.pair
的属性,它是对相关元素的引用。
以下是它的完成方式:
var i, ii, tempS, tempT
shapes = [ ... ],
texts = [ ... ];
for (i = 0, ii = shapes.length; i < ii; i++) {
tempS = shapes[i].attr( ... );
tempT = texts[i].attr( ...);
// Make all the shapes and texts dragable
shapes[i].drag(move, dragger, up);
texts[i].drag(move, dragger, up);
// Associate the elements
tempS.pair = tempT;
tempT.pair = tempS;
}
然后在拖放代码中,这是move()
,dragger()
和up()
函数,您必须确保处理被点击的元素及其相关联的元素元件。
例如,这里是move()
函数的相关部分。请注意,text
的处理方式与rectangle
相同(通过更改属性x
和y
),因此每个false
条件都可以下面的Javascript条件运算符处理rectangle
和text
move = function (dx, dy) {
// Move main element
var att = this.type == "ellipse" ?
{cx: this.ox + dx, cy: this.oy + dy} :
{x: this.ox + dx, y: this.oy + dy};
this.attr(att);
// Move paired element
att = this.pair.type == "ellipse" ?
{cx: this.pair.ox + dx, cy: this.pair.oy + dy} :
{x: this.pair.ox + dx, y: this.pair.oy + dy};
this.pair.attr(att);
...
}
以下是完整的工作代码:
Raphael.fn.connection = function (obj1, obj2, line, bg) {
if (obj1.line && obj1.from && obj1.to) {
line = obj1;
obj1 = line.from;
obj2 = line.to;
}
var bb1 = obj1.getBBox(),
bb2 = obj2.getBBox(),
p = [{x: bb1.x + bb1.width / 2, y: bb1.y - 1},
{x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + 1},
{x: bb1.x - 1, y: bb1.y + bb1.height / 2},
{x: bb1.x + bb1.width + 1, y: bb1.y + bb1.height / 2},
{x: bb2.x + bb2.width / 2, y: bb2.y - 1},
{x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + 1},
{x: bb2.x - 1, y: bb2.y + bb2.height / 2},
{x: bb2.x + bb2.width + 1, y: bb2.y + bb2.height / 2}],
d = {}, dis = [];
for (var i = 0; i < 4; i++) {
for (var j = 4; j < 8; j++) {
var dx = Math.abs(p[i].x - p[j].x),
dy = Math.abs(p[i].y - p[j].y);
if ((i == j - 4) || (((i != 3 && j != 6) || p[i].x < p[j].x) && ((i != 2 && j != 7) || p[i].x > p[j].x) && ((i != 0 && j != 5) || p[i].y > p[j].y) && ((i != 1 && j != 4) || p[i].y < p[j].y))) {
dis.push(dx + dy);
d[dis[dis.length - 1]] = [i, j];
}
}
}
if (dis.length == 0) {
var res = [0, 4];
} else {
res = d[Math.min.apply(Math, dis)];
}
var x1 = p[res[0]].x,
y1 = p[res[0]].y,
x4 = p[res[1]].x,
y4 = p[res[1]].y;
dx = Math.max(Math.abs(x1 - x4) / 2, 10);
dy = Math.max(Math.abs(y1 - y4) / 2, 10);
var x2 = [x1, x1, x1 - dx, x1 + dx][res[0]].toFixed(3),
y2 = [y1 - dy, y1 + dy, y1, y1][res[0]].toFixed(3),
x3 = [0, 0, 0, 0, x4, x4, x4 - dx, x4 + dx][res[1]].toFixed(3),
y3 = [0, 0, 0, 0, y1 + dy, y1 - dy, y4, y4][res[1]].toFixed(3);
var path = ["M", x1.toFixed(3), y1.toFixed(3), "C", x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)].join(",");
if (line && line.line) {
line.bg && line.bg.attr({path: path});
line.line.attr({path: path});
} else {
var color = typeof line == "string" ? line : "#000";
return {
bg: bg && bg.split && this.path(path).attr({stroke: bg.split("|")[0], fill: "none", "stroke-width": bg.split("|")[1] || 3}),
line: this.path(path).attr({stroke: color, fill: "none"}),
from: obj1,
to: obj2
};
}
};
var el;
window.onload = function () {
var color, i, ii, tempS, tempT,
dragger = function () {
// Original coords for main element
this.ox = this.type == "ellipse" ? this.attr("cx") : this.attr("x");
this.oy = this.type == "ellipse" ? this.attr("cy") : this.attr("y");
if (this.type != "text") this.animate({"fill-opacity": .2}, 500);
// Original coords for pair element
this.pair.ox = this.pair.type == "ellipse" ? this.pair.attr("cx") : this.pair.attr("x");
this.pair.oy = this.pair.type == "ellipse" ? this.pair.attr("cy") : this.pair.attr("y");
if (this.pair.type != "text") this.pair.animate({"fill-opacity": .2}, 500);
},
move = function (dx, dy) {
// Move main element
var att = this.type == "ellipse" ? {cx: this.ox + dx, cy: this.oy + dy} :
{x: this.ox + dx, y: this.oy + dy};
this.attr(att);
// Move paired element
att = this.pair.type == "ellipse" ? {cx: this.pair.ox + dx, cy: this.pair.oy + dy} :
{x: this.pair.ox + dx, y: this.pair.oy + dy};
this.pair.attr(att);
// Move connections
for (i = connections.length; i--;) {
r.connection(connections[i]);
}
r.safari();
},
up = function () {
// Fade original element on mouse up
if (this.type != "text") this.animate({"fill-opacity": 0}, 500);
// Fade paired element on mouse up
if (this.pair.type != "text") this.pair.animate({"fill-opacity": 0}, 500);
},
r = Raphael("holder", 640, 480),
connections = [],
shapes = [ r.ellipse(190, 100, 30, 20),
r.rect(290, 80, 60, 40, 10),
r.rect(290, 180, 60, 40, 2),
r.ellipse(450, 100, 20, 20)
],
texts = [ r.text(190, 100, "One"),
r.text(320, 100, "Two"),
r.text(320, 200, "Three"),
r.text(450, 100, "Four")
];
for (i = 0, ii = shapes.length; i < ii; i++) {
color = Raphael.getColor();
tempS = shapes[i].attr({fill: color, stroke: color, "fill-opacity": 0, "stroke-width": 2, cursor: "move"});
tempT = texts[i].attr({fill: color, stroke: "none", "font-size": 15, cursor: "move"});
shapes[i].drag(move, dragger, up);
texts[i].drag(move, dragger, up);
// Associate the elements
tempS.pair = tempT;
tempT.pair = tempS;
}
connections.push(r.connection(shapes[0], shapes[1], "#fff"));
connections.push(r.connection(shapes[1], shapes[2], "#fff", "#fff|5"));
connections.push(r.connection(shapes[1], shapes[3], "#000", "#fff"));
};
为了完整起见,这里是 the linked to jsFiddle for showing the properties of a set 的代码:
window.onload = function () {
var paper = Raphael("canvas", 320, 200),
st = paper.set(),
propArr = [];
st.push(
paper.circle(10, 10, 5),
paper.circle(30, 10, 5)
);
st.attr({fill: "red"});
for(var prop in st) {
if (st.hasOwnProperty(prop)) {
// handle prop as required
propArr.push(prop + " : " + st[prop]);
}
}
alert(propArr.join("\n"));
};
// Output:
// 0 : Raphael's object
// 1 : Raphael's object
// items : Raphael's object,Raphael's object
// length : 2
// type : set
答案 1 :(得分:7)
或者,试试Raphael的这个“组”插件,它可以让你创建一个合适的SVG组元素。
https://github.com/rhyolight/Raphael-Plugins/blob/master/raphael.group.js
答案 2 :(得分:4)
是的,这就是set
对象的用途:
var myWords = r.set();
myWords.push(
r.text(190, 100, "Hello"),
r.text(480,100, "Good Bye"
);
// now you can treat the set as a single object:
myWords.rotate(90);
补充答案:
好的,我看到你尝试过使用套装,但你错了。集合创建了一组东西。就像您要在Adobe Illustrator或Inkscape或Microsoft Word或Open Office中对形状和文本进行分组一样。如果我理解你想要的是这个:
shapes = [ r.set(r.text (190, 100, "node1"), r.ellipse(190, 100, 30, 20)),
r.set(r.text (290, 80, "Center"), r.rect(290, 80, 60, 40, 10)),
r.set(r.text (290, 180, "node2"), r.rect(290, 180, 60, 40, 2)),
r.set(r.text (450, 100, "node3"), r.ellipse(450, 100, 20, 20))
];
您还需要修改拖动器和移动功能,因为形状不再是'rect'类型,而是'set'类型:
var dragger = function () {
this.ox = this.attr("x");
this.oy = this.attr("y");
this.animate({"fill-opacity": .2}, 500);
};
var move = function (dx, dy) {
var att = {x: this.ox + dx, y: this.oy + dy};
this.attr(att);
for (var i = connections.length; i--;) {
r.connection(connections[i]);
}
r.safari();
};
所有套装都有x
和y
属性。
答案 3 :(得分:1)
仅仅更改配对对象的属性以及拖动主对象时正在更改的属性会不会更容易?
这样的事情:
window.onload = function () {
var R = Raphael("holder"),
circ = R.circle(100, 100, 50).attr({ "fill": "#d9d9d9", "stroke-width": 1 }),
circ2 = R.circle(50, 50, 5),
start = function () {
this.ox = this.attr("cx"); //ox = original x value
this.oy = this.attr("cy");
this.animate({ "opacity": .5, "stroke-width": 15 }, 200);
},
move = function (dx, dy) { //dx - delta x - diiference in movement between point a and b
var cdx = circ2.attr("cx") - this.attr("cx"),
cdy = circ2.attr("cy") - this.attr("cy");
this.attr({ "cx": this.ox + dx, "cy": this.oy + dy });
group(this,circ2,cdx,cdy);
R.safari();
},
up = function () {
this.animate({ "opacity": 1, "stroke-width": 1 }, 200);
},
group = function (refObj,thisObj, dx, dy) {
thisObj.attr({ "cx": refObj.attr("cx") + dx, "cy": refObj.attr("cy") + dy });
};
circ.drag(move, start, up);
};