如何将子元素以外的元素用作拖动手柄?

Posted

技术标签:

【中文标题】如何将子元素以外的元素用作拖动手柄?【英文标题】:How to use other than a child element as a drag handle? 【发布时间】:2012-10-03 14:13:28 【问题描述】:

我有以下代码 (jsfiddled)。我想使用红色 SVG 矩形作为可拖动 div 元素的句柄,但是因为 SVG 元素不是 div 的子元素,所以这是不可能的。这个想法是让手柄(红色矩形)触发 div 的拖动事件,当拖动 div 时,代码会更新红色 SVG 矩形的位置。 如何让 SVG 矩形充当 div 的拖动句柄(使 SVG 元素不是 div 元素的子元素)?

我已经测试过让 SVG 成为 div 的子对象,并使用 SVG rect 作为句柄,这可以正常工作。当我拖动 SVG 矩形时,拖动时会移动 div 和 SVG 矩形。但问题是 SVG 元素本身也被拖动了。但我不希望 SVG 元素本身在拖动时移动,只移动 rect 和 div。

编辑:我想到了在 svg rect 上按下鼠标时触发 div 的某种拖动事件作为一种可能的解决方案,但尚未测试。

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>jQuery UI Draggable - Handles</title>
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.9.0/themes/base/jquery-ui.css" />
        <script src="http://code.jquery.com/jquery-1.8.2.js"></script>
        <script src="http://code.jquery.com/ui/1.9.0/jquery-ui.js"></script>
        <style>
            #draggable  position:absolute; opacity:0.5;
    width: 100px; height: 100px; padding: 0.5em; float: left; margin: 0 10px 10px 0; 
           #draggable p  cursor: move; 
           #draggable left:30px;top:0px;z-index:1
        </style>
        <script>
            $(function() 
                $( "#draggable" ).draggable( handle: "p" );
                $( "div, p" ).disableSelection();
            );
        </script>
    </head>
    <body>
        <div id="draggable" class="ui-widget-content">
            <p class="ui-widget-header">I can be dragged only by this handle</p>
        </div>
        <svg   style="position:absolute;z-index:-1">
            <rect x="0" y="0"   fill="#FF8888"/>
        </svg>
    </body>
</html>

【问题讨论】:

我不明白你的问题。如果 svg 不应该被拖动,你想如何将它用作句柄?如果手柄不动,目标为什么要动? SVG 元素是“顶部”元素,就像 BODY 元素一样。它们不应该被移动,只有红色矩形是 SVG 元素的子元素和 div 是 BODY 元素的子元素。 好的,现在我明白了。您可能想看看以下问题:***.com/questions/5744068/…. 接受的答案是“一种可能的解决方案是将手柄放在里面,但使用 css 将其放在外面。”这似乎意味着句柄应该是 div 的子级。但我不明白如何在我的问题中适应这个原则。如何将 SVG rect 附加到 div 的子元素,但不拖动 SVG 根元素? 您需要 jQuery UI draggable 提供的任何额外功能吗?在这种情况下,在 puer javascript 中实现更简单。 【参考方案1】:

经过一些测试,我最终使用了div.trigger(e) 的组合,并在可拖动div 的拖动功能this jsfiddled way 中更新了SVG rect 的transform 属性。

关键点如下代码,当鼠标在SVG路径元素上按下时触发div的拖动事件:

$("#path_1").mousedown(function(e) 
    $( "#div_1" ).trigger(e);
);

另外一个关键点如下,更新了SVG路径元素的transform属性来实现移动:

drag: function(e, ui)

    var x=$( "#div_1" )[0].style.left;
    var y=$( "#div_1" )[0].style.top;
    x = parseInt(x);
    y = parseInt(y);
    $( "#path_1" ).attr("transform", "translate("+x+","+y+")");

它依赖于 div 中的pointer-events:none,因此在 Opera 中不起作用,但在其他新浏览器中可以。有a hack 允许pointer-events:none,但最好等待所有最新的浏览器本机允许它。在问题的示例中,指针事件不是问题,因为红色矩形没有完全低于 div。

Jsfiddle example 可以扩展为例如。如果您想使用 jQuery Draggable 插件来拖动 SVG 的图形对象并想使用 div 作为选择矩形,请为 SVG 元素制作选择矩形功能。 (选择矩形的其他可能解决方案是使用两个 SVG 根元素,一个用于选择矩形,一个用于实际形状。)

而using setTimeout() 我们可以强制在移动 div 时始终移动 SVG 路径。

【讨论】:

以上是关于如何将子元素以外的元素用作拖动手柄?的主要内容,如果未能解决你的问题,请参考以下文章

如何将子元素作为解码字符串添加到 XElement?

PHP DOM 将子元素附加到根

csharp 内容生成器的示例代码,用于将子文本元素添加到当前元素

拖动子元素时触发 Svelte 可拖动,onleave 事件

仅使用 CSS 而没有 JS [重复] 将子元素的高度设置为父 div

jQuery,zepto手机端用on将子元素事件委托给body或document无效