18

我在外部 div 中有一个内部 div。内部 div 是可拖动的,外部 div 旋转 40 度。这是一个测试用例。在实际情况下,它可以是任何角度。还有另一个名为 point 的 div,其位置如图所示。(我来自 Flash 背景。在 Flash 中,如果我要拖动内部 div,即使它包含在外部旋转 div 中,它也会跟随鼠标。)但是在 HTML 中,内部 div 不会跟随鼠标,因为它可以看到从小提琴。我希望 div 'point' 完全跟随鼠标。这可能吗。我尝试使用三角函数来处理它,但无法让它工作。

http://jsfiddle.net/bobbyfrancisjoseph/kB4ra/8/

4

6 回答 6

9

这是我解决这个问题的方法。

http://jsfiddle.net/2X9sT/21/

我把点放在旋转的 div 之外。这样我就可以确保拖动事件会产生正常的行为(不会向奇怪的方向跳跃)。我使用可拖动处理程序将点附加到鼠标光标。

在拖动事件中,我转换拖动偏移以反映新值。这是通过以与旋转角度相反的方向围绕外部 div 中心旋转偏移量来完成的。

我对其进行了测试,它似乎可以在 IE9、Firefox 和 Chrome 中运行。

您可以尝试不同的角度值,它应该可以正常工作。

我还修改了 HTML,因此可以将相同的逻辑应用于页面中的多个 div。

编辑:

我更新了脚本,以解释包含行为以及评论中建议的级联旋转。

我也正在使outerdiv 可拖动到另一个 div 中。现在它几乎可以工作了。我只需要能够更新拖动 div 的中心来修复拖动行为。

尝试拖动红色 div。

http://jsfiddle.net/mohdali/kETcE/39/

于 2012-06-05T14:11:34.323 回答
3

我现在在工作,所以我不能为你做这项工作,但我可以解释解决问题的最简洁方法背后的数学原理(可能不是最简单的解决方案,但与其他一些黑客不同,它灵活一旦你得到它实施)。

首先,您必须意识到您正在使用的旋转插件正在对您的元素 ( transform: rotate(30deg)) 进行转换,然后浏览器将其更改为矩阵 ( matrix(0.8660254037844387, 0.49999999999999994, -0.49999999999999994, 0.8660254037844387, 0, 0))。其次,有必要了解,通过旋转一个元素,子元素的轴是绝对旋转的(在寻找了很长时间之后,没有任何真正的技巧可以绕过这个,这是有道理的),因此唯一的正如其他一些答案所建议的那样,方法是将孩子从父母身边带走,但我假设这不是您的应用程序中的一个选项。

现在,我们因此需要做的是取消父级的原始矩阵,这是一个两步过程。首先,我们需要使用以下代码找到矩阵:

var styles = window.getComputedStyle(el, null);

var matrix = styles.getPropertyValue("-webkit-transform") ||
             styles.getPropertyValue("-moz-transform") ||
             styles.getPropertyValue("-ms-transform") ||
             styles.getPropertyValue("-o-transform") ||
             styles.getPropertyValue("transform");

接下来,矩阵将是一个字符串,如上所示,您需要将其解析为可以使用的数组(有 jquery 插件可以做到这一点)。完成后,您将需要取矩阵的逆矩阵(在您的示例中归结为rotate(-30deg)),这可以使用例如这个库(或您的数学书:P)来完成。

最后你需要做逆矩阵时间(使用我之前提到的矩阵库)一个平移矩阵(使用这个工具来弄清楚它们的外观(平移是沿着 x 和 y 轴的移动,有点像 left 和 top on一个相对定位的元素,但硬件加速和矩阵变换 css 属性的一部分))这将为您提供一个新矩阵,您可以将其应用于您的子元素,为您提供与父元素相同轴上的平移。

现在,您可以通过使用和手动三角函数1仅针对特定旋转(完全绕过对逆矩阵甚至矩阵的全部需求)执行此操作来大大简化此操作left,但这具有明显的缺点,即它适用于正常旋转并且会需要根据使用的每个特定情况进行更改。top

哦,如果你现在认为flash更容易,相信我,在 HTML/CSS 中旋转轴的方式很有意义,如果你想要类似 flash 的行为,请使用这个库


1 例如,这就是 Mohamed Ali 在他的回答中所做的(他的 jsFiddletransformOffset中的函数)。


免责声明,自从我做这些事情以来已经有一段时间了,我对矩阵的理解从来没有非常好,所以如果你发现任何错误,请指出/修复它们。

于 2012-06-06T10:00:44.923 回答
2

仅对于 Webkit,该webkitConvertPointFromPageToNode函数处理缺失的行为:

   var point = webkitConvertPointFromPageToNode(
       document.getElementById("outer"),
       new WebKitPoint(event.pageX, event.pageY)
   );

jsFiddle:http: //jsfiddle.net/kB4ra/108/

要涵盖其他浏览器,您可以使用此 StackOverflow 答案中描述的方法:https ://stackoverflow.com/a/6994825/638544

function coords(event, element) {
  function a(width) {
    var l = 0, r = 200;
    while (r - l > 0.0001) {
      var mid = (r + l) / 2;
      var a = document.createElement('div');
      a.style.cssText = 'position: absolute;left:0;top:0;background: red;z-index: 1000;';
      a.style[width ? 'width' : 'height'] = mid.toFixed(3) + '%';
      a.style[width ? 'height' : 'width'] = '100%';
      element.appendChild(a);
      var x = document.elementFromPoint(event.clientX, event.clientY);
      element.removeChild(a);
      if (x === a) {
        r = mid;
      } else {
        if (r === 200) {
          return null;
        }
        l = mid;
      }
    }
    return mid;
  }
    var l = a(true),
        r = a(false);
    return (l && r) ? {
        x: l,
        y: r
    } : null;
}

这样做的缺点是当鼠标在目标元素之外时不起作用,但是应该可以将它覆盖的区域扩展任意数量(尽管无论如何都很难保证它覆盖整个窗口大的)。

jsFiddle:http: //jsfiddle.net/kB4ra/122/

这可以通过添加 mousemove 事件扩展到适用于#point:

$('#outer').mousemove(function(event){
   var point = convertCoordinates(event, $("#outer"));

    $("#point").css({left: point.x+1, top: point.y+1});          
});

请注意,我将#point的x和y坐标调整了1px,以防止它直接位于鼠标下方;如果我不这样做,那么它会阻止拖动#inner。另一种解决方法是将处理程序添加到#point,以检测鼠标事件并将它们传递给直接位于#point 下方的任何元素(和stopPropagation,这样它们就不会在较大的页面元素上运行两次)。

jsfiddle:http: //jsfiddle.net/kB4ra/123/

于 2012-06-05T09:50:17.973 回答
0

在我看来,如果您不旋转 div,则 div 会完全跟随鼠标。这可能是插件的问题..也许您可以正确模拟可拖动功能?

于 2012-05-30T12:39:59.547 回答
0

这基本上会做你需要的,虽然它是错误的。绑定拖动事件处理程序,截取ui对象并修改为使用父元素的偏移X和Y。所有 X、Y、顶部、左侧等都在这些对象中。今天我有更多时间的时候,我会试着给你一个更好的例子。祝你好运!

http://jsfiddle.net/kB4ra/107/

于 2012-06-04T21:14:54.047 回答
-1

可能这是您的 jquery 库的问题,或者您可以通过分配内部 div 和外部 div 的 z-order 值来检查这一点,确保您为内部 div 提供更高的数字。

于 2012-06-11T19:06:10.377 回答