【问题标题】:HTML5 Drag-and-Drop: How do I target the cloned AND original elements?HTML5 拖放:如何定位克隆和原始元素?
【发布时间】:2012-06-15 17:03:03
【问题描述】:

我想将类名应用到被拖动的“ghost”元素,而不是被克隆的原始元素。这是我为dragstart 事件设置的函数:

function dragStart(event) {
    event.originalEvent.dataTransfer.effectAllowed = 'move';
    event.originalEvent.dataTransfer.setData("text/plain", event.target.getAttribute('id'));
    console.log(event);
    console.log('Dragging...');
    $(event.currentTarget).addClass('dragging');
    return true;
}

$(event.currentTarget).addClass('dragging'); 行将 .dragging 类添加到原始元素,而不是克隆的拖动元素。

如何正确定位两者?

编辑

希望尽可能使用原生 HTML5 来处理这个问题。最好不要使用 jQuery 插件。

【问题讨论】:

  • 虽然我以前实际上没有做过类似的事情,但对我来说,您所指的“幽灵”元素听起来像是可以用event.dataTransfer.setDragImage(image, xOffset, yOffset); 覆盖的图像/画布。这是基于来自MDN 的信息。
  • 绝对正确,但我希望能够设置克隆或“幽灵”元素的样式,而不是完全替换它......听起来这可能是不可能的。
  • 您是否尝试过复制目标对象(在 JavaScript 中),将您的类添加到副本中,然后将其传递给 setDragImage 方法?虽然它声明第一个参数是图像,但我认为它的真正含义是“生成图像使用什么 DOM 元素”。
  • 您已经在使用 jQuery 并且不想使用插件。这是否意味着你不能使用更多的 jQuery?你真的不应该在你的例子中使用 jQuery。

标签: html css drag-and-drop


【解决方案1】:

在原始元素上添加类,然后在拖动开始后将其删除(demo):

function dragStart(event) {
    var el = $(this);

    event.originalEvent.dataTransfer.effectAllowed = 'move';
    event.originalEvent.dataTransfer.setData("text/plain", event.target.getAttribute('id'));

    el.addClass('dragging');
    setTimeout(function() { el.removeClass('dragging'); }, 0);
}

【讨论】:

  • 我想过这个问题,这可能是最好的解决方法。一旦你开始拖动,肯定会在开始时出现闪烁,但我怀疑一些 CSS 调整可以解决这个问题。
【解决方案2】:

我不是一个*的 JavaScript 脚本编写者,但我在尝试为您找到一些东西时偶然发现了这个页面,它可能是您需要的,特别是代理拖动版本:

http://threedubmedia.com/demo/drag/

$('#demo6_box')
        .bind('dragstart',function( event ){
                if ( !$(event.target).is('.handle') ) return false;
                return $( this ).css('opacity',.5)
                        .clone().addClass('active')
                        .insertAfter( this );
                })
        .bind('drag',function( event ){
                $( event.dragProxy ).css({
                        top: event.offsetY,
                        left: event.offsetX
                        });
                })
        .bind('dragend',function( event ){
                $( event.dragProxy ).remove();
                $( this ).animate({
                        top: event.offsetY,
                        left: event.offsetX,
                        opacity: 1
                        })
                });

这都是 jQuery。

【讨论】:

  • 是的,我正在尝试尽可能多地使用原生 HTML5。
  • 我认为包含 jquery 没有问题,它非常强大,而且比普通的 javascript 简单得多。但你的问题,你的规则。
  • 这根本不是问题——我实际上包括在内——我只是希望尽可能多地使用本机功能。
  • 好吧,我想每个开发人员都按照自己的标准工作,无论如何祝你好运(我本来打算放一个笑脸,但后来我意识到这是一个严肃的问答板)
【解决方案3】:

我知道这个问题很老,但您需要做的是根据https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer#setDragImage.28.29 创建/使用可见元素(或图像/画布等)

因此,您可以获取当前拖动的元素(通常在事件上下文中为 this),克隆它,将其添加到 dom(确保它是“可见的”,也就是不是 display: nonevisibility:hidden)和然后,您可以对其应用一个类,以便您可以在 css 中定位拖动的项目本身。然后,将该元素作为第一个参数添加到e.dataTransfer.setDragImage(),浏览器将使用它。

请记住稍后将其删除 (dragend) 或以某种方式隐藏它。

这是一个实际操作的小提琴:http://jsfiddle.net/6TDvz/

【讨论】:

    【解决方案4】:

    从这行代码:

    event.originalEvent
    

    您似乎在使用 jquery?所以只要考虑 jquery 让事情变得更容易并且是跨浏览器兼容的。

    实现拖动的 HTML5 本机和 jquery 方法(仅使用 javascript)几乎相同。 HTML5 只添加了拖动事件,但没有添加更多的拖放方法:

    没有 jquery:

    function dragStart(event) {
        event.originalEvent.dataTransfer.effectAllowed = 'move';
        event.originalEvent.dataTransfer.setData("text/plain", event.target);//JUST ELEMENT references is ok here NO ID
        console.log(event);
        console.log('Dragging...');
    
        var clone = event.target.cloneNode(true);
        event.target.parentNode.appendChild(clone);
        event.target.ghostDragger = clone;//SET A REFERENCE TO THE HELPER
    
        $(clone).addClass('dragging');//NOW YOU HAVE A CLONE ELEMENT JUST USE this and remove on drag stop
        return true;
    }
    
    function dragging(event){
      var clone = event.target.ghostDragger;
      //here set clone LEFT and TOP from event mouse moves
    }
    //ON STOP REMOVE HELPER ELEMENT
    function stopDrag(event){
      var clone = event.target.ghostDragger;
      clone.parentNode.removeChild(clone);
    }
    

    使用 jquery:

    $( "#draggable" ).draggable({ 
     helper: "clone", //EVEN here you can set the helper you want by defining a funcition
     start:function(event, ui){
       ui.helper.addClass('yourclass');
     }
    });
    

    尽管我建议使用 jquery ui 进行拖动。有了它,您可以根据需要个性化拖动助手。

    【讨论】:

    • 对我来说,在 chrome 中这个样式是原始元素。
    【解决方案5】:

    我可能遗漏了一些东西,但以下内容对我有用,为原始文本和拖动文本提供黄色背景(通过设置类)。也许在您的特定情况下有些东西给了您一个“幽灵”副本。或者它可能与您已经在使用的少量 jQuery 有关。我只能说,在尝试重现您的问题时,我的简单测试用例实际上运行良好。

    <!DOCTYPE html>
    <html>
      <head>
        <title>Drag Test</title>
        <script>
          function startDrag(event) {
            var orig = document.getElementById('original');
            var dt = event.dataTransfer;
    
            orig.className += 'dragging';
    
            dt.effectAllowed = 'move';
            dt.setData('text/plain', 'This text may be dragged');
          }
        </script>
    
        <style>
          .dragging {
            background-color: yellow;
          }
        </style>
      </head>
    
      <body>
        <div id="original"  draggable="true" ondragstart="startDrag(event);">
          This text may be dragged.
        </div>
      </body>
    </html>
    

    【讨论】:

      【解决方案6】:

      你说:

      我想为被拖动的“ghost”元素应用一个类名,而不是 被克隆的原始元素

      嗯,正常的拖放没有原始元素和克隆元素,只有被拖动的元素。没有看到其余的拖放实现,没有办法给你答案。我们不知道正在调用什么“事件”。如果您的dragStart 事件是HTML5 ondragstart event,那么this article 可能会帮助您。但是,如果它是由 jQuery 或其他框架创建的自定义事件,那么除非您共享其余代码,否则任何人都无法告诉您如何获取原始元素和克隆元素。

      如果您不想依赖 jQuery,那么您将不得不从头开始编写整个拖放功能。以下是一些有关如何执行此操作的教程:

      JavaScript Drag and Drop Tutorial

      Drag & Drop Sortable Lists w/ JavaScript

      HTML5 Drag & Drop

      如果我可以提出建议,那就是坚持使用 jQuery。从头开始制作一个跨浏览器兼容的拖放系统需要大量时间。如果您共享其余代码,那么我可以尝试为您提供更具体的答案。

      【讨论】:

        最近更新 更多