Вопрос по html, javascript, jquery – Внутренний div внутри внешнего повернутого div не следует за мышью в случае перетаскивания с помощью jQuery UI

18

У меня есть внутренний div внутри внешнего div. Внутренний div перетаскивается, а внешний поворачивается на 40 градусов. Это контрольный пример. В реальном случае это может быть любой угол. Есть еще один div, называемый точкой, который расположен, как показано на рисунке. (Я из фона flash. Во Flash, если бы я перетаскивал внутренний div, он бы следовал за мышью, даже если он содержался внутри внешнего повернутого div.) Но в HTML внутренний div не следует за мышью, как это видно с скрипки Я хочу, чтобы div 'point' apos; точно следовать за мышью. Это возможно. Я пытался работать с помощью тригнометрии, но не смог заставить его работать.

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

Вы принимаете без JQuery? user1365010
Пожалуйста, покажите демо. Я не могу понять это правильно. Bobby Francis Joseph
это определенно проблема с плагином. Вы сообщили об этом вcode.google.com/p/jqueryrotate/issues/list? naveen
Эй, извините за этот громкий звук, но все, что вам нужно, это перемещать div с id-точкой каждый раз, когда div с внутренним id перемещается? Дай мне знать, с небольшими изменениями. Я подготовил для тебя демо! B-) Tats_innit

Ваш Ответ

6   ответов
0

Это может быть проблемой с плагином. Может, вы могли бы корректно смоделировать перетаскиваемую функцию?

Error: User Rate Limit Exceeded Bobby Francis Joseph
2

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/

Это можно расширить, чтобы применить к #point, добавив событие mousemove:

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

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

Обратите внимание, что я корректирую координаты x и y точки # на 1px, чтобы она не находилась непосредственно под мышью; если бы я этого не делал, он бы заблокировал перетаскивание #inner. В качестве альтернативы можно добавить обработчики в #point, которые обнаруживают события мыши и передают их любому элементу, находящемуся непосредственно под #point (и stopPropagation, чтобы они не запускались дважды на больших элементах страницы).

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

Добавлена обработка #point в моем ответе. Кроме того, я заметилgetRotateAngle функция плагина jQuery, используемого для поворота - это сделает возможным учет поворотов вjsfiddle.net/kB4ra/118 (таким образом, что будет работать даже с мышью за пределами #outer).
Нашел способ, который действительно работает для Firefox. Я отредактировал его в своем ответе.
Вот версия, которая намного ближе к правильному обращению с Firefox:jsfiddle.net/kB4ra/118 (Все еще нужен код для учета преобразований, о которых, по-видимому, довольно сложно получить информацию).
0

что вам нужно, хотя это глючит. Свяжите обработчик события перетаскивания, перехватите объект пользовательского интерфейса и измените его, чтобы использовать смещение X и Y родительского элемента. Все X, Y, сверху, слева и т. Д. Находятся в этих объектах. Я постараюсь привести вам лучший пример, когда сегодня у меня будет немного больше времени. Удачи!

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

@ Tom, проблема с мерцанием из-за event.offsetX & amp; Y возвращаясьNaN время от времени.
В Chrome мерцание вызвано event.offsetX & amp; Y возвращает 1, а не NaN. Это, в свою очередь, вызвано перемещением мыши над элементом #inner, в результате чего координаты смещения относительно него. Обрыв Firefox происходит из-за event.offsetX & amp; Y всегда возвращается неопределенным.
@thomallen Я попробовал скрипку, но маленький серый прямоугольник вообще не перетаскивается в FF 12.0, и он сильно мерцает в веб-браузерах.
@ Brilliand, ну хром вернулсяNaN в моем эксперименте
Большое вам спасибо .. Я почти отказался от этого .. Я начну щедрость .. 250 очков .. ура ... Bobby Francis Joseph
9

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

Я поставил точку за пределами повернутого div. Таким образом, я уверен, что событие перетаскивания будет производить нормальное поведение (не прыгать в странных направлениях). Я использую перетаскиваемый обработчик, чтобы прикрепить точку к курсору мыши.

В событии перетаскивания я преобразую смещение перетаскивания, чтобы отразить новые значения. Это делается путем вращения смещения вокруг внешнего центра делителя в направлении, противоположном углу поворота.

Я проверил его, и, похоже, он работает в IE9, Firefox и Chrome.

Вы можете попробовать разные значения для угла, и он должен работать нормально.

Я также изменил HTML, чтобы можно было применить одну и ту же логику к нескольким элементам div на странице.

Edit:

Я обновил скрипт, чтобы учесть поведение сдерживания, а также каскадные повороты, как это предлагается в комментариях.

Я также заканчиваю делатьouter div перетаскивается внутри другого div. Прямо сейчас это почти работает. Мне просто нужно иметь возможность обновить центр перетаскиваемого элемента div, чтобы исправить поведение при перетаскивании.

Попробуйте перетащить красный div.

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

Error: User Rate Limit Exceededtop а такжеleft не учитываются вmatrix, пожалуйста, проверьтеjsfiddle.net/mohdali/kETcE/5
Как содержать#inner div, либоoverflow или жеcontainment или же?так, чтобы он оставался внутри#outer? Подход не выдерживает+1, Просто удивительно!
Error: User Rate Limit Exceededjsfiddle.net/4XJgP
Error: User Rate Limit Exceeded
Основным недостатком, как я отмечаю в своем ответе, является то, чтоtransformOffsetError: User Rate Limit Exceeded
-1

это проблема вашей библиотеки jquery, или вы можете проверить это, присвоив z-order значение внутреннего div, а внешний div убедитесь, что вы даете большее число внутреннему div.

3

поэтому я не могу выполнить эту работу за вас, но я могу объяснить математику, стоящую заneatest способ решения вашей проблемы (вероятно, не самое простое решение, но в отличие от некоторых других хаков, этоa lot более гибким, как только вы его реализовали).

Прежде всего вы должны понимать, что используемый плагин поворота применяет преобразование к вашему элементу (transform: rotate(30deg)), который в свою очередь превращается в матрицу вашим браузером (matrix(0.8660254037844387, 0.49999999999999994, -0.49999999999999994, 0.8660254037844387, 0, 0)). Secondly it is necessary to understand that by rotating an element the axis of the child elements are rotate absolutely and entirely with it (after looking for a long time there isn't any real хитрость, чтобы обойти это, что имеет смысл), таким образом, единственным способом было бы исключить ребенка из родительского процесса, как предлагают некоторые другие ответы, но я предполагаю, что это не вариант в вашем приложении.

Теперь нам нужно отменить исходную матрицу родителя, которая состоит из двух этапов. Сначала нам нужно найти матрицу, используя код в следующих строках:

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, немного похожи на левый и верхний на относительно позиционированном элементе, но с аппаратным ускорением и частью свойства css преобразования матрицы)), который даст вам новую матрицу, которая Вы можете обратиться к своему дочернему элементу, предоставив вам перевод на той же оси, что и ваш родительский элемент.

Теперь вы можете значительно упростить это, сделав это сleft, top и ручная тригонометрия1 только для специфических вращений (обходя всю потребность в обратных матрицах или даже матрицах полностью), но это имеет явный недостаток, заключающийся в том, чтоonly работают для нормальных вращений и должны будут меняться в зависимости от каждой конкретной ситуации, в которой он используется.

Ох, и если вы сейчас думаете, чтоflash Поверьте, было намного проще, так как поворот оси в HTML / CSS имеет большое значение иесли вы хотите flash как поведение, используйте эту библиотеку.

1 This is what Mohamed Ali is doing in his answer for example (the transformOffset function in его jsFiddle).

Disclaimer, it has been awhile since I have been doing this stuff and my understanding of matrices has never been extremely good, so if you see any mistakes, please do point them out/fix them.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededjsfiddle.net/kB4ra/118 - которая была бы подходящей отправной точкой для реализации этого метода.

Похожие вопросы