试图获得一个div来跟随"关注"光标在mousemove上,但有延迟

时间:2015-11-12 15:25:38

标签: javascript jquery

我想创建类似于旧鼠标轨道的效果,其中div被延迟但跟在光标之后。

通过使用set interval将动画触发到光标坐标,我已经相当接近了。

$("body").mousemove(function (e) {
    if (enableHandler) {
        handleMouseMove(e);
        enableHandler = false;
    }
});

timer = window.setInterval(function(){
    enableHandler = true;
}, 250);

function handleMouseMove(e) {

  var x = e.pageX,
      y = e.pageY;

      $("#cube").animate({
        left: x,
        top: y
      }, 200);

}

JSFiddle

现在仍然存在两个问题:

  1. 追逐' div非常跳跃(因为需要使用设置间隔)

  2. 如果在触发动画之前鼠标移动停止,div将保留在远离光标的位置。

6 个答案:

答案 0 :(得分:4)

删除SetInterval并添加$(“#cube”)。stop();停止基于旧(x,y)的旧动画,这样你就可以开始一个新的“更快”的动画。

$(document).ready(function() {
    $("body").mousemove(function (e) {
        $("#cube").stop();
        handleMouseMove(e);
    });

function handleMouseMove(event) {

  var x = event.pageX,
      y = event.pageY;

      $("#cube").animate({
        left: x,
        top: y
      }, 50);

}
});

工作示例 https://jsfiddle.net/jabnxgp7/

答案 1 :(得分:4)

我的做法略有不同。而不是使用setInterval(或甚至setTimeout) - 我只是让动画需要x毫秒才能完成。动画越长,下面的div似乎就越不敏感。

我注意到的唯一问题是,如果鼠标移动很多,它会被备份。

$(document).ready(function () {

    $("body").mousemove(function (e) {
        handleMouseMove(e);
    });

    function handleMouseMove(event) {

        var x = event.pageX;
        var y = event.pageY;

        $("#cube").animate({
            left: x,
            top: y
        }, 1);
    }
});

https://jsfiddle.net/jvmravoz/1/

答案 2 :(得分:1)

这是一个可能会模拟鼠标轨迹的解决方案,因为它只记住最后100个位置并丢弃旧的那些设置鼠标轨迹的长度。

https://jsfiddle.net/acmvhgzm/6/

$(document).ready(function() {

var pos = new Array();
$("body").mousemove(function (e) {
        handleMouseMove(e);
});

timer = window.setInterval(function() {
    if (pos.length > 0) {
        $('#cube').animate(pos.shift(),15);
    }
}, 20);

function handleMouseMove(event) {
  var x = event.pageX,
      y = event.pageY;
  if (pos.length = 100) {
      pos.shift();
  }
  pos.push({'left':x, 'top':y});
}

});

答案 3 :(得分:1)

这里超级晚了,但是我真的不喜欢在这里添加延迟的任何选项,因为它们遵循鼠标的先前位置而不是朝鼠标移动。因此,我对Mike Willis的代码进行了重大修改,以获取此代码-

$(document).ready(function () {

$("body").mousemove(function (e) {
  mouseMoveHandler(e);
});
var currentMousePos = { x: -1, y: -1 };
function mouseMoveHandler(event) {
  currentMousePos.x = event.pageX;
  currentMousePos.y = event.pageY;
}

mouseMover = setInterval(positionUpdate, 15);

function positionUpdate() {

  var x_cursor = currentMousePos.x;
  var y_cursor = currentMousePos.y;
  var position = $("#cube").offset();
  var x_box = position.left;
  var y_box = position.top;

  $("#cube").animate({
    left: x_box+0.1*(x_cursor-x_box),
    top: y_box+0.1*(y_cursor-y_box) 
  }, 1, "linear"); 
}
});
-----------------------------------------------------------------------
body { overflow:hidden; position:absolute; height:100%; width:100%; background:#efefef; }

#cube {
  height:18px;
  width:18px;
  margin-top:-9px;
  margin-left:-9px;
  background:red;
  position:absolute;
  top:50%;
  left:50%;   
}
.circleBase {
    border-radius: 50%;
}
.roundCursor {
    width: 20px;
    height: 20px;
    background: red;
    border: 0px solid #000;
}

https://jsfiddle.net/rbd1p2s7/3/

每次移动并以固定间隔保存光标位置时,它会以div位置与最新光标位置之间的差值的一小部分更新div位置。由于圆看起来更好,我也将其更改为一个圆。

这里需要担心的是,它经常触发,并且可能会使一台性能较差的机器变慢,降低更新频率会使光标跳得比我想要的还要多,但是在更新频率和跳动之间可能会找到一些中间立场,或使用我不熟悉的动画方法来自动执行动作。

答案 4 :(得分:0)

尝试使用setInterval.css() css

删除transition



$(document).ready(function () {
    var cube = $("#cube");
    $("body").mousemove(function (e) {
        handleMouseMove(e);
    });

    function handleMouseMove(event) {
        var x = event.pageX,
            y = event.pageY;
        cube.css({
            left: x + cube.width() / 2 + "px",
            top: y + cube.height() / 2 + "px"
        }).parents("body").mousemove()
    }
});

body {
    overflow:hidden;
    position:absolute;
    height:100%;
    width:100%;
    background:#efefef;

}
#cube {
    height:50px;
    width:50px;
    margin-top:-25px;
    margin-left:-25px;
    background:red;
    position:absolute;
    top:50%;
    left:50%;
    transition:all 1.5s ease-in-out;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
    <div id="cube"></div>
</div>
&#13;
&#13;
&#13;

答案 5 :(得分:0)

旧的鼠标跟踪功能使用了多个形状像光标的窗口的列表,这些窗口每帧都会更新其位置。基本上,它具有一个“光标”列表,并且列表中下一个“光标”的每一帧都被移动到当前光标位置,从而达到使每个假光标延迟fake cursors - 1帧来更新其自身位置的效果。 / p>

可以使用requestAnimationFrameperformance.nowEvent.timeStamp模拟单个对象的平稳按需延迟运动。想法是将鼠标事件保留在内部列表中,并仅在创建后经过特定时间后使用它们。

function DelayLine(delay, action){
    capacity = Math.round(delay / 1000 * 200);
    this.ring = new Array(capacity);
    this.delay = delay;
    this.action = action;
    this._s = 0;
    this._e = 0;
    this._raf = null;
    this._af = this._animationFrame.bind(this);
    this._capacity = capacity;
}
DelayLine.prototype.put = function(value){
    this.ring[this._e++] = value;
    if (this._e >= this._capacity) this._e = 0;
    if (this._e == this._s) this._get();
    cancelAnimationFrame(this._raf);
    this._raf = requestAnimationFrame(this._af);
}
DelayLine.prototype._get = function(){
    var value = this.ring[this._s++];
    if (this._s == this._capacity) this._s = 0;
    return value;
}
DelayLine.prototype._peek = function(){
    return this.ring[this._s];
}
DelayLine.prototype._animationFrame = function(){
    if (this._length > 0){
        if (performance.now() - this._peek().timeStamp > this.delay)
            this.action(this._get());
        this._raf = requestAnimationFrame(this._af);
    }
}
Object.defineProperty(DelayLine.prototype, "_length", {
    get: function() { 
        var size = this._e - this._s;
        return size >= 0 ? size : size + this._capacity;
    }
});

var delayLine = new DelayLine(100, function(e){
    pointer.style.left = e.x - pointer.offsetWidth/2 + "px";
    pointer.style.top = e.y - pointer.offsetHeight/2 + "px";
});

document.addEventListener("mousemove", function(e){
    delayLine.put(e);
}, false);

https://jsfiddle.net/os8r7c20/2/