2011-01-13 5 views
2

In den letzten zwei Tagen habe ich effektiv herausgefunden, wie man Raphael Elements nicht dreht.Raphael SVG VML Implementieren Multi Pivot Punkte für Rotation

Grundsätzlich versuche ich, mehrere Drehpunkte auf Element zu implementieren, um es mit der Maus zu drehen.

Wenn ein Benutzer in den Rotationsmodus wechselt, werden 5 Drehpunkte erstellt. Eine für jede Ecke der Bounding Box und eine in der Mitte der Box.

Wenn die Maus gedrückt ist und sich bewegt, ist es einfach genug, sich mit Raphael elements.rotate(degrees, x, y) um den Drehpunkt zu drehen und die Grade basierend auf den Mauspositionen und atan2 zum Drehpunkt zu berechnen.

Das Problem tritt auf, nachdem ich das Element, Bbox und die anderen Pivots gedreht habe. Dort ist x, y-Position im selben nur dort Ansichtsfenster anders. In einem SVG-fähigen Browser kann ich neue Pivot-Punkte basierend auf matrixTransformation and getCTM erstellen. Nach dem Erstellen des ersten Satzes neuer Pivots wird jedoch jede Drehung nach den Pivots aufgrund von Rundungsfehlern weiter von der transformierten Bbox entfernt.

rotate errors

Das ist oben nicht einmal eine Option in IE da ist VML basiert und kann nicht für die Transformation berücksichtigen.

ist die einzig wirksame Weise Element Rotation zu implementieren wird durch Verwendung rotate absolute oder Drehen um die Mittel des Begrenzungskastens?

Ist es möglich, an dem alle Multis erstellen Drehpunkte für ein Objekt und sie nach mouseup aktualisiert in den Ecken und in der Mitte der transformierten bbox zu bleiben?

UPDATE: ich versucht habe jQuery zu verwenden versetzt den Dreh zu finden, nachdem es gedreht wurde, und dass die Verwendung Standort als Drehpunkt versetzt.

Demo site ... http://weather.speedfetishperformance.com/dev/raphael/rotation.html

+0

Das sieht für mich so aus, als könnte es leicht reparierbar sein - das heißt, ich denke, dass Sie näher an einer richtigen Lösung sind als Sie denken ... könnten Sie Ihren Code irgendwo posten oder hochladen? – Zevan

+0

Bearbeitet, um Code zu zeigen ... dieser Weg ist natürlich nicht freundlich IE –

Antwort

1

Die beste Cross-Browser, wie ich mir vorstellen kann zu tun, was Sie wollen, ist die Rotation selbst anstatt lassen SVG tun, sie umzusetzen. Rotierende x, y Koordinaten sind ziemlich einfach und ich habe diesen (tcl) Code immer benutzt, wenn ich eine 2D Rotation machen muss: Canvas Rotation.

Der Vorteil ist, dass Sie die maximale Kontrolle über die Rotation haben, da Sie es manuell tun. Dies löst die Probleme, die Sie versuchen, die endgültigen Koordinaten nach der Drehung zu erraten. Dies sollte auch Cross-Browser-kompatibel sein.

Der Nachteil ist, dass Sie Pfade verwenden müssen. Also keine Rectures (obwohl es einfach sein sollte, sie in Pfade umzuwandeln) oder Ellipsen (ein bisschen schwieriger in Pfad zu konvertieren, aber machbar). Da du es auch manuell machst, sollte es langsamer sein als SVG es für dich tun zu lassen.

Hier ist eine teilweise Umsetzung dieser Tcl-Code in Javascript:

zuerst brauchen wir eine regexp SVG Pfade tokenize:

var svg_path_regexp = (function(){ 
    var number = '-?[0-9.]+'; 
    var comma = '\s*[, \t]\s*'; 
    var space = '\s+'; 
    var xy = number + comma + number; 
    var standard_paths = '[mlcsqt]'; 
    var horiz_vert = '[hv]\s*' + number; 
    var arc = 'a\s*' + xy + space + number + space + xy + space + xy; 
    var OR = '\s*|'; 

    return new RegExp(
    standard_paths +OR+ 
    xy +OR+ 
    horiz_vert +OR+ 
    arc, 

    'ig' 
); 
})(); 

jetzt können wir die Drehfunktion implementieren:

function rotate_SVG_path (path, Ox, Oy, angle) { 
    angle = angle * Math.atan(1) * 4/180.0; // degrees to radians 

    var tokens = path.match(svg_path_regexp); 

    for (var i=0; i<tokens.length; i++) { 
    var token = tokens[i].replace(/^\s+|\s+$/g,''); // trim string 

    if (token.match(/\d/)) { // assume it's a coordinate 
     var xy = token.split(/[, \t]+/); 
     var x = parseFloat(xy[0]); 
     var y = parseFloat(xy[1]); 
     x = x - Ox; // Shift to origin 
     y = y - Oy; 
     var xx = x * Math.cos(angle) - y * Math.sin(angle); // Rotate 
     var yy = x * Math.sin(angle) + y * Math.cos(angle); 
     x = xx + Ox; // Shift back 
     y = yy + Oy; 

     token = x + ',' + y; 
    } 
    else if (token.match(/^[hv]/)) { 
     // handle horizontal/vertical line here 
    } 
    else if (token.match(/^a/)) { 
     // handle arcs here 
    } 

    tokens[i] = token; 
    } 
    return tokens.join(''); 
} 

Die obige Rotationsfunktion implementiert alles außer t horizontale/vertikale Linien (Sie müssen den vorherigen XY-Wert verfolgen) und Bögen. Beides sollte nicht zu schwer zu implementieren sein.

+0

Das ist also die einzige Möglichkeit, um diesen Pivot-Effekt zu erreichen ist es, die Pfade zu zerstören und neu zu erstellen? Ursprünglich habe ich die Rotationsformel angewendet, um einen neuen Ursprung zu finden. Ich fand dann heraus, dass der jQuery-Offset jedes Mal fast gleichwertig war, also begann ich damit. Ich bin in der Lage, die neuen Punkte nach der Rotation zu finden ... scheint nur, als ob ich eine Schlüsselinformation über mehrere Umdrehungen verpasse. Scheint einfach, dass es einen einfacheren Weg geben würde. –

+0

Du zerstörst nicht wirklich das Pfadobjekt, das wäre viel langsamer. Ändere stattdessen den Pfadstring: 'obj.attr ('Pfad', rotiere (obj.attr ('Pfad'), x, y, Winkel)' ' – slebetman

+0

Eigentlich, für saubereren Code, kannst du es sogar als Methode implementieren:' Raphael.el.rotate_path = function ... 'dann kannst du es wie folgt benennen:' obj.rotate_path (x, y, angle) ' – slebetman

Verwandte Themen