【问题标题】:SVG draggable using JQuery and Jquery-svg使用 JQuery 和 Jquery-svg 可拖动的 SVG
【发布时间】:2009-07-10 08:54:55
【问题描述】:

我有一个 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>

【问题讨论】:

    标签: jquery jquery-ui svg


    【解决方案1】:

    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】:

      我正在修改的解决方案涉及(将其与您的情况联系起来)创建一个新的 div 和 svg,位于原始形状上,作为目标 svg 对象的句柄。使句柄 div 可拖动并在外部存储起始顶部/左侧偏移量(想想隐藏的 div)。触发可拖动 div 的“停止”事件后,计算顶部和左侧的变化程度(stopX-startX=changeX)并将其应用于原始形状坐标。然后 .remove() 你的临时形状。

      【讨论】:

        【解决方案3】:

        This link 很好地描述了如何解决一般问题(即,不需要 JQuery),这绝对是我见过的最好的解决方案。但是,我想继续使用 JQuery 出色的 Draggable API。

        我最近花了几天时间来解决这个问题。上面接受的答案是我首先尝试的,但我无法让它在 Firefox 中正常工作。 something about how browsers handle SVG 坐标不同。

        我想出了一个在 Chrome 和 Firefox 中都非常适合我的解决方案,让我可以继续使用 JQuery UI。我没有到处测试过。这绝对是一个 hack。

        您可以看到我在小提琴here 中所做的快速模型。关键思想是使用代理 div,您可以将其准确悬停在要拖动的 svg 元素上。然后在拖动代理 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 定位在目标上非常容易。在其他情况下,这可能要困难得多。使用“遏制”选项来确保您不会将背景拖到框架之外也不是太难……它只需要一些仔细的数学运算,并且您必须在每次拖动之间重置遏制。

        要使其适用于更多 SVG 元素,您可以使用变换而不是 x 和 y 坐标。

        【讨论】:

          【解决方案4】:

          我创建了一个基本的拖放功能来定位我的 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>
          

          【讨论】:

          • 我收到了来自创建 jquerysvg keith-wood.name/svg.html 的 Keith Wood 的回复:“我正在努力让 jQuery 与 SVG DOM 一起工作,这与设计 jQuery 的 HTML DOM 略有不同。这将允许将 jQuery 事件处理程序附加到 SVG 元素。它不会显式实现拖放,但它将有助于使用 jQuery 这样做。我将牢记拖放功能以备将来使用释放。”
          • 因为观看次数太多,我想我会更新这个。我在 silverlight 中创建了类似的功能,并且在我使用 silverlights Mouse Capture 之前,拖放也很复杂。我不确定 Mouse Capture 方法会发生什么,但如果它可以在 jquery 中实现,那么这将解决拖放问题。
          • 它完美运行@skyfoot。但是有两对坐标的线,即 (x1,y1) 和 (x2,y2) 而不是像圆 (cx,cy) 这样有一个坐标的线呢?谢谢。
          • @kamal 这在 IE8 中不起作用。我不相信 svg 在 IE8 中有效
          • 是否有任何插件或类似的东西,以便我们可以在 IE8 上加载 svg
          【解决方案5】:

          只需将 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>

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-05-03
            • 2017-07-21
            • 2016-05-03
            • 2017-05-26
            • 2018-03-20
            • 2023-03-09
            • 2014-04-02
            • 2012-07-05
            相关资源
            最近更新 更多