33

SVG 要素 (path、rect、または circle) をドラッグ可能にして、サイズ変更ハンドルを付与できるようにしたいと考えています。

ただし、HTML DOM とは異なり、すべての要素が左上隅の x、y 座標と、コンテンツを囲むボックスの幅と高さを持っているわけではありません。これにより、一般的なサイズ変更またはドラッグ手順を作成するのが不便になります。

各パスまたは円を独自の svg オブジェクト内に描画して、遊ぶためのボックスを提供することは良い考えですか?

ドラッグ可能/サイズ変更可能は通常、SVG でどのように実装されていますか?

4

4 に答える 4

54

注: ドラッグとサイズ変更の両方について、特定の異なるタイプの要素に対して個別のケースを作成する必要があります。後で提供する例を見てください。これは、同じ関数セットで楕円と四角形の両方のドラッグを処理します。


要素をドラッグ可能にするには、次を使用します。

element.drag(move, start, up);

3 つの引数は、移動 (ドラッグ)、開始 (マウスダウン)、および停止 (マウスアップ) を処理する関数への参照です。

たとえば、ドラッグ可能な円を作成するには (ドキュメントから):

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プロパティが要素に付けられてその位置を追跡します。これらのプロパティは と と組み合わせてdx使用dy​​され、要素がドラッグされているときに要素の位置を変更します。

この質問に答えるには、より複雑なドラッグ アンド ドロップが必要です。

オブジェクトをサイズ変更可能にするには、リサイズ用のドラッグ アンド ドロップ メソッドの 2 番目のセットを作成し、リサイズのドラッグに基づいてターゲット要素heightを調整するだけです。width

これは、私が書いたドラッグアンドドロップとサイズ変更可能なボックスでいっぱいです:

ドラッグ アンド ドロップとサイズ変更可能なボックスの 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 キャンバスを 1 つ作成するだけで、各アイテムが異なる要素になります。上記の例のように、それらを変数に割り当てるだけで処理できます (cは、作成された circle 要素を参照するために使用されました)。

コメントへの回答として、ドラッグ アンド ドロップ + サイズ変更可能な円を簡単に使用できます。トリックは、円が属性cxを使用してcy、配置と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 に答える