是否需要画布?

时间:2016-03-22 06:47:44

标签: html5 drag-and-drop canvas

我一直在使用HTML5拖放和画布。我试图将两者放在一起:我将一个元素拖到一个下降区域;在下拉区域,我希望能够移动掉落的物品以根据需要定位它们。

我知道如何将元素放入div中,例如,但是:

  1. 下拉区域必须是(重新)定位的画布吗?

  2. 是否有一个特定的术语,用于在放置区/画布中移动/重新定位元素。我已经做了很多搜索,但却找不到具体的术语。只需拖动'

  3. sample drop-area

2 个答案:

答案 0 :(得分:1)

链接的canvas demo需要canvas元素,但您也可以使用html + JS中内置的drag/drop API。你可以手动"使用鼠标事件移动DOM对象,如Kaiido的回答中所述。

您的链接演示需要使用画布。

使用canvas元素的绘图功能对该精确演示进行了编码,如果您尝试替换DIV,则无法使用精确的演示。

将html5 canvas视为可重写位图。你不能移动"或者"拖动"画布上的任何东西。相反,您将完全擦除画布表面并在新位置重绘圆圈。

在拖动的情况下,您在画布上侦听mousemove事件,并在鼠标下方重新定位自上次mousemove事件以来鼠标移动的距离。

答案 1 :(得分:1)

无论如何都不需要canvas元素。

您可以在不使用任何画布的情况下获得与您提供的linked example完全相同的结果。

这是一个示例代码,在许多其他可能的情况下,肯定远非完美,但它与您的示例相同,仅使用<div>元素,css和javascript,但它也可以使用svg

// we will increment it to get the dragged element atop of everything
var zIndex = 0;

// our constructor
var newElement = function() {
  var that = {};
  // first get its dimension and position randomly
  that.rad = Math.random() * 20 + 10;
  // x and y are the center of our element
  that.x = Math.random() * (500 - that.rad * 2) + that.rad;
  that.y = Math.random() * (300 - that.rad * 2) + that.rad;
  // define the element that will be appended to the doc
  that.el = document.createElement('div');
  // a shortcut to the style property of the element
  // since we'll play with this to update our object's position
  var s = that.el.style;
  // don't forget we're talking in css
  s.width = that.rad * 2 + 'px';
  s.height = that.rad * 2 + 'px';
  s.left = that.x - that.rad + 'px';
  s.top = that.y - that.rad + 'px';
  s.backgroundColor = get_random_color();
  // needed to make be sure we're not in a corner of the circle shaped elements
  that.isCircle = Math.random() > .5;
  if (that.isCircle) {
    that.el.className = 'circle';
  }
  // happens on mousedown
  that.startDrag = function(x, y) {
      that.lastX = x;
      that.lastY = y;
      s.zIndex = ++zIndex;
    }
    // happens on mousemove if we're the one being dragged
  that.move = function(x, y) {
    that.x += x - that.lastX;
    that.y += y - that.lastY;
    that.lastX = x;
    that.lastY = y;
    s.left = that.x - that.rad + 'px';
    s.top = that.y - that.rad + 'px';
  };
  container.appendChild(that.el);
  return that;
};

var elements = [];
for (var i = 0; i < (~~(Math.random() * 50)) + 15; i++) {
  elements.push(newElement());
}

var dragged;

var mousedown = function(e) {
  var rect = container.getBoundingClientRect();
  var x = e.clientX - rect.left;
  var y = e.clientY - rect.top;
  dragged = null;

  // sort our elements, higher zIndex firsts
  elements.sort(function(a, b) {
    return (+b.el.style.zIndex) - (+a.el.style.zIndex);
  });

  elements.forEach(function(el) {
    // we already found the One, no need to go further
    // (no "break;" in forEach method...)
    if (dragged) return;
    // is our mouse over the rectangular bounds of this element
    if (x >= el.x - el.rad && x <= el.x + el.rad &&
      y >= el.y - el.rad && y <= el.y + el.rad) {

      if (el.isCircle) {
        // a little bit of Pythagorian			
        var a = el.x - x;
        var b = el.y - y;
        var dist = Math.sqrt(a * a + b * b);
        // too far from the center, we were in the corner
        if (dist > el.rad) {
          return;
        }
      }
      // we got through here, 
      // tell the whole app we've got the One
      dragged = el;

      el.startDrag(x, y);
    }
  });
};
var mousemove = function(e) {
  // nobody is being dragged, so don't do anything
  if (!dragged) return;
  // otherwise, tell the browser we handle the event
  e.preventDefault();
  e.stopPropagation();
  // get the coordinates of our container
  var rect = container.getBoundingClientRect();
  // get the relative coordinates of our event
  var x = e.clientX - rect.left;
  var y = e.clientY - rect.top;
  // move the dragged element accordingly
  dragged.move(x, y);
};

var mouseup = function() {
  // we dropped it..
  dragged = null;
};

container.onmousedown = mousedown;
container.onmousemove = mousemove;
container.onmouseup = mouseup;


function get_random_color() {
  var letters = '0123456789ABCDEF'.split('');
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.round(Math.random() * 15)];
  }
  return color;
};
body {
  text-align: center;
}
#container {
  width: 500px;
  height: 300px;
  background-color: black;
  margin: 0 auto;
  position: relative;
  overflow: hidden;
}
#container>div {
  position: absolute;
  opacity: .7;
}
.circle {
  border-radius: 50%;
}
<div id="container"></div>

正如您所看到的,我自己使用单词dragged来指示我们在按下按钮的同时移动鼠标时移动的对象。是的,拖动是这个动作的调用方式......

但是,这与HTML drag and drop API几乎没有关系,重要的不是你的元素的定位,而是它们的内容。

您可以将元素拖放到其他元素中,但主要是将数据(外部文件或文本内容)拖放到文档中。

对于这个特殊的例子,这会使事情变得更加困难,而名称“拖动”仍然适用于最终用户的行为,这不应与API和每个相关的事件混淆。