【问题标题】:HTML5 Drag and Drop anywhere on the screenHTML5 拖放到屏幕上的任意位置
【发布时间】:2011-09-08 00:27:41
【问题描述】:

我有一个用 JavaScript 为我正在处理的项目编写的调试器日志。日志基本上是 HTML5 中的 <aside> 标记,仅在需要时显示。我想尝试一下能够在屏幕上移动日志的想法,因为它可能会重叠某些东西(这对我的项目来说很好)。但是,我似乎无法弄清楚如何使用 HTML5 正确拖放标签,以便可以将其放置在屏幕上的任何位置(嗯,或者在 <div> 元素内)。

在阅读了 HTML5 的拖放支持之后,我对它的工作原理有了基本的了解,但是我不确定在允许将 div 放置在任何地方时从哪里开始(它的 z-index 很高值,正如我所说,重叠很好)。

有什么建议吗?

哦,我想尽可能避免在这个项目中使用外部库。我正在尝试在纯 JavaScript/HTML5 中执行此操作。

【问题讨论】:

  • 您尝试过任何教程吗?例如this.
  • 是的,事实上,我已经打开了该选项卡。我应该说我略读了它,而不是完全遵循它,但对我来说,看起来他们基本上是在重新组织他们的专栏内容。我想要做的是让一个元素移动到屏幕上的任何位置,并保持在那个新位置。
  • 可能是一层重叠的 div/"columns"(为了让 drop 更准确)继承了调试器日志标签的大小并覆盖了整个页面。
  • 或者,您可以使用一点 CSS 来更改位置。可能没有那种 dnd yumminess,但它肯定能够重新定位您的数据。

标签: javascript html drag-and-drop


【解决方案1】:

拖放不会移动元素,如果您希望元素在放置时移动,则必须在放置事件中设置元素的新位置。我有 done an example 可以在 Firefox 和 Chrome 中使用,这里是关键点:

function drag_start(event) {
    var style = window.getComputedStyle(event.target, null);
    event.dataTransfer.setData("text/plain",
    (parseInt(style.getPropertyValue("left"),10) - event.clientX) + ',' + (parseInt(style.getPropertyValue("top"),10) - event.clientY));
} 

dragstart 事件计算出鼠标指针与元素左侧和顶部的偏移量,并将其传递给dataTransfer。我不担心传递 ID,因为页面上只有一个可拖动元素 - 没有链接或图像 - 如果你的页面上有任何这些东西,那么你将不得不在这里做更多的工作。

function drop(event) {
    var offset = event.dataTransfer.getData("text/plain").split(',');
    var dm = document.getElementById('dragme');
    dm.style.left = (event.clientX + parseInt(offset[0],10)) + 'px';
    dm.style.top = (event.clientY + parseInt(offset[1],10)) + 'px';
    event.preventDefault();
    return false;
}

drop 事件解包偏移量并使用它们相对于鼠标指针定位元素。

当任何东西被拖过去时,dragover 事件只需要preventDefault。同样,如果页面上还有其他可拖动的内容,您可能需要在此处执行更复杂的操作:

function drag_over(event) {
    event.preventDefault();
    return false;
} 

因此将其绑定到document.body 以及drop 事件以捕获所有内容:

var dm = document.getElementById('dragme');
dm.addEventListener('dragstart',drag_start,false);
document.body.addEventListener('dragover',drag_over,false);
document.body.addEventListener('drop',drop,false); 

如果您希望它在 IE 中工作,您需要将 aside 转换为 a 元素,当然,所有事件绑定代码都会有所不同。据我所知,拖放 API 在 Opera 或任何移动浏览器上都不起作用。另外,我知道你说过你不想使用 jQuery,但是跨浏览器事件绑定和操作元素位置是 jQuery 让事情变得更容易的事情。

【讨论】:

  • 这段代码是否可以一次使用多个拖动山墙框?
  • 如果你有多个可拖动的盒子怎么办?
  • 如果您希望它在 IE 10 和 11 中工作,请将 setData 和 getData 中的第一个参数从“text/plain”更改为“text”。 jsfiddle.net/131udfnm/1
  • 这可以支持一个包含 50 多个项目的大型库吗?
【解决方案2】:

感谢您的回答。它在 Chrome 和 Firefox 中运行良好。我对其进行了调整以在 IE 中工作。下面是代码。

 <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta name="generator" content="CoffeeCup HTML Editor (www.coffeecup.com)">
        <meta name="dcterms.created" content="Fri, 27 Jun 2014 21:02:23 GMT">
        <meta name="description" content="">
        <meta name="keywords" content="">
        <title></title>
        
        <!--[if IE]>
        <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    	<style>
    	li
    	{ 
          position:  absolute;
          left: 0;
          top: 0; /* set these so Chrome doesn't return 'auto' from getComputedStyle */
          width: 200px; 
          background: rgba(255,255,255,0.66); 
          border: 2px  solid rgba(0,0,0,0.5); 
          border-radius: 4px; padding: 8px;
    	}
    	</style>
    	<script>
            function drag_start(event) {
                var style = window.getComputedStyle(event.target, null);
                var str = (parseInt(style.getPropertyValue("left")) - event.clientX) + ',' + (parseInt(style.getPropertyValue("top")) - event.clientY) + ',' + event.target.id;
                event.dataTransfer.setData("Text", str);
            }

            function drop(event) {
                var offset = event.dataTransfer.getData("Text").split(',');
                var dm = document.getElementById(offset[2]);
                dm.style.left = (event.clientX + parseInt(offset[0], 10)) + 'px';
                dm.style.top = (event.clientY + parseInt(offset[1], 10)) + 'px';
                event.preventDefault();
                return false;
            }

            function drag_over(event) {
                event.preventDefault();
                return false;
            }
    	</script>
      </head>
      <body ondragover="drag_over(event)" ondrop="drop(event)">
       <ul>
              <li id="txt1" draggable="true" ondragstart="drag_start(event)"> Drag this text </li><br>
              <li id="txt2" draggable="true" ondragstart="drag_start(event)"> Drag me</li>
      </ul>
      	   <p>I never am really satisfied that I understand anything; because, understand it well as I may, my comprehension can only be an infinitesimal fraction of all I want to understand about the many connections and relations which occur to me, how the matter in question was first thought of or arrived at, etc., etc.</p>
      	   <p>In almost every computation a great variety of arrangements for the succession of the processes is possible, and various considerations must influence the selections amongst them for the purposes of a calculating engine. One essential object is to choose that arrangement which shall tend to reduce to a minimum the time necessary for completing the calculation.</p>
      	   <p>Many persons who are not conversant with mathematical studies imagine that because the business of [Babbage’s Analytical Engine] is to give its results in numerical notation, the nature of its processes must consequently be arithmetical and numerical, rather than algebraical and analytical. This is an error. The engine can arrange and combine its numerical quantities exactly as if they were letters or any other general symbols; and in fact it might bring out its results in algebraical notation, were provisions made accordingly.</p>
      	   <p>The Analytical Engine has no pretensions whatever to originate anything. It can do whatever we know how to order it to perform. It can follow analysis, but it has no power of anticipating any analytical revelations or truths. Its province is to assist us in making available what we are already acquainted with.</p>
    
      </body>
   </html>

【讨论】:

    【解决方案3】:

    我稍微调整了 robertc 对于多个项目的情况的最佳答案。这里的secondclass 名称只是用于另一个位置。

    <aside draggable="true" class="dragme" data-item="0">One</aside>
    <aside draggable="true" class="dragme second" data-item="1">Two</aside>
    

    将 data-item 属性添加到setDatafunction。

    function drag_start(event) {
      var style = window.getComputedStyle(event.target, null);
      event.dataTransfer.setData("text/plain", (parseInt(style.getPropertyValue("left"), 10) - event.clientX) + ',' + (parseInt(style.getPropertyValue("top"), 10) - event.clientY) + ',' + event.target.getAttribute('data-item'));
    }
    

    定位被拖动的元素。

    function drop(event) {
      var offset = event.dataTransfer.getData("text/plain").split(',');
      var dm = document.getElementsByClassName('dragme');
      dm[parseInt(offset[2])].style.left = (event.clientX + parseInt(offset[0], 10)) + 'px';
      dm[parseInt(offset[2])].style.top = (event.clientY + parseInt(offset[1], 10)) + 'px';
      event.preventDefault();
      return false;
    }
    

    并循环使用类dragme的所有元素。

    var dm = document.getElementsByClassName('dragme');
    for (var i = 0; i < dm.length; i++) {
      dm[i].addEventListener('dragstart', drag_start, false);
      document.body.addEventListener('dragover', drag_over, false);
      document.body.addEventListener('drop', drop, false);
    }
    

    pen

    【讨论】:

      猜你喜欢
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      • 1970-01-01
      • 2014-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多