2012-04-07 46 views
3

我有一堆隨機位置的span元素,它們被封閉在名爲'.background'的父div內。這些都是用Javascript生成的。像這樣:鼠標移近時排斥對象

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

我希望它們在鼠標靠近時移開(或排斥),但我不知道該如何做到這一點!我將如何去完成這個在jQuery中完成?

我想你必須搜索附近的跨度,然後改變它們的位置,如果它們位於鼠標周圍的特定半徑內,但我真的不知道從哪裏開始。任何幫助表示讚賞!

回答

12

一個簡單的方法是將每個跨度換成另一個更大的跨度。讓鼠標靠近內部距離的最小距離使其在每一側都變大。綁定一個將每個包裝器移動到包裝器上的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()); 
    } 
}; 

然後,將樣品圓形逃避功能(這是最簡單的實現)。概要:

  1. 計算保險槓的中心(保險槓的corner加上outer dimensions分成兩半)
  2. 計算鼠標偏移向量(從mouse cursor到元件的中心)
  3. 接近測試:如果該距離> =允許的最小距離,然後提前返回。
  4. 計算delta:與鼠標光標的距離太小,所以我們需要從保險槓所在的位置(delta)開始的矢量。延長偏移矢量,使其達到最小允許距離,即保護杆的中心應該位於相對於鼠標位置的位置。從中減去偏移矢量可以得到從接近邊緣到鼠標的增量,這也恰好是增量。
  5. 計算新位置:
    1. 將delta增加到當前位置。
    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

+1

徹底的答案! – 2012-10-12 18:50:50

+0

但不是[完美](http://jsfiddle.net/outis/bA8YE/39/)。 z指數會導致多個逃犯出現問題。 – outis 2012-10-13 18:11:35

+1

哈哈哈JSfiddle玩起來很有趣,我可以想象使用它的鏈接,說'點我!'然後不能。 – Partack 2014-06-25 13:29:23

1

您選擇具有類圓與jQuery的所有對象,把在一個變量,然後檢查鼠標移動(也AE用jQuery做)的,如果通過他們循環一個是從鼠標的某個半徑。

+0

給每個跨度一個id並保存所有位置,然後再做這個操作,這樣你就不必每次重新計算了。 – ampersand 2012-04-07 21:53:20