一個簡單的方法是將每個跨度換成另一個更大的跨度。讓鼠標靠近內部距離的最小距離使其在每一側都變大。綁定一個將每個包裝器移動到包裝器上的mouseover
的函數(evade
)。這種方法爲您提供了一個方形邊框,因此如果內部跨度中的圖形元素不是正方形,則從鼠標到圖形元素邊框的距離將不會保持不變,但很容易實現。
或者,使用保險槓進行粗略的接近測試。而不是將規避功能綁定到mouseover
,而是綁定一個函數(beginEvade
),該函數在mousemove上綁定evade
。此外,綁定功能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());
}
};
然後,將樣品圓形逃避功能(這是最簡單的實現)。概要:
- 計算保險槓的中心(保險槓的corner加上outer dimensions分成兩半)
- 計算鼠標偏移向量(從mouse cursor到元件的中心)
- 接近測試:如果該距離> =允許的最小距離,然後提前返回。
- 計算delta:與鼠標光標的距離太小,所以我們需要從保險槓所在的位置(delta)開始的矢量。延長偏移矢量,使其達到最小允許距離,即保護杆的中心應該位於相對於鼠標位置的位置。從中減去偏移矢量可以得到從接近邊緣到鼠標的增量,這也恰好是增量。
- 計算新位置:
- 將delta增加到當前位置。
- 範圍檢查:保留文檔中的圓的所有邊界。
- 移動保險槓
在代碼:
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-10-12 18:50:50
但不是[完美](http://jsfiddle.net/outis/bA8YE/39/)。 z指數會導致多個逃犯出現問題。 – outis 2012-10-13 18:11:35
哈哈哈JSfiddle玩起來很有趣,我可以想象使用它的鏈接,說'點我!'然後不能。 – Partack 2014-06-25 13:29:23