SVG中的可拖动和可调整大小元素

35

我想使一个 SVG 元素(路径、矩形或圆)可以被拖动,并同时提供调整大小的手柄。

但与 HTML DOM 不同,不是所有的元素都有左上角的 x,y 坐标和围绕内容的盒子的宽度和高度。这使得制作通用的调整大小或拖动过程不方便。

有没有将每个路径或圆圈绘制在自己的 SVG 对象中以给我一个可操作的盒子的好方法呢?

在 SVG 中,可拖动/可调整大小通常如何实现?

4个回答

56

注意:对于拖动和调整大小,您需要为某些不同类型的元素制作单独的情况。请查看我稍后提供的示例,该示例处理了椭圆和矩形在同一组函数中的拖动。


要使元素可拖动,您可以使用:

element.drag(move, start, up);

这三个参数是对处理移动(拖动)、开始(鼠标按下)和停止(鼠标松开)的函数的引用。

例如,要制作一个可拖动的圆形(摘自文档):

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例子


在上面的例子中,oxoy属性被添加到元素上以跟踪其位置,这些属性与dxdy结合使用,用于在拖动时更改元素的位置。

一个更复杂的拖放例子以回答这个问题

要使对象可调整大小,只需为调整大小器创建第二组拖放方法,并根据拖动调整目标元素的heightwidth

这是一个完整的拖放和可调整大小的盒子的例子:

jsFiddle例子:拖放和可调整大小的盒子

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

包含的事件处理程序(当然,您可以结合.node()使用更多)和拖放描述位于页面底部文档中。

您只需创建一个 Raphael 画布,然后每个项将成为不同的元素。只需将它们分配给变量以便处理,就像上面的示例中使用 c 引用所创建的圆形元素一样。

回应这里的评论,这是一个简单的可拖放和调整大小的圆形。诀窍在于圆形使用属性 cxcy 进行定位,使用属性 r 进行大小调整。机制基本相同......椭圆可能稍微复杂一些,但再次,这只是与正确属性一起工作的问题。

jsFiddle 示例:可拖放和可调整大小的圆形

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

你好,上面的例子非常棒,但我想进一步扩展它。我希望能够使用可调整大小的圆形。我已经成功地让矩形工作了,但在处理圆形时遇到了困难。我认为我的问题源于rmove方法,因为当我设置this.box的宽度和高度时,圆形没有其他选择。您有什么想法,或者您知道可能的教程吗?谢谢。 - Adam Holmes
1
@Adam - 对于圆和椭圆,您只需要使用中心点cxcy以及半径。这是一个处理拖动矩形和椭圆的示例==>http://jsfiddle.net/vPyjc/(查看“dragger”函数,它使用if`shapes[ind].type =="rect"`来检查形状类型并分别处理每个形状。)------这意味着您实际上必须编写单独的代码来处理拖动和调整椭圆大小(使用半径和中心坐标而不是框)。 - Peter Ajtai
抱歉,也许我没有表达清楚。我没有任何问题拖动形状。问题出在调整大小上。我可以像您上面的示例一样调整矩形的大小,但是我无法使用可拖动形状调整圆形/椭圆形的大小,即使我选择了正确的属性。我认为问题出在.box上,因为圆形没有宽度和高度属性。 - Adam Holmes
1
@Adam - 我理解了。这就是为什么我建议使用 cxcyradius 来绘制圆形。 radius 属性可以通过 r 访问,您可以使用它来调整圆形的大小,而不是使用矩形框 - 这里有一个快速调整圆形大小的示例:http://jsfiddle.net/EqrQZ/(当然,在更精细的示例中,您会想要添加一个用于调整大小的手柄)- 请注意,我正在使用 r 调整圆形大小。-box 只是较大对象的副本,您必须自己创建它...看看代码的最后一行 ==> s.box = c; - Peter Ajtai
@Adam - 在圆上放置手柄会更加棘手,因为手柄的移动方式不同,但这里有一个快速入门 ==> http://jsfiddle.net/Pxbrf/ - 您还可以通过移动手柄来确定椭圆的形状。 - Peter Ajtai
1
啊,现在一切都清晰了,我已经把它搞定了。感谢你们的帮助。我可能应该把它作为一个问题来问,这样你们就可以得到声望值了。谢谢 :) - Adam Holmes

4

3

试用Graphiti,这是链接:Draw2d和Graphiti

它基于Raphael,非常易于使用。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接