首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >拉斐尔JS的拖拽和形状旋转

拉斐尔JS的拖拽和形状旋转
EN

Stack Overflow用户
提问于 2011-11-13 23:39:38
回答 5查看 12.5K关注 0票数 4

我正在使用RaphaelJS 2.0在一个div中创建几个形状。每个形状都需要能够独立地在div的范围内被拖放。双击形状时,该形状需要旋转90度。然后,它可能会被拖拽,然后再掉落和旋转。

我已经将一些代码加载到fiddler:http://jsfiddle.net/QRZMS/上。基本上是这样的:

代码语言:javascript
复制
    window.onload = function () {

        var angle = 0;

        var R = Raphael("paper", "100%", "100%"),
            shape1 = R.rect(100, 100, 100, 50).attr({ fill: "red", stroke: "none" }),
            shape2 = R.rect(200, 200, 100, 50).attr({ fill: "green", stroke: "none" }),
            shape3 = R.rect(300, 300, 100, 50).attr({ fill: "blue", stroke: "none" }),
            shape4 = R.rect(400, 400, 100, 50).attr({ fill: "black", stroke: "none" });
        var start = function () {
            this.ox = this.attr("x");
            this.oy = this.attr("y");
        },
        move = function (dx, dy) {
            this.attr({ x: this.ox + dx, y: this.oy + dy });
        },
        up = function () {

        };
        R.set(shape1, shape2, shape3, shape4).drag(move, start, up).dblclick(function(){
            angle -= 90;
            shape1.stop().animate({ transform: "r" + angle }, 1000, "<>");
        });


    }

拖放正在工作,其中一个形状在双击时也会旋转。然而,有两个问题:

  1. 如何将旋转自动附加到每个形状上,而不必将每个项引用硬编码到旋转方法中?也就是说,我只想画一次形状,然后让它们都自动暴露在相同的行为中,这样它们就可以独立地被拖放/旋转,而不必对每个形状显式地应用这种行为。
  2. 在形状被旋转后,它不再正确地拖动--就好像鼠标拖动的运动与形状的原始方向有关,而不是在形状旋转时进行更新。我如何才能使它正确地工作,使形状可以被拖动和旋转很多次,无缝?

非常感谢你的指点!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-11-18 23:37:53

我试过好几次,想把我的头绕在新的转换引擎上,但没有用。所以,我回到了第一原则。

我终于设法正确地拖放了一个经过几次转换的对象,试图计算出不同转换的影响-- t、T、...t、...T、r、R等.

所以,这是解决方案的关键

代码语言:javascript
复制
var ox = 0;
var oy = 0;

function drag_start(e) 
{
};


function drag_move(dx, dy, posx, posy) 
{


   r1.attr({fill: "#fa0"});

   //
   // Here's the interesting part, apply an absolute transform 
   // with the dx,dy coordinates minus the previous value for dx and dy
   //
   r1.attr({
    transform: "...T" + (dx - ox) + "," + (dy - oy)
   });

   //
   // store the previous versions of dx,dy for use in the next move call.
   //
   ox = dx;
   oy = dy;
}


function drag_up(e) 
{
   // nothing here
}

就这样。愚蠢的简单,我相信已经有很多人想到了,但也许有人会发现它是有用的。

这是给你玩的小提琴

..。是最初问题的有效解决方案。

票数 13
EN

Stack Overflow用户

发布于 2011-11-14 20:54:00

正如amadan建议的那样,当多个事物具有相同的(初始)属性/属性时,创建函数通常是个好主意。这确实是你第一个问题的答案。至于第二个问题,那就有点棘手了。

当拉皮尔物体被旋转时,坐标平面也是如此。出于某种原因,dmitry和网络上的一些其他来源似乎同意这是实现它的正确方法。我和你一样不同意。我没有找到一个全面的好的解决方案,但我确实创造了一个工作。我将简要解释,然后显示代码。

  • 创建一个自定义属性来存储当前的旋转状态
  • 根据该属性,您可以决定如何处理移动。

如果你只旋转90度的形状(如果不是,那就更困难了),你就可以确定坐标应该如何操作。

代码语言:javascript
复制
var R = Raphael("paper", "100%", "100%");

//create the custom attribute which will hold the current rotation of the object {0,1,2,3}
R.customAttributes.rotPos = function (num) {
    this.node.rotPos = num;
};

var shape1 = insert_rect(R, 100, 100, 100, 50, { fill: "red", stroke: "none" });
var shape2 = insert_rect(R, 200, 200, 100, 50, { fill: "green", stroke: "none" });
var shape3 = insert_rect(R, 300, 300, 100, 50, { fill: "blue", stroke: "none" });
var shape4 = insert_rect(R, 400, 400, 100, 50, { fill: "black", stroke: "none" });

//Generic insert rectangle function
function insert_rect(paper,x,y, w, h, attr) {
    var angle = 0;
    var rect = paper.rect(x, y, w, h);  
    rect.attr(attr);

    //on createion of the object set the rotation position to be 0
    rect.attr({rotPos: 0});

    rect.drag(drag_move(), drag_start, drag_up);

    //Each time you dbl click the shape, it gets rotated. So increment its rotated state (looping round 4)
    rect.dblclick(function(){
        var pos = this.attr("rotPos");
        (pos++)%4;
        this.attr({rotPos: pos});
        angle -= 90;
        rect.stop().animate({transform: "r" + angle}, 1000, "<>");
    });

    return rect;  
}

//ELEMENT/SET Dragger functions.
function drag_start(e) {
    this.ox = this.attr("x");
    this.oy = this.attr("y");
};


//Now here is the complicated bit
function drag_move() {
    return function(dx, dy) {

        //default position, treat drag and drop as normal
        if (this.attr("rotPos") == 0) {
          this.attr({x: this.ox + dx, y: this.oy + dy});
        }
        //The shape has now been rotated -90
        else if (this.attr("rotPos") == 1) {

            this.attr({x:this.ox-dy, y:this.oy + dx});
        }           
        else if (this.attr("rotPos") == 2) {
            this.attr({x: this.ox - dx, y: this.oy - dy});
        }
        else if (this.attr("rotPos") == 3) {
             this.attr({x:this.ox+dy, y:this.oy - dx});

        }      
    }
};

function drag_up(e) {
}

我真的想不出清晰、简洁的方法来解释drag_move是如何工作的。我认为最好是看一下代码,看看它是如何工作的。基本上,您只需要计算出x和y变量现在是如何从这个新的旋转状态中处理的。没有我画了很多图形,我不确定我是否足够清楚。(我做了很多事情,想弄清楚它应该做什么)。

但是,这种方法有一些缺点:

  • 它只适用于90度旋转(要做45度就需要更多的计算,更不用说任何给定的学位)。
  • 旋转后,拖动启动时会有轻微的移动。这是因为拖动采用了旧的x和y值,这些值已经被旋转。对于这个大小的形状来说,这不是一个很大的问题,但是更大的形状你会开始注意到在画布上跳跃的形状。

我假设你使用变换的原因是你可以动画旋转。如果这不是必要的话,那么您可以使用.rotate()函数,它总是围绕元素的中心旋转,因此可以消除我提到的第二个缺点。

这不是一个完整的解决方案,但它肯定会让您走上正确的道路。我希望看到一个完整的工作版本。

我还在jsfiddle上创建了一个版本,您可以在这里查看:http://jsfiddle.net/QRZMS/3/

祝好运。

票数 3
EN

Stack Overflow用户

发布于 2011-11-14 12:47:00

我通常为我的形状创建一个对象,并将事件处理写入对象中。

代码语言:javascript
复制
function shape(x, y, width, height, a)
{
  var that = this;
  that.angle = 0;
  that.rect = R.rect(x, y, width, height).attr(a);

  that.rect.dblclick(function() {
      that.angle -= 90;
      that.rect.stop().animate({
          transform: "r" + that.angle }, 1000, "<>");
  });
  return that;
}

在上面的示例中,构造函数不仅创建矩形,而且设置双击事件。

需要注意的一点是,对对象的引用存储在“那个”中。这是因为“此”引用根据作用域的不同而变化。在dblClick函数中,我需要引用对象中的rect值,因此我使用存储的引用that.rectthat.angle

请参阅此示例 (从前一个稍有可疑的实例中更新)

也许有更好的方法来做你需要的事情,但这应该对你有用。

希望能帮上忙

尼克

增编:丹,如果你真的是,而且没有Raphael2给你的一些东西,我建议搬回Raphael1.5.x。转换刚刚添加到Raphael2中,在1.5.2中,旋转/平移/缩放代码完全不同(而且更容易)。

看着我,更新我的帖子,希望有因果报应.

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8115713

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档