簡単なアプローチは、別の大きなスパンで各スパンをラップすることです。マウスを内側スパンに接近させたい最小限の距離で両側を大きくします。各ラッパーをラッパー上の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());
}
};
次に、実装する最も単純な円形回避関数です。概要:
- が
- (バンパーのcorner半分に分割outer dimensionsプラス)をバンパーの中央を計算する(mouse cursorから要素の中央に)マウスオフセットベクトル
- 近接テストを計算する:距離がある場合> =許容されている最小距離。
- デルタを計算する:マウスカーソルまでの距離が小さすぎるので、バンパーがどこにあるべきか(デルタ)からのベクトルが必要です。オフセットベクトルを最小許容距離になるように延長すると、マウスの位置に対するバンパの中心がどこにあるかが決まります。デルタを近接エッジからマウスに与えるオフセットベクトルを差し引く(デルタであることもある)。
- 新しい位置を計算:
- デルタを現在の位置に追加します。
- 境界チェック:文書内の円のすべての境界線を維持します。コードで
- 移動バンパー
:その後
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
どのような徹底的な答え! –
しかし、[完璧ではない](http://jsfiddle.net/outis/bA8YE/39/)。 z-インデックスは、複数の避難者に問題を引き起こす。 – outis
JSfiddleは楽しいですが、私はそれを 'CLICK ME!'というリンクに使用すると想像することができます。それからできない。 – Partack