webentwicklung-frage-antwort-db.com.de

Draggables und Resizables in SVG

Ich möchte, dass ein svg-Element (Pfad, Rechteck oder Kreis) in der Lage sein soll, ziehbar zu sein und ihm Griffe zur Größenänderung zu geben.

Im Gegensatz zu HTML-DOM haben jedoch nicht alle Elemente eine x-, y-Koordinate in der oberen linken Ecke sowie Breite und Höhe für eine den Inhalt umgebende Box. Dies macht es unbequem, eine generische Größenänderungs- oder Ziehprozedur durchzuführen.

Ist es eine gute Idee, dass jeder Pfad oder Kreis innerhalb seines eigenen svg-Objekts gezeichnet wird, um mir eine Box zum Spielen zu geben?

Wie wird DragSable/Resizable normalerweise in SVG implementiert?

29
Boris Yeltz

Hinweis: Beim Ziehen und Ändern der Größe müssen Sie für bestimmte Arten von Elementen getrennte Fälle definieren. Werfen Sie einen Blick auf das Beispiel, das ich später gebe -, das das Ziehen von Ellipsen und Rechtecken in derselben Gruppe von Funktionen übernimmt.


Um ein Element ziehbar zu machen, verwenden Sie:

element.drag(move, start, up);

Die drei Argumente sind Verweise auf die Funktionen, die das Verschieben (Ziehen), Starten (Herunterfahren) und Stoppen (Mouseup) ausführen.

Um beispielsweise einen ziehbaren Kreis (aus der Dokumentation) zu erstellen:

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-Beispiel


Im obigen Beispiel werden die Eigenschaften ox und oy an das Element angehängt, um dessen Position zu verfolgen, und diese Eigenschaften werden in Verbindung mit dx und dy verwendet, um die Position des Elements beim Ziehen zu ändern.

Ein komplizierteres Ziehen und Ablegen zur Beantwortung dieser Frage.

Um die Größe eines Objekts zu ändern, erstellen Sie einfach eine zweite Gruppe von Drag & Drop-Methoden für die Größenanpassung und passen die Zielelemente height und width basierend auf dem Ziehen der Größenanpassung an.

Hier ist ein voller Drag-and-Drop-Kasten, den ich aufgeschrieben habe:

jsFiddle-Beispiel für Drag & Drop und an der Größe veränderbare Box

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;
};​

Die enthaltenen Event-Handler (Sie können natürlich mehr in Verbindung mit .node() verwenden) und die Drag & Drop-Beschreibung finden Sie am Ende der Seite in der Dokumentation.

Sie würden einfach eine Raphael-Leinwand erstellen, und dann wäre jedes Element ein anderes Element. Weisen Sie sie einfach Variablen zu, damit Sie mit ihnen umgehen können, wie im obigen Beispiel (c wurde verwendet, um auf das erstellte Kreiselement zu verweisen).

In Reaktion auf Kommentare ist hier ein einfacher Kreis mit Drag & Drop + Größenänderung möglich. Der Trick ist, dass Kreise die Attribute cx und cy für die Positionierung und r für die Größe verwenden. Die Mechanik ist ziemlich gleich ... eine Ellipse wäre etwas komplizierter, aber es ist wieder nur eine Frage der Arbeit mit den richtigen Attributen.

jsFiddle-Beispiel für Drag & Drop und einen veränderbaren Kreis

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;
};
53
Peter Ajtai

Werfen Sie einen Blick auf Raphael.FreeTransform das scheint zu tun, was Sie wollen.

4
Elbert Alias

Versuchen Sie Graphiti hier ist der Link: Draw2d und Graphiti

Es basiert auf Raffael und ist sehr einfach zu bedienen.

3
JS Rocker

Es gibt auch dieses Plugin für SVG.js.

https://github.com/svgdotjs/svg.resize.js

0
Paul LeBeau