Получить относительные x и y div после поворота - PullRequest
7 голосов
/ 28 октября 2011

Итак, вот что мне хотелось бы уделить больше внимания на уроках математики:

http://i.imgur.com/noKxg.jpg

У меня есть большой контейнер div и внутри него у меня есть несколько div контента, которые вращаются.

То, что я пытаюсь сделать, это анимировать между дочерними элементами, перемещая основной элемент в окне просмотра. Это было бы действительно легко, если бы я просто делал это, основываясь на простых вычислениях x / y (вверху / слева), однако, когда происходит вращение, моя математика просто ломается.

Я перепробовал несколько вещей и действительно не взломал его.

Вот упрощенная версия моих результатов сортировки, пожалуйста, не стесняйтесь возиться:

http://jsfiddle.net/dXKJH/3/

Я действительно не могу понять это!

[EDIT]

Я предпочитаю использовать это решение просто потому, что уже разработал способ заставить плагин rotate работать с MSIE6 +.

Как же мне сказать, что, хотя я следую всем математическим функциям и они кажутся чистыми, результаты не идеальны по пикселям, это как-то связано с вычислением ПИ? Кажется, чем больше я делаю коробки, тем меньше вероятность того, что они совпадут с верхним левым краем? Нечетность.

Также кто-нибудь может напомнить мне о том, что мне нужно сделать, если угол больше 45 градусов, я не могу найти ссылку, которую я помню из класса математики много лет назад, когда было 4 квадранта или что-то в этом роде ... р-р, как бы я хотел уделять больше внимания ..: -)

Огромное спасибо за всю помощь !!

Ответы [ 3 ]

2 голосов
/ 28 октября 2011

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

Важные моменты:

  • Math.sin / Math.cos требуется радианы, а не градусы
  • CSS вращается вокруг средней точки элемента, а не (0, 0) (это относится как к основному div, так и к блоку div s; сначала переведите -width / 2, -height / 2, поверните, а затем переведите обратно )
  • Используйте parseInt(x, 10), чтобы убедиться, что вы используете базу 10

Итоговый код: http://jsfiddle.net/pimvdb/dXKJH/10/. Это решение требует жестко закодированных позиций и поворотов в HTML, так как .css имел некоторые причуды с повернутыми элементами.

$("#div-1").rotate("-10deg");
$("#div-2").rotate("10deg");
$("#div-3").rotate("15deg");
$("#div-4").rotate("75deg");

$("#main").click(function() {
    console.log($('body').scrollLeft(), $('body').scrollTop());
});

$("a").click(function(e){
    goTo($(this).attr("id").substring(4,5));
    return false;
});


function n(x) {
    return parseInt(x, 10);
}

function sin(x) {
    return Math.sin(x / 180 * Math.PI);
}

function cos(x) {
    return Math.cos(x / 180 * Math.PI);
}

function rotate(x, y, a) {
    var x2 = cos(a) * x - sin(a) * y;
    var y2 = sin(a) * x + cos(a) * y;
    return [x2, y2];
}


var offsets = [null,
              [0,100,-10],
              [100,200, 10],
              [300,100, 15],
              [400,100, 75]].map(function(v) {
                  if(!v) return v;
                  var rotated = rotate(-50, -50, v[2]);
                  rotated[0] += v[0] + 50;
                  rotated[1] += v[1] + 50;
                  return rotated.concat(v[2]);
               });


function goTo(num){
    var obj = $("#div-" + num);
    var angle = -n(obj.rotate());
    var pointX = offsets[num][0] - 500;
    var pointY = offsets[num][1] - 500;
    var rotated = rotate(pointX, pointY, angle);
    var newX = rotated[0] + 500;
    var newY = rotated[1] + 500;

    $("#main").animate({rotate: angle + "deg"}, 1000);  
    $("body").animate({scrollLeft: newX,
                       scrollTop:  newY}, 1000)
}
1 голос
/ 28 октября 2011

Похоже, вы пытаетесь имитировать сайт Apple iPhone: http://www.apple.com/iphone/. Я подражал этой технике здесь:

http://jsfiddle.net/Yw9SK/2/ (использует переходы Webkit)

Это действительно не требует много математики, не переусердствуйте с этим. Вам просто нужно отменить поворот дочерних <div> s и отрегулировать их ширину / высоту и смещение от контейнера <div>.

Вот как это сделать:

container width: 500  height: 500  rotation: 0       top: 0    left: 0
child     width: 90   height: 90   rotation: 120deg  top: 330  left: 0


  1. Чтобы обеспечить правильное вращение, контейнер должен получить отрицательное вращение дочернего элемента:

    child rotation: 120deg  --> container rotation: -120deg
    
  2. Чтобы дочерний элемент был центрирован в представлении, нам нужно вычесть его ширину из ширины контейнера, разделить на 2 (чтобы он был в центре), а затем вычесть любые смещения. То же самое происходит для высоты:

    Width                                   Height
     500    (container width)                 500    (container height)
    - 60    (child width)                    - 40    (child height)
    ----                                     ----
     440                                      460
       /    (divide by 2                        /    (divide by 2
       2     to keep it centered)               2     to keep it centered)
    ----                                     ----
     220                                      230
    -  0    (subtract the left: offset)      -330    (subtract the top: offset)
    ----                                     ----
     220    translateX                       -100    translateY
    


Поскольку «сцена» центрирована поверх контейнера, новое преобразование также будет центрировано внутри сцены. (Сделать это не намного сложнее для прямоугольника по сравнению с квадратом.) Таким образом, наше преобразование, которое будет применено к контейнеру <div>:

transform: rotate(-120eg) translateX(220px) translateY(-100px)

Промыть и повторить для других дочерних элементов и перейти через них соответственно.


Этот JSFiddle является лишь примером того, как этого добиться. Это не очень хорошо продуманная имплантация. Более оптимальное решение будет иметь задержку перехода или задержку анимации (вместо setInterval), а затем прослушивать события 'transitionEnd' или 'animationEnd'.

Я бы определенно рекомендовал НЕ пытаться вычислять новые позиции и повороты программно на лету (хотя вы можете, и тогда вам просто нужно получить эти значения из свойства .style в JS). Я бы порекомендовал иметь заранее заданные переводы / ротации (как показано в моем примере, хотя они должны быть в CSS) и просто применять их в правильном порядке к контейнеру. Это обеспечит быстрые и плавные переходы.

1 голос
/ 28 октября 2011

Я хотел бы предложить другой подход:

  1. Переместиться в div-2 из начального состояния (переместить Main Div, используя левый / верхний стили)
  2. Установить transform-начало основного деления в центр зрения (также центр деления-2)
  3. вращение основного деления на противоположное количество деления-2 (деление-2 должно быть правильно отцентрировано)
  4. вращение основногоDiv обратно на 0 градусов.
  5. Перейти к div-3
  6. Установить источник преобразования основного Div в центр обзора (также центр div-3)
  7. Повернуть MainDiv на противоположное количество div-3 (div-3 должен быть центрирован правильно)
  8. Промыть и повторить

Это может быть проще и приведет к менее сложному (более удобному для обслуживания) коду,Обратите внимание, что движения и повороты могут быть анимированными.Кроме того, если вы используете переводы вместо левого / верхнего стилей, это решение будет намного более сложным из-за изменений источника преобразования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...