如何使用JavaScript和Raphael旋转先前拖动的SVG对象

How do I rotate a previously dragged SVG object using JavaScript and Raphael?

本文关键字:拖动 SVG 对象 旋转 何使用 JavaScript Raphael      更新时间:2023-09-26

我正在使用Raphael库旋转和拖动图像。我让它正确地拖动,我有一个按钮,每次按下它都会正确地旋转90度。但是我有一个问题当我旋转图像,拖动它,然后再旋转它。

HTML中仅有的元素是用于保存Raphael画布的div和用于旋转图像的按钮。JavaScript在这里:

var gboard;
var piece;
window.onload = function () 
{
    gboard = Raphael("gameboard", 800, 500);    
    // piece = gboard.rect(100, 100, 50, 50).attr({fill: "#0CF", "fill-opacity": 1, stroke: "none", cursor: "move"});
    piece = gboard.image("piece.gif", 100, 100, 50, 50).attr({cursor: "move"});
    piece.drag(dragMove, dragStart, dragStop);  
    var angle = 0;
    document.getElementById('btn').onclick = function () {
        angle += 90;
        var cx = piece.attr('x') + 25;
        var cy = piece.attr('y') + 25;
        piece.animate({transform: "R" + angle + ", " + cx + ", " + cy + ""}, 500, "<>");
        // piece.transform("R90," + cx + "," + cy);
    };
}
// Set up the object for dragging
function dragStart() 
{
    this.ox = this.attr("x");
    this.oy = this.attr("y");
}
// Clean up after dragging ends
function dragStop() {}
/**
 * Handle the moving of objects when dragging 
 * Check the current angle to compensate for rotated coordinate system.
 */
function dragMove(dx, dy) 
{
    var angle = getAngle(this._['deg']);
    if (angle == 90)
        this.attr({x: this.ox + dy, y: this.oy - dx});
    else if (angle == 180)
        this.attr({x: this.ox - dx, y: this.oy - dy});
    else if (angle == 270)
        this.attr({x: this.ox - dy, y: this.oy + dx});
    else // angle == 0
        this.attr({x: this.ox + dx, y: this.oy + dy});
}
/** 
 * Get the simplified equivalent angle (0 <= angle <= 360) for the given angle. 
 *
 * @param deg   The angle in degrees
 * @return  The equivalent angle between 0 and 360
 */
function getAngle(deg)
{
    if (deg % 360 == 0)
        return 0;   
    else if (deg < 0)
    {
        while (deg < 0)
            deg += 360;
    }
    else if (deg > 360)
    {
        while (deg > 360)
            deg -= 360;
    }
    return deg;
}

我通过在值改变时重新应用所有转换来解决这个问题。

http://alias.io/raphael/free_transform/

来源:https://github.com/ElbertF/Raphael.FreeTransform

您可以使用转换工具来处理这两者,而不是使用x/y属性来操作位置和使用转换来操作旋转,从而大大简化了您的项目。

由于我们在翻译中使用了大写的"T",它忽略了同一字符串中的先前翻译命令,因此我们不再需要担心拖动时的当前角度。

var gboard, 
    piece;
gboard = Raphael("gameboard", 800, 500);    
var angle = 0,
    x = 100,
    y = 100;
//note that this now starts at 0,0 and is immediately translated to 100,100
piece = gboard.image("piece.gif", 0, 0, 50, 50).attr({cursor: "move", transform: "R" + angle + "T" + x + "," + y });
piece.drag(dragMove, dragStart, dragStop);
document.getElementById('btn').onclick = function () {  
  angle += 90;
  piece.animate({transform: "R" + angle + "T" + x + "," + y}, 500, "<>");
};
// Set up the object for dragging
function dragStart() 
{
    this.ox = x;
    this.oy = y;
}
// Clean up after dragging ends
function dragStop() {}
//Since we're using a capital 'T' in the translation, which ignores previous translation commands in the same string, we no longer have to worry about the current angle here    
function dragMove(dx, dy) {
  x = this.ox + dx;
  y = this.oy + dy;
  piece.attr({ transform: "R" + angle + "T" + x + "," + y });
}

jsFiddle

好奇;看起来旋转实际上改变了x和y的值。所以如果你旋转90度,将盒子向右移动100像素实际上是将它向上移动100像素,然后被翻译为向右。这就抛弃了cx和cy值,它们决定了盒子旋转的点。

要明白我的意思,旋转一次,然后拖动框,同时观察检查器中的X和Y值。

我可以看到两种方法来修复它:你可以做数学来重新计算每次旋转的"真实"x和y,或者你可以通过附加数据属性来自己跟踪x和y(这是我建议的)。好运!