SVG перетаскивается с использованием JQuery и Jquery-svg - PullRequest
33 голосов
/ 10 июля 2009

У меня есть страница HTML 5, где я загружаю кружок SVG. Когда я нажимаю на круг, я создаю еще один маленький круг, где я нажимаю. Я хочу иметь возможность перетаскивать второй круг, но, кажется, не могу сделать это с помощью 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>

Ответы [ 5 ]

46 голосов
/ 29 мая 2011

Поведение перетаскивания в 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);
  });
2 голосов
/ 21 июня 2013

Эта ссылка содержит отличное описание того, как решить проблему в целом (то есть, не требуя JQuery), и это определенно лучшее решение, которое я видел. Тем не менее, я хотел продолжать использовать превосходный Draggable API JQuery.

Я недавно провел пару дней, пытаясь решить эту проблему. Принятый ответ выше - то, что я попробовал сначала, но я не мог заставить его работать прямо в Firefox. кое-что о том, как браузеры обрабатывают SVG-координаты по-разному.

Я придумал решение, которое довольно хорошо работало для меня, как в Chrome, так и в Firefox, и позволяет мне продолжать использовать пользовательский интерфейс JQuery. Я не проверял это везде. Это определенно хак.

Вы можете увидеть быстрый макет того, что я сделал в скрипке здесь . Основная идея заключается в том, чтобы использовать прокси-элемент div, который вы постоянно удерживаете над элементом svg, который хотите перетащить. Затем вы изменяете координаты x и y элемента svg при перетаскивании прокси-элемента div. Примерно так:

$('#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 над целью. В других ситуациях это может быть намного сложнее. Также не слишком сложно использовать опцию «сдерживание», чтобы убедиться, что вы не перетаскиваете фон за пределы рамки ... это просто требует некоторой тщательной математики и вам необходимо сбросить удерживание между каждым перетаскиванием.

Чтобы сделать это применимым к большему количеству элементов SVG, вы можете использовать преобразования, а не координаты x и y.

2 голосов
/ 30 сентября 2010

Решение, с которым я работаю, заключается в том, чтобы (привязать его к вашему делу) создать новый div и svg, расположенные над исходной формой, которые будут действовать как дескриптор для целевого объекта svg. Сделайте ручку div перетаскиваемой и сохраните начальный верх / левое смещение внешне (представьте себе скрытый div). После того, как событие «стоп» для перетаскиваемого элемента div запущено, выясните степень изменения для верхнего и левого (stopX-startX = changeX) и примените это к исходным координатам фигур. Затем .remove () ваша временная фигура.

1 голос
/ 10 июля 2009

Я создал базовую функцию перетаскивания, предназначенную для моих объектов 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>
0 голосов
/ 19 января 2019

Просто поместите svg в перетаскиваемый div.

//*
$(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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...