3

「.background」と呼ばれる親 div 内に囲まれたランダムな位置に一連のスパン要素があります。これらは Javascript で生成されます。このような:

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

ネズミが近づいてきたら遠ざける(または反発する)ようにしたいのですが、どうすればいいのかわかりません!jQueryでこれを達成するにはどうすればよいですか?

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

4

2 に答える 2

14

簡単なアプローチは、各スパンを別のより大きなスパンでラップすることです。マウスが内側のスパンに近づくことができるようにする最小距離だけ、両側を大きくします。evade各ラッパーをラッパーに移動する関数 ( ) をバインドしますmouseover。このアプローチでは正方形の境界線が得られるため、内部スパンのグラフィック要素が正方形でない場合、マウスからグラフィック要素の境界線までの距離は一定ではありませんが、実装は簡単です。

または、大まかな近接テストにバンパーを使用します。回避関数を にバインドする代わりに、mousemovemouseoverにバインドする関数 ( beginEvade) をバインドします。evadeまた、mouseoutunbindsに関数をバインドしますevadeevadeその後、より正確な近接テストを実行できます。

まず、ベクトル タイプを提供する優れたジオメトリ ライブラリを見つけます。実装がない場合の実装例を次に示します。

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. バンパーの中心を計算する (バンパーの外側の寸法を半分に割った値)
  2. マウス オフセット ベクトルを計算します (マウス カーソルから要素の中心まで)
  3. 近接テスト: 距離が最小許容距離以上の場合、早期に戻ります。
  4. デルタの計算: マウス カーソルまでの距離が小さすぎるため、バンパーがある場所からあるべき場所 (デルタ) までのベクトルが必要です。オフセット ベクトルを長くして、最小許容距離になるようにすると、マウスの位置に対してバンパーの中心がどこにあるべきかがわかります。そこからオフセット ベクトルを引くと、近接エッジからマウスまでのデルタが得られます。これもたまたまデルタです。
  5. 新しい位置を計算します:
    1. デルタを現在の位置に追加します。
    2. 境界チェック: ドキュメント内の円のすべての境界を保持します。
  6. バンパーをずらす

コード内:

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);
});

これはjsFiddleでプレビューできます

于 2012-04-07T21:04:18.253 に答える
1

クラス circle を持つすべてのオブジェクトを jQuery で選択し、それを変数に入れてから、マウスから特定の半径内にある場合はそれらをループして mousemove をチェックします (jQuery で行うこともできます)。

于 2012-04-07T21:07:08.470 に答える