I have a question regarding the scrolling of a background image that repeats it self endlessly. The problem i am having is that it is starts off fast but quickly become slower and slower (stuttering etc.). Here is the code:
var panoramaTimeOutId = null;
var panoramaPosition = null;
$('.panorama-left').mousedown(function() {
panoramaTimeOutId = setInterval(function(){
panoramaMove(8, 1)
}, 50);
}).bind('mouseup mouseleave', function() {
clearInterval(panoramaTimeOutId);
});
$('.panorama-right').mousedown(function() {
panoramaTimeOutId = setInterval(function(){
panoramaMove(8, 2)
}, 50);
}).bind('mouseup mouseleave', function() {
clearInterval(panoramaTimeOutId);
});
function panoramaMove(amount, direction)
{
var panorama = document.getElementsByClassName('panorama_foto')[0];
if(panoramaPosition == null)
{
panoramaPosition = panorama.style.backgroundPosition;
panoramaPosition = parseInt(panoramaPosition[0].replace("px",""));
}
if(direction == 1)
{
panoramaPosition = panoramaPosition + amount;
panorama.style.backgroundPosition = panoramaPosition+"px";
}
else
{
panoramaPosition = panoramaPosition - amount;
panorama.style.backgroundPosition = panoramaPosition+"px";
}
}
And i have already tried a few things for optimization.Like writing the function with standard javascript. Calculating the panoramaPosition only one time before just incrementing it through a variable that only contains a simple int. Yet it still stutters.
I also tried changing the interval timing and the amount of px but it still stutters on certain computers. For example the site is designed for tablets on tablets it stutters on the pc on which i program it does not. And it is mandatory that it works properly on the tablet.
Here is a JSbin example: http://jsbin.com/upociv/1/edit
Hopefully somebody can give tips on how to optimize this or general suggestions how i would improve it.
Quick note: must be supported by Ipad (1/2/3) all galaxy tablets and ie 8+ firefox chrome etc.
Instead of moving the panoramaPosition by an ever-increasing number of pixels, try moving it by panoramaPosition % (image width) instead.
This way, you won't have the browser trying to invisibly tile the background image starting 10,000 pixels to the left -- instead, it will never have to tile it more than twice. (You'll also avoid the small, but nonzero, possibility of an integer overflow error.)
if(direction == 1)
{
panoramaPosition = panoramaPosition + amount;
panorama.style.backgroundPosition = (panoramaPosition%1277)+"px";
}
else
{
panoramaPosition = panoramaPosition - amount;
panorama.style.backgroundPosition = (panoramaPosition%1277)+"px";
}
http://jsbin.com/upociv/2/edit
However, if you can implement this in CSS3, you should -- Modernizr lets you detect in JavaScript whether a browser supports CSS3 transitions and transformations or not.
jQuery has large overheads so I've been playing with re-writing it to not use jQuery since my comment. Also, to cache as much as possible. Calling Panorama returns an Object which has everything neatly in properties. First two params are required.
I did a compatibility thing for addEventListener I called listen, you might need one for getElementsByClassName, too.
Demo and Code
function Panorama(fullheight, fullwidth, foto, left, right) {
var panorama = {};
// crossbrowser listener
function listen(node, ev, fn) {
var a = ev.split(' '), i;
if (node.addEventListener)
for (i = 0; i < a.length; ++i)
node.addEventListener(a[i], fn);
else
for (i = 0; i < a.length; ++i)
node.attachEvent('on' + a[i], fn);
}
// short convert (px?) string to number, might be useful
function Xpx(s) {
return parseFloat(s.replace(/[^\d.]/, ''));
}
// movement
function move(amount, direction) {
if(direction) {
panorama.position += amount;
if (panorama.position > panorama.width)
panorama.position %= panorama.width;
foto.style.backgroundPosition = panorama.position + 'px';
}
else {
panorama.position -= amount;
if (panorama.position < 0)
panorama.position = panorama.width - ((-panorama.position) % panorama.width);
foto.style.backgroundPosition = panorama.position + 'px';
}
}
function zoom(scale) {
panorama.scale = scale;
panorama.height = scale * fullheight;
panorama.width = scale * fullwidth;
foto.style.zoom = scale;
}
panorama.move = move;
panorama.zoom = zoom;
// cache nodes
if (!foto) foto = document.getElementsByClassName('panorama_foto')[0];
if (!left) left = document.getElementsByClassName('panorama-left')[0];
if (!right) right = document.getElementsByClassName('panorama-right')[0];
panorama.node = {
foto: foto,
left: left,
right: right
};
// panorama scaled size info
panorama.height = fullheight;
panorama.width = fullwidth;
panorama.scale = 1;
// values
panorama.timeout = null;
panorama.position = 0;
// left
listen(left, 'mousedown', function() {
panorama.timeout = setInterval(
function(){ move(8, 1); },
50
);
});
listen(left, 'mouseup mouseout', function() { clearInterval(panorama.timeout); });
// right
listen(right, 'mousedown', function() {
panorama.timeout = setInterval(
function(){ move(8, 0); },
50
);
});
listen(right, 'mouseup mouseout', function() { clearInterval(panorama.timeout); });
return panorama;
}
var pan = Panorama(414, 1277);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With