Désolé pour une longue question, mais voilà. J'essaie de modifier les formes de glissement autour de la démo ici:
http://raphaeljs.com/graffle.html
La démo fonctionne bien. Ce que je veux faire, c'est mettre des mots à l'intérieur des formes et déplacer la forme et le texte comme un objet composite unique.
Voici le code pour créer les objets:
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"));
};
J'ai essayé quelque chose comme ça:
myWords = [ r.text(190, 100, "Hello"),
r.text(480,100, "Good Bye")
];
et fait des ajustements ailleurs pour que cela fonctionne, mais il déplace simplement le texte et les formes, mais la forme et le texte ne sont jamais vus dans leur ensemble. Je peux déplacer le texte séparément de la forme et vice versa. J'ai besoin qu'ils soient un seul objet. alors ils se déplacent ensemble. Comment puis je faire ça? Merci pour toute aide.
ÉDITER:
J'ai essayé ceci:
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))
Mais le texte et la forme ne sont pas restés ensemble lorsque j'ai déplacé la forme. Le texte est juste resté immobile.
EDIT: je ne peux pas obtenir la démo de stock à http://raphaeljs.com/graffle.html pour travailler avec Chrome. IE ça marche.
A fait une modification majeure pour associer les éléments d'une manière plus élégante.
Ensembles sont bons pour regrouper des objets Raphael, mais les ensembles ne créent pas leurs propres éléments, vous ne pouvez donc pas faire glisser et déposer un ensemble , car lorsque vous cliquez sur le canevas, vous sélectionnez la forme ou le texte, mais jamais l'ensemble (car il n'y a pas d'élément d'ensemble).
Voici un simple jsFiddle montrant les propriétés d'un ensemble. Notez qu'un ensemble n'a pas de x
ou y
propriétés.
Depuis le documentation Raphael:
[Un ensemble c] crée un objet de type tableau pour conserver et faire fonctionner deux éléments à la fois. Avertissement: il ne crée aucun élément pour lui-même dans la page.
La solution simple consiste à faire glisser le texte et la forme séparément. Déplacez ensuite le texte associé avec la forme ... et la forme associée avec le texte.
L'association d'objets comme celui-ci est simple ... créez une propriété. Dans ce cas, chaque forme et chaque texte a une propriété appelée .pair
Qui est une référence à l'élément associé.
Voici comment procéder:
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;
}
Et puis dans le code glisser-déposer, qui est les fonctions move()
, dragger()
et up()
, vous devez vous assurer de traiter à la fois l'élément cliqué sur et son élément associé.
Par exemple, voici la partie pertinente de la fonction move()
. Notez que text
peut être traité de la même manière que rectangle
(en changeant les attributs x
et y
), donc le false
dans chacun des opérateurs conditionnels Javascript ci-dessous gère à la fois la casse pour rectangle
et pour 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);
...
}
Et ci-dessous est le code de travail complet:
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"));
};
Pour être complet, voici le code pour le lié à jsFiddle pour afficher les propriétés d'un ensemble:
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
Ou, essayez ce plugin "groupe" pour Raphael qui vous permet de créer un élément de groupe SVG approprié.
https://github.com/rhyolight/Raphael-Plugins/blob/master/raphael.group.js
Oui, c'est à cela que sert l'objet 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);
Réponse supplémentaire:
OK, je vois que vous avez essayé d'utiliser set mais que vous l'utilisez mal. Un ensemble crée un groupe de choses. Tout comme si vous deviez grouper des formes et du texte dans Adobe Illustrator ou Inkscape ou Microsoft Word ou Open Office. Si je vous comprends bien, ce que vous voulez c'est:
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))
];
Vous devrez également modifier votre dragger et déplacer les fonctions car les formes ne sont plus de type 'rect' mais de type '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();
};
Tous les ensembles ont des attributs x
et y
.
Ne serait-il pas plus facile de simplement changer les attributs de l'objet jumelé avec les attributs qui changent lorsque l'objet principal est déplacé?
Quelque chose comme ça:
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);
};