33

我想让一个 svg 元素(路径、矩形或圆形)能够被拖动并给它调整大小的句柄。

但与 HTML DOM 不同,并非所有元素都有左上角 x,y 坐标以及围绕内容的框的宽度和高度。这使得进行通用的调整大小或拖动过程很不方便。

将每条路径或圆圈绘制在自己的 svg 对象内以给我一个可以玩的盒子是个好主意吗?

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

4

4 回答 4

54

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


要使元素可拖动,请使用:

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


在上面的例子中,oxandoy属性被附加到元素上以跟踪其位置,这些属性与dxanddy一起用于在元素被拖动时更改元素的位置。

一个更复杂的拖放来回答这个问题

要使对象可调整大小,您只需为调整大小创建第二组拖放方法,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;
};
于 2010-10-07T02:58:57.893 回答
4

看看Raphael.FreeTransform似乎可以满足您的需求。

于 2011-12-07T03:58:11.820 回答
3

在这里尝试 Graphiti 是链接:Draw2d 和 Graphiti

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

于 2012-08-23T13:34:35.670 回答
1

SVG.js 也有这个插件。

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

于 2018-12-11T12:26:35.770 回答