web-dev-qa-db-ja.com

JQueryおよびJquery-svgを使用してドラッグ可能なSVG

SvgサークルをロードするHTML 5ページがあります。円をクリックすると、クリックする別の小さな円が作成されます。 2番目の円をドラッグできるようにしたいのですが、jquery-ui .draggable();でドラッグできないようです。

Cxおよびcy属性にアクセスして円を移動できるので、円をドラッグする方法が必要です。

    <!DOCTYPE HTML> 
<html >
<head>
<title></title>
<link href="css/reset.css" rel="stylesheet" type="text/css">
<link href="css/layout.css" rel="stylesheet" type="text/css">
<link href="css/style.css" rel="stylesheet" type="text/css">
<script src="js/jquery.js" type="text/javascript" ></script>
<script src="js/jquerysvg/jquery.svg.js" type="text/javascript" ></script>
<script src="js/jquery-ui.js" type="text/javascript" ></script>
<script type="text/javascript" >
jQuery(document).ready(function(){
    $('#target').svg({onLoad: drawInitial});
    $('circle').click(function(e){
        drawShape(e);
        var shape = this.id;

    });

    $('.drag').mousedown(function(e){
        var shape = this.id;
        this.setAttribute("cx", e.pageX);
        this.setAttribute("cy", e.pageY);
    });
})

function drawInitial(svg) {
    svg.add($('#svginline')); 
}

function drawShape(e) {
    var svg = $("#target").svg('get');
    $('#result').text(e.clientX + ": " +  e.pageX);
    var dragme = svg.circle(e.clientX, e.clientY, 5, {fill: 'green', stroke: 'red', 'stroke-width': 3, class_: 'drag'});    
    //$(dragme).draggable();
}
</script>
</head>
<body>
    <div id="target" ></div>
    <svg:svg id="svginline">
        <svg:circle id="circ11" class="area" cx="75" cy="75" r="50" stroke="black" stroke-width="2" fill="red"/>
    </svg:svg>
    <div id="result" >ffff</div>
</body>
</html>
33
skyfoot

jQuery UIのドラッグ可能な動作は機能しますが、相対CSSの配置はSVG内では機能しないため、ドラッグハンドラーで手動で位置を更新する必要があります。

svg.rect(20,10,100,50, 10, 10, {fill:'#666'});
svg.rect(40,20,100,50, 10, 10, {fill:'#999'});
svg.rect(60,30,100,50, 10, 10, {fill:'#ccc'});

$('rect')
  .draggable()
  .bind('mousedown', function(event, ui){
    // bring target to front
    $(event.target.parentElement).append( event.target );
  })
  .bind('drag', function(event, ui){
    // update coordinates manually, since top/left style props don't work on SVG
    event.target.setAttribute('x', ui.position.left);
    event.target.setAttribute('y', ui.position.top);
  });
46
tkdave

このリンク は、一般的に(つまり、JQueryを必要とせずに)問題を解決する方法についての優れた説明を持っています。しかし、私はJQueryの優れたDraggable APIを使い続けたいと思っていました。

私は最近、この問題を数日間叩きました。上記の受け入れられた答えは最初に試したものですが、Firefoxで正しく動作させることができませんでした。 ブラウザの処理方法に関するもの SVGの調整方法は異なります。

ChromeとFirefoxの両方でかなりうまく機能するソリューションを思いついたので、JQuery UIを使い続けることができます。私はどこでもテストしていません。間違いなくハックです。

私がフィドルでやったことの簡単なモックアップを見ることができます here 。重要なアイデアは、ドラッグするsvg要素の上に正確にホバーし続けるプロキシdivを使用することです。次に、プロキシdivをドラッグするときに、svg要素のx座標とy座標を変更します。このようなもの:

$('#proxy').on('drag', function(e)
    {
        t = $('#background');
        prox = $('#proxy');
        t.attr('x', t.attr('x')*1
                   + prox.css('left').slice(0,-2)*1
                   - prox.data('position').left)
            .attr('y', t.attr('y')*1
                      + prox.css('top').slice(0,-2)*1
                      - prox.data('position').top);
        prox.data('position',{top : prox.css('top').slice(0,-2)*1,
                              left: prox.css('left').slice(0,-2)*1}
                  );
    });

私の場合、ドラッグしたいSVG要素は常に画面上の特定の四角形を埋めるので、プロキシdivをターゲットの上に配置するのは非常に簡単でした。他の状況では、それははるかに難しいかもしれません。フレームの外に背景をドラッグしないようにするために 'containment'オプションを使用することもそれほど難しくありません...いくつかの注意深い計算が必要で、各ドラッグの間に包含をリセットする必要があります。

これをより多くのSVG要素に適用できるようにするには、x座標とy座標ではなく変換を使用できます。

2
galdre

私がいじくり回している解決策は、(それをあなたのケースに結び付けるために)対象のsvgオブジェクトのハンドルとして機能する、元の形状の上に配置された新しいdivとsvgを作成することです。ハンドルdivをドラッグ可能にして、開始の上部/左オフセットを外部に保存します(非表示のdivを考えてください)。ドラッグ可能なdivの「stop」イベントが発生したら、上部と左側の変更の程度(stopX-startX = changeX)を把握し、それを元の形状座標に適用します。次に、一時的な形状を.remove()します。

2
Mike

私のsvgオブジェクトをターゲットにする基本的なドラッグドロップ関数を作成しました。封じ込めや衝突検出はありません。マウスを素早く動かしすぎると、ドラッグ可能なオブジェクトを残してしまうという問題があります。

<!DOCTYPE HTML> 
<html >
<head>
<title></title>
<link href="css/reset.css" rel="stylesheet" type="text/css">
<link href="css/layout.css" rel="stylesheet" type="text/css">
<link href="css/style.css" rel="stylesheet" type="text/css">
<script src="js/jquery.js" type="text/javascript" ></script>
<script src="js/jquery-ui.js" type="text/javascript" ></script>
<script src="js/jquerysvg/jquery.svg.js" type="text/javascript" ></script>
<script src="js/jquerysvg/jquery.svgdom.js" type="text/javascript" ></script>

<script type="text/javascript" >
jQuery(document).ready(function(){
    $('#target').svg({onLoad: drawInitial});
    $('circle').click(function(e){
        drawShape(e);
        var shape = this.id;

    }); 
})

function drawInitial(svg) {
    svg.add($('#svginline')); 
}

function onMouseDown(evt){
        //var shape = this.id;

        var target = evt.target;        
        target.onmousemove = onMouseMove; 

        return false; 
}

function onMouseMove(evt){
    circle = evt.target

    var cx = circle.getAttribute("cx");
    offsetX = $('#target').offset().left;
    offsetY = $('#target').offset().top
    circle.setAttribute("cx", evt.clientX -offsetX);
    circle.setAttribute("cy", evt.clientY - offsetY);

    circle.onmouseup = OnMouseUp;
}

function OnMouseUp(evt) { 
    var target = evt.target;        
    target.onmousemove = null; 
}

function drawShape(e) {
    var svg = $("#target").svg('get');
    offsetX = $('#target').offset().left;
    offsetY = $('#target').offset().top;
    $('#result').text(e.clientX + ": " +  e.pageX);
    var dragme = svg.circle(e.clientX - offsetX, e.clientY - offsetY, 5, {onmousedown: "onMouseDown(evt)",fill: 'green', stroke: 'red', 'stroke-width': 3});    
    $(dragme).addClass('drag');
}
</script>
</head>
<body>
    <div id="target" ></div>
    <svg:svg id="svginline">
        <svg:circle id="circ11" class="area" cx="75" cy="75" r="50" stroke="black" stroke-width="2" fill="red"/>
    </svg:svg>
    <div id="result" >ffff</div>
</body>
</html>
1
skyfoot

ドラッグ可能なdivにsvgを置くだけです。

//*
$(document).ready(function(){
  $('#mydiv').draggable();
});
//*/
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<div id="mydiv">
  <svg xml:lang="en"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <text class="main" x="10" transform="rotate(-28 0 0)" y="90">Sol min</text>
    <text class="sous" x="4" y="110" transform="rotate(-28 0 20)">(SOUS DOM.)</text>
   <line stroke="black" stroke-width="2" x1="10" y1="100" x2="110" y2="46" />
   <line stroke="red" stroke-width=2 x1=10 y1=99 x2=10 y2=140 />
 </svg>
</div>
0
Philippe Perret