2012-04-07 6 views
3

私は、「。バックグラウンド」と呼ばれる親div内に囲まれたランダムな位置にある複数のスパン要素を持っています。これらはJavascriptで生成されます。このように:マウスが近くにあるときのオブジェクトの反発

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

私はマウスが近づくと、彼らが離れて移動(または撃退)したいが、私はどのようにこれを行うには考えています! jQueryでこれを達成するにはどうすればいいですか?

近くにあるスパンを検索し、マウスを囲む特定の半径内にある場合はその位置を変更する必要があると思いますが、どこから開始するのかは本当にわかりません。どんな助けもありがとう!

答えて

12

簡単なアプローチは、別の大きなスパンで各スパンをラップすることです。マウスを内側スパンに接近させたい最小限の距離で両側を大きくします。各ラッパーをラッパー上のmouseoverに移動する関数(evade)をバインドします。この方法では四角形の境界線が得られるため、内側スパンの図形要素が四角形でない場合、マウスから図形要素の境界線までの距離は一定ではなく、実装が簡単です。

また、バンパーをラフな近接テストに使用してください。回避関数をmouseoverにバインドする代わりに、evadeをmousemoveにバインドする関数(beginEvade)をバインドします。また、mouseoutに関数をバインドすると、evadeのバインドが解除されます。 evadeは、より正確な近接性テストを実行できます。

まず、ベクトルタイプを提供する良いジオメトリライブラリを見つけます。 1つでも存在しない場合、サンプル実装があります:

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プラス)をバンパーの中央を計算する(mouse cursorから要素の中央に)マウスオフセットベクトル
  2. 近接テストを計算する:距離がある場合> =許容されている最小距離。
  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は楽しいですが、私はそれを 'CLICK ME!'というリンクに使用すると想像することができます。それからできない。 – Partack

1

でこれをプレビューすることができ、変数にして、あればそれらを介してループすることによって(また、jQueryを使って行わAE可能性)のMouseMove上で確認することを置きます1つはマウスから特定の半径にあります。

+0

各スパンにidを与え、これを行う前にすべての位置を保存して、毎回再計算する必要はありません。 – ampersand

関連する問題