Javascript 试图获得一个div到";跟随;光标位于mousemove上,但有延迟
我想创建类似于旧鼠标轨迹的效果,其中div延迟但跟随光标 通过使用“设置间隔”(set interval)触发光标坐标的动画,我已经相当接近了Javascript 试图获得一个div到";跟随;光标位于mousemove上,但有延迟,javascript,jquery,Javascript,Jquery,我想创建类似于旧鼠标轨迹的效果,其中div延迟但跟随光标 通过使用“设置间隔”(set interval)触发光标坐标的动画,我已经相当接近了 $("body").mousemove(function (e) { if (enableHandler) { handleMouseMove(e); enableHandler = false; } }); timer = window.setInterval(function(){ enabl
$("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);
}
现在仍然存在两个问题:
尝试使用
.css()
,css
转换删除setInterval
$(文档).ready(函数(){
var cube=$(“#cube”);
$(“body”).mousemove(函数(e){
手推车(e);
});
功能handleMouseMove(事件){
var x=event.pageX,
y=event.pageY;
cube.css({
左:x+cube.width()/2+“px”,
顶部:y+cube.height()/2+“px”
}).parents(“body”).mousemove()
}
});代码>
正文{
溢出:隐藏;
位置:绝对位置;
身高:100%;
宽度:100%;
背景:#efef;
}
#立方体{
高度:50px;
宽度:50px;
利润上限:-25px;
左边距:-25px;
背景:红色;
位置:绝对位置;
最高:50%;
左:50%;
过渡:所有1.5s的轻松进出;
}
删除SetInterval并添加$(“#立方体”).stop();停止基于旧(x,y)的旧动画,以便可以启动新的“更快”动画
工作示例
我的做法略有不同。我没有使用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);
}
});
这里有一个解决方案,它可能会更像鼠标轨迹,因为它只会记住最后100个位置,并丢弃设置鼠标轨迹长度的旧位置
旧的鼠标轨迹功能使用了几个窗口的列表,这些窗口的形状类似于光标,每一帧都会更新它们的位置。基本上,它有一个“游标”列表,列表中“游标”旁边的每一帧都被移动到当前游标位置,实现了让每个假游标更新自己位置的效果,延迟假游标-1帧
可以使用requestAnimationFrame
、performance.now
和Event.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);
游戏在这里进行得太晚了,但我不太喜欢在这里添加延迟的任何选项,因为它们跟随鼠标之前的位置,而不是朝鼠标移动。因此,我对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;
}
它会在每次移动时保存光标位置,并以固定的时间间隔更新div位置,更新距离为其与最新光标位置之差的一小部分。我还把它改成了一个圆圈,因为这个圆圈看起来更好
这里的一个问题是,它经常触发,可能会减慢一台较弱的机器,降低更新频率会使光标跳得比我想象的要多,但可能在更新频率和跳跃性之间存在某种中间地带,或者使用我不熟悉的动画方法来自动移动。如果我不清楚的话,很抱歉-关键是div要“追赶”光标-有一个延迟,所以当鼠标移动时,div将缓慢(且平稳)跟随它,在鼠标停止后逐渐追赶。@chris.carruthers请参阅更新的帖子。“chase”可以在过渡设置和左侧设置以及顶部设置中进行调整,在.css()
我不确定我是否遗漏了一些内容,但尝试了这两种方法,它似乎仍然完全卡在光标上。这很好,接近我所追求的,是一个很好的简单解决方案。我这里唯一的问题是,我想象div在接近光标时会减速,而不是跳过光标。此外,在一个完全理想的世界中,“追逐动画”将更加平滑。谢谢是的,我顺便去了easeOutExpo,它真的很有帮助。不客气。很高兴这有帮助。:)你可以改变动画的dalay来投入更多的精力。这真是太棒了,几乎就是我想要的效果。我想我一直在尝试类似的东西,但我担心动画会被频繁触发,这会有多大问题?可能会有很多问题,考虑到每次鼠标稍微移动一点都会触发动画,我不确定它会对性能产生多大影响。一种解决方案可能是找到一种只在鼠标移动的开始、几个中点和结束时触发的方法。这可能说起来容易做起来难。是的,我想最终可能会归结到这一点,说起来肯定容易做起来难。不幸的是,这里有一种方法,如果鼠标移动至少2个像素,你只会触发动画。不过,这仍然不是一个很好的解决方案-很好,它确实减轻了一些重量。我接受麦克风的回答,因为结果肯定是最接近我想要的效果,但这里还有其他可靠的想法,它们可能也更轻。从guest271314获得额外的灵感后,我通过使用CSS动画降低了更新率以获得类似的效果,但它远不如每次都更新那么平滑
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);
$(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;
}