43 votes

Comment puis-je combiner des objets dans la bibliothèque JavaScript de Raphael?

Désolé pour une longue question, mais voilà. Je suis en train de modifier la faire glisser des formes autour de démo ici:

http://raphaeljs.com/graffle.html

La démo fonctionne très bien. Ce que je veux faire c'est mettre des mots à l'intérieur de la forme et de déplacer la forme et de texte autour d'un composite unique objet.

Voici le code permettant de 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 ceci:

 myWords = [ r.text(190, 100,  "Hello"),
      r.text(480,100, "Good Bye")
    ];

et fait les ajustements ailleurs, de sorte que cela pourrait fonctionner, mais il déplace juste le texte et les formes, mais la forme et le texte ne sont jamais considérés comme un tout. Je peux déplacer le texte distinct de la forme et vice versa. J'ai besoin d'eux pour un seul objet. de sorte qu'ils se déplacent ensemble. Comment puis-je le faire? Merci pour toute aide.

EDIT:

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 restent pas ensemble, quand j'ai déménagé de la forme. Le texte est resté immobile.

EDIT: je ne peux pas obtenir le stock de démonstration à http://raphaeljs.com/graffle.html travailler avec google Chrome. IE ça fonctionne.

55voto

Peter Ajtai Points 26377

Fait majeur de modifier à associer des éléments de manière plus élégante.


Les ensembles sont bonnes pour le groupement des Raphaël, des objets, mais des ensembles de ne pas créer leurs propres éléments, de sorte que vous ne pouvez pas faire glisser et déposer un ensemble, car lorsque vous cliquez sur le canevas, soit vous sélectionnez la forme ou le texte, mais jamais l'ensemble (car il n'existe aucun élément de jeu).

Voici un simple jsFiddle montrant les propriétés d'un ensemble. Notez qu'une série n'a pas d' x ou y propriétés.

Depuis le Raphaël de la documentation:

[Un ensemble c]reates tableau comme objet de conserver et d'exploiter deux éléments à la fois. Avertissement: il ne crée pas d'éléments dans la page.


Le travail simple est de faire à la fois le texte et la forme séparément déplaçable. Déplacez ensuite le texte associé avec la forme... et la forme associée avec le texte.

L'association d'objets comme c'est simple... la création d'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 on fait:

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 le glisser-déposer de code, qui est l' move(), dragger(), et up() des fonctions que vous avez à faire assurez-vous de traiter à la fois les cliqué sur un élément et son élément associé.

Par exemple voici la partie pertinente de l' move() fonction. Notez que text peuvent être traitées de la même manière qu' rectangle (en modifiant les attributs x et y), de sorte que l' false condition dans chaque Javascript opérateurs conditionnels ci-dessous gère à la fois le cas pour rectangle et 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 l'intégralité du code qui fonctionne:

Travail jsFiddle exemple de selection des textes et des formes

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 la liés à jsFiddle pour montrer 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

7voto

Ben Bederson Points 696

Ou bien essayez ce plugin "group" 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

4voto

slebetman Points 28276

Oui, c'est ce que l' set objet de:

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 le jeu mais que vous l'utilisez mal. Un ensemble crée un groupe de choses. Tout comme si vous étiez au groupe 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 ceci:

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 dragueur et déplacer fonctions depuis les formes ne sont plus du type "rect", mais sont 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 jeux ont x et y attributs.

1voto

Adam Moszczyński Points 516

Ne serait-il pas plus simple de changer les attributs de l'objet apparié ainsi que 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);




    };
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X