2012-04-07 4 views
3

'.background'라는 부모 div 안에있는 임의의 위치에 여러 개의 span 요소가 있습니다. 이들은 자바 스크립트로 생성됩니다. 이처럼 :마우스가 가까울 때 반발하는 개체

<span class="circle" style="width: 54px; height: 54px; background: #5061cf; top: 206px; left: 306px"></span> 

나는 마우스가 가까워로 멀리 이동 (또는 격퇴) 싶지만 어떻게하는지 모르겠어요! jQuery에서이 작업을 수행하려면 어떻게해야합니까?

주변에있는 범위를 검색 한 다음 마우스를 둘러싼 특정 반경 내에있는 경우 위치를 변경해야한다고 생각하지만 실제로 시작해야 할 위치를 모르겠습니다. 어떤 도움을 주셔서 감사합니다!

답변

12

간단한 방법은 각 범위를 다른 하나의 큰 범위로 묶는 것입니다. 마우스를 내부 범위에 접근 할 수있는 최소 거리만큼 각면을 더 크게 만듭니다. 랩퍼에서 각 랩퍼를 mouseover으로 이동시키는 함수 (evade)를 바인드하십시오. 이 방법은 사각형 테두리를 제공하므로 안쪽 범위의 그래픽 요소가 사각형이 아닌 경우 마우스에서 그래픽 요소의 테두리까지의 거리가 일정하지 않지만 구현하기 쉽습니다.

또는 거친 근접 테스트를 위해 범퍼를 사용하십시오. evade 함수를 mouseover에 바인딩하는 대신 evade을 바인딩하는 함수 (beginEvade)를 mousemove에 바인딩하십시오. 또한 함수를 mouseout에 바인드하여 evade을 바인드 해제하십시오. 그런 다음 evade은보다 정확한 근접 테스트를 수행 할 수 있습니다.

먼저 벡터 유형을 제공하는 우수한 형상 라이브러리를 찾습니다. 하나가 없으면 다음 샘플 구현이 있습니다.

Math.Vector = function (x,y) { 
    this.x = x; 
    this.y = y; 
} 
Math.Vector.prototype = { 
    clone: function() { 
     return new Math.Vector(this.x, this.y); 
    }, 
    negate: function() { 
     this.x = -this.x; 
     this.y = -this.y; 
     return this; 
    }, 
    neg: function() { 
     return this.clone().negate(); 
    }, 
    addeq: function (v) { 
     this.x += v.x; 
     this.y += v.y; 
     return this; 
    }, 
    subeq: function (v) { 
     return this.addeq(v.neg()); 
    }, 
    add: function (v) { 
     return this.clone().addeq(v); 
    }, 
    sub: function (v) { 
     return this.clone().subeq(v); 
    }, 
    multeq: function (c) { 
     this.x *= c; 
     this.y *= c; 
     return this; 
    }, 
    diveq: function (c) { 
     this.x /= c; 
     this.y /= c; 
     return this; 
    }, 
    mult: function (c) { 
     return this.clone().multeq(c); 
    }, 
    div: function (c) { 
     return this.clone().diveq(c); 
    }, 

    dot: function (v) { 
     return this.x * v.x + this.y * v.y; 
    }, 
    length: function() { 
     return Math.sqrt(this.dot(this)); 
    }, 
    normal: function() { 
     return this.clone().diveq(this.length()); 
    } 
}; 

다음으로 구현할 가장 간단한 회피 함수입니다. 개요 :

  1. 범퍼의 중심을 계산 (범퍼의 corner 플러스 반으로 나눈 outer dimensions)
  2. 근접 테스트합니다 (mouse cursor에서 요소의 중심) 마우스 오프셋 벡터를 계산 : 거리 인 경우 > = 허용되는 최소 거리. 그런 다음 일찍 돌아옵니다.
  3. 델타 계산 : 마우스 커서까지의 거리가 너무 작기 때문에 범퍼가 있어야하는 위치 (델타)에서 벡터가 필요합니다. 오프셋 벡터를 길게하여 최소 허용 거리를 지정하면 범퍼의 중심이 마우스의 위치와 관련하여 있어야합니다. 오프셋 벡터를 빼면 델타가 근접 에지에서 마우스로 이동하며 델타도 발생합니다.
  4. 새로운 위치를 계산하십시오 :
    1. 델타를 현재 위치에 추가하십시오.
    2. 범위 검사 : 문서 내의 모든 경계선을 유지합니다.코드에서
  5. 이동 범퍼

: 그 후

function evade(evt) { 
    var $this = $(this), 
     corner = $this.offset(), 
     center = {x: corner.left + $this.outerWidth()/2, y: corner.top + $this.outerHeight()/2}, 
     dist = new Math.Vector(center.x - evt.pageX, center.y - evt.pageY), 
     closest = $this.outerWidth()/2; 

    // proximity test 
    if (dist.length() >= closest) { 
     return; 
    } 

    // calculate new position 
    var delta = dist.normal().multeq(closest).sub(dist), 
     newCorner = {left: corner.left + delta.x, top: corner.top + delta.y}; 

    // bounds check 
    var padding = parseInt($this.css('padding-left')); 
    if (newCorner.left < -padding) { 
     newCorner.left = -padding; 
    } else if (newCorner.left + $this.outerWidth() - padding > $(document).width()) { 
     newCorner.left = $(document).width() - $this.outerWidth() + padding; 
    } 
    if (newCorner.top < -padding) { 
     newCorner.top = -padding; 
    } else if (newCorner.top + $this.outerHeight() - padding > $(document).height()) { 
     newCorner.top = $(document).height() - $this.outerHeight() + padding; 
    } 

    // move bumper 
    $this.offset(newCorner); 
} 

, 모든 것을 남은 모든 것을 설정하는/evade 때어를 결합하는 기능, 및 호출입니다.

function beginEvade() { 
    $(this).bind('mousemove', evade); 
} 

function endEvade() { 
    $(this).unbind('mousemove', evade); 
} 

$(function() { 
    // you can also wrap the elements when creating them. 
    $('.circle').wrap('<span class="bumper" />') 

    $('.bumper').bind('mouseover', beginEvade); 
    $('.bumper').bind('mouseout', endEvade); 
}); 

당신은 jQuery로 클래스 원 모든 개체를 선택 jsFiddle

+1

철저한 답변! –

+0

하지만 [완벽하지] (http://jsfiddle.net/outis/bA8YE/39/). z- 색인은 하나 이상의 회피 자에게 문제를 일으 킵니다. – outis

+1

JSfiddle은 재미있게 놀 수 있습니다. '클릭 해주세요!'라는 링크로 사용하는 것이 상상할 수 있습니다. 그런 다음 할 수 없게됩니다. – Partack

1

이를 미리 볼 수 있습니다, 변수에 다음 경우들을 통해 반복하여 (또한 jQuery를 함께 할 AE 수) MouseMove 이벤트에 확인하는 것이 넣어 하나는 마우스의 특정 반지름에 있습니다.

+0

각 스팬에 ID를 부여하고 모든 위치를 저장하기 전에 이렇게하면 매번 다시 계산하지 않아도됩니다. – ampersand

관련 문제