我用 jQuery 编写了一个用于 360 度产品预览的脚本。它工作得很好。但如果我长时间“玩”它(拖动、放大、缩小等),它就会变得越来越慢。如果我缓慢地拖动鼠标,它工作正常,但它在快速鼠标移动时卡住。页面重新加载后,它再次正常工作几分钟,然后变慢。
什么会导致这种行为?是否有类似 jQuery 内存变满的东西?
根据请求,部分代码:
加载图片:
$.getJSON("load.php", {dir: 'images/'}, function(output) {
var imagelist = jQuery.makeArray(output.imagelist);
var zoomlist = jQuery.makeArray(output.zoomlist);
var cache = [];
function preload(arrayOfImages) {
$(arrayOfImages).each(function(){
var im = $("<img>").attr("src",this);
cache.push(im);
image.attr('src', this);
});
}
preload(imagelist);
旋转部分
holder.mousedown(function(e){
var enterPosition = e.pageX - this.offsetLeft;
isDown = true;
$(document).mousemove(function(e){
if(isDown && !isZoom){
var cursorPosition = e.pageX - contOffset.left;
var xOffset = cursorPosition - enterPosition;
var step = Math.round(contWidth/countFrames);
var frameOffset = Math.round(xOffset/step);
var cycles = Math.abs(Math.floor((frameOffset+startFrame)/countFrames));
currentFrame = startFrame + frameOffset;
if(currentFrame >= countFrames){
currentFrame = currentFrame - countFrames*cycles;
}
if(currentFrame < 0){
currentFrame = countFrames*cycles + currentFrame;
}
image.attr('src', imagelist[currentFrame]);
$('#info').html(currentFrame);
var corner = Math.floor(360/countFrames);
var degrees = corner*currentFrame;
var radians=degrees*Math.PI/180;
var sine=Math.sin(radians);
var cose=Math.cos(radians);
var poinx = rotCenter+rotRadius*sine*-1;
var poiny = rotCenter+rotRadius*cose
$('#pointer').css('left',poinx);
$('#pointer').css('top',poiny);
};
});
$(document).mouseup(function(){
isDown = false;
startFrame = currentFrame;
});
});
缩放部分
$('#zoom').click(function(e){
var isZoom = true;
var offset = holder.offset();
var startXpos = e.pageX - offset.left;
var startYpos = e.pageY - offset.top;
var zoomImg = new Image();
zoomImg.onload = function() {
zoomHeight = zoomImg.height;
zoomWidth = zoomImg.width;
var leftOverflow = (zoomWidth - contWidth)/-2;
var topOverflow = (zoomHeight - contHeight)/-2;
image.attr('src', zoomlist[currentFrame]);
image.css('left', leftOverflow);
image.css('top', topOverflow);
$('#round').fadeOut();
$('#zoom').fadeOut();
holder.addClass('zoomout');
holder.mousemove(function(e){
if(isZoom){
var currentXpos = e.pageX - offset.left;
var currentYpos = e.pageY - offset.top;
var xlimit = (zoomWidth-contWidth)*-1;
var ylimit = (zoomHeight-contHeight)*-1;
var xSpeedCoeff = Math.floor(zoomWidth/contWidth);
var ySpeedCoeff = Math.floor(zoomHeight/contHeight);
var moveLeft = startXpos - currentXpos;
var moveTop = startYpos - currentYpos;
var leftOffset = leftOverflow + moveLeft*xSpeedCoeff;
var topOffset = topOverflow + moveTop*ySpeedCoeff;
var hMoveLock = false;
var vMoveLock = false;
if(leftOffset >= 0){
hMoveLock = true;
startXpos = startXpos - leftOffset;
}
if(leftOffset <= xlimit){
hMoveLock = true;
startXpos = startXpos - leftOffset + xlimit;
}
if(topOffset >= 0){
vMoveLock = true;
startYpos = startYpos - topOffset;
}
if(topOffset <= ylimit){
vMoveLock = true;
startYpos = startYpos - topOffset + ylimit;
}
if(!hMoveLock) {
image.css('left', leftOffset);
}
if(!vMoveLock) {
image.css('top', topOffset);
}
holder.mousedown(function(){
image.attr('src', imagelist[currentFrame]);
image.css('left', 0);
image.css('top', 0);
$('#round').fadeIn();
$('#zoom').fadeIn();
holder.removeClass('zoomout');
pan = false;
isZoom = false;
});
}
});
}
zoomImg.src = zoomlist[currentFrame];
});
我知道,代码不清楚,现在就在这里,如果有任何建议,我将不胜感激。
最佳答案
发生这种情况的原因有很多,如果没有看到代码就不可能说 既然您已经发布了代码,请参阅下面的更新:
我想到了几种可能性:
是的,您可能分配了很多对象,然后要么不释放它们,要么垃圾收集器运行缓慢。
您可能会不经意地一遍又一遍地重新附加事件处理程序,因此事件(最终触发所有附加的处理程序)会因为附加的(冗余)处理程序的数量而变慢。
发布代码后
更新:
它是#2,这是有问题的代码(它可能不是唯一有问题的代码):
holder.mousedown(function(e){
var enterPosition = e.pageX - this.offsetLeft;
isDown = true;
$(document).mousemove(function(e){
// ...
});
$(document).mouseup(function(){
// ...
});
});
当 mousedown
事件在 holder
元素上触发时,您正在做的是添加一个新的mousemove
和 mouseup
到文档的处理程序,在已经存在的任何处理程序之上。所以每次 mousedown 都会向链中引入一个新的处理程序。由于 mousemove
发生了很多,因此不断增加的处理程序链被称为很多。
您应该只附加 mousemove
和 mouseup
处理程序一次,而不是在每个 mousedown
上,或者您应该确保在 mouseup
上删除它们。 (后者将要求您不像目前那样使用匿名函数,因为您需要将相同函数引用传递给您[间接]传递给的unbind
bind
。编辑:或者您可以使用 jQuery 的“命名空间”事件内容。)
FWIW,这应该让您开始使用一次附加版本:
(function() { // Scoping function so isDown and enterPosition aren't globals
var isDown = false,
enterPosition;
// I don't know where `holder` or `startFrame` come from, but presumably you do
// Hook up mousedown on holder
holder.mousedown(function(e){
enterPosition = e.pageX - this.offsetLeft;
isDown = true;
});
// Hook up mousemove on document (just once)
$(document).mousemove(function(e){
// Flag controls whether we do anything
if(isDown && !isZoom){
var cursorPosition = e.pageX - contOffset.left;
var xOffset = cursorPosition - enterPosition;
var step = Math.round(contWidth/countFrames);
var frameOffset = Math.round(xOffset/step);
var cycles = Math.abs(Math.floor((frameOffset+startFrame)/countFrames));
currentFrame = startFrame + frameOffset;
if(currentFrame >= countFrames){
currentFrame = currentFrame - countFrames*cycles;
}
if(currentFrame < 0){
currentFrame = countFrames*cycles + currentFrame;
}
image.attr('src', imagelist[currentFrame]);
$('#info').html(currentFrame);
var corner = Math.floor(360/countFrames);
var degrees = corner*currentFrame;
var radians=degrees*Math.PI/180;
var sine=Math.sin(radians);
var cose=Math.cos(radians);
var poinx = rotCenter+rotRadius*sine*-1;
var poiny = rotCenter+rotRadius*cose
$('#pointer').css('left',poinx);
$('#pointer').css('top',poiny);
};
});
// Hook mouseup on document (just once)
$(document).mouseup(function(){
isDown = false;
startFrame = currentFrame;
});
})();
如果您的代码已经在作用域函数中,则不需要我介绍的新代码。
关于javascript - 是否有类似 Jquery 内存或缓存的东西?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9377088/