Движущиеся круги вдоль луча, чтобы исключить проверку местоположения


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

Вот вам схема, чтобы лучше объяснить это:

circles

Я увеличить размер красного круга от 100 пикселей на 200 пикселей. Я хочу, чтобы переместить все голубые круги в сторону на половину разницы ( (200-100)/2 = 50 пикселей, в этом примере ) вдоль серой линии (с серой линии которые различны для каждого синий круг).

jsFiddle

$this.siblings( ".circle" ).each( function() {

    var $this = $( this ),
        circle = $this.data(),
        circleX = circle.left + circle.radius,
        circleY = circle.top + circle.radius,
        a = Math.abs( hoveredY - circleY ),
        b = Math.abs( hoveredX - circleX ),
        c = Math.sqrt( ( a*a ) + ( b*b ) ),
        A = Math.acos( b / c ), 
        C = 90 * ( Math.PI / 180 ),
        B = C - A,
        sinA = Math.sin( A ),
        sinB = Math.sin( B ),
        sinC = Math.sin( C ),
        newc = c + ( expand / 2 ),
        newa = ( newc * sinA ) / sinC,
        newb = ( newc * sinB ) / sinC,
        newX = hoveredX + ( hoveredX > circleX ? -newb : newb ),
        newY = hoveredY + ( hoveredY > circleY ? -newa : newa ),
        left = newX - circle.radius,
        top = newY - circle.radius;

    $this.animate( { 

        "left": left,
        "top": top

    }, 75 );

});

hoveredX и hoveredY имеют левую и верхнюю координаты красного круга и расширить насколько красный круг расширяется в пикселях.

Математически, я уверен, что есть лучший способ сделать это, но у меня этот способ работает, и это нормально (хотя я не против слышать лучше решения). Но мне не нравится эта функция-это две линии:

newX = hoveredX + ( hoveredX > circleX ? -newb : newb ),
newY = hoveredY + ( hoveredY > circleY ? -newa : newa ),

Что меня бесит, что мне приходится делать проверку на всех. Эти две линии, которые говорят: "Если круг слева/сверху сделать это одним способом, а если справа/снизу делать это другим способом". Мне кажется, что я упускаю что-то раньше в функцию, которая может быть решена путем переключения стороны операторов, добавив вместо вычитания, или получить абсолютное значение.



Комментарии
1 ответ

У меня было две мысли. Один был ... ты действительно нужен только угол и расстояние. Расстояние-это сумма, которую вы расширить и угол может быть производной от X/Y координаты.

http://jsfiddle.net/uLu7v/38/

сначала вам вычислить угол:

var angle = Math.atan2(hoveredY - circleY, hoveredX - circleX);

Затем вам рассчитать расстояние они двигаются:

var topMove = ((expand /2 ) * Math.sin(angle)); // sin for Y
var leftMove = ((expand /2 ) * Math.cos(angle)); // cos for X

затем использовать jQuery встроенный анимировать +=:

$this.animate( { 
"left": "-=" + leftMove + "px",
"top": "-=" + topMove + "px"
}, 75 );

Тада!

Изменения:- несколько улучшений в код не входят в вопрос:

В функции вписанной окружности() изменить return для возврата (mouseDistance <= радиус); используя тернарный оператор, чтобы возвращать логическое значение? ... Я уверен, что это используется, чтобы возвратить другие значения правильно?

В $( ".круг" ).нажмите кнопку( :

if(!$( this ).data( "clicked" ) && inCircle( $( this ), event.pageX, event.pageY ) ) {

$( this ).data( "clicked", true );
setLocations( this, 200, event );

} else {

resetLocations();
$( this ).data( "clicked", false );

};

Делает его чище, но не реальное улучшение в противном случае, больше предпочтение.

В функции setLocations() круг параметр конфликты с местным кругом переменной. Я бы изменил параметр circleElement.

2
ответ дан 14 декабря 2011 в 03:12 Источник Поделиться