当鼠标靠近时排斥对象

Joh*_*nny 3 javascript jquery

我在一个名为'.background'的父div中包含一些随机位置的span元素.这些是使用Javascript生成的.像这样:

<span class="circle" style="width: 54px; height: 54px; background: #5061cf; top: 206px; left: 306px"></span>
Run Code Online (Sandbox Code Playgroud)

我希望它们在鼠标靠近时移开(或击退),但我不知道该怎么做!我将如何在jQuery中实现这一目标?

我想你必须搜索附近的跨度,如果它们在鼠标周围的某个半径范围内,则改变它们的位置,但我真的不知道从哪里开始.任何帮助表示赞赏!

out*_*tis 14

一种简单的方法是将每个跨度包裹在另一个更大的跨度中.通过您希望鼠标能够接近内跨的最小距离,使每侧更大.绑定一个函数(evade),将每个包装器移动到mouseover包装器上.这种方法为您提供了方形边框,因此如果内部跨度中的图形元素不是方形,则鼠标到图形元素边框的距离将不会保持不变,但很容易实现.

或者,使用保险杠进行粗略接近测试.而不是绑定evade函数mouseover,绑定一个beginEvade绑定evade在mousemove上的function().另外,将函数mouseout绑定到unbinds 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());
    }
};
Run Code Online (Sandbox Code Playgroud)

接下来,一个样本循环逃避函数(这是最简单的实现).大纲:

  1. 计算保险杠的中心(保险杠的角落外部尺寸除以一半)
  2. 计算鼠标偏移矢量(从鼠标光标到元素的中心)
  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);
}
Run Code Online (Sandbox Code Playgroud)

在那之后,剩下的就是绑定/解除绑定的函数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);
});
Run Code Online (Sandbox Code Playgroud)

您可以在jsFiddle中预览