Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Background image Panorama

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.

like image 927
N.Schipper Avatar asked Jun 16 '26 16:06

N.Schipper


2 Answers

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.

like image 81
Blazemonger Avatar answered Jun 19 '26 06:06

Blazemonger


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);
like image 22
Paul S. Avatar answered Jun 19 '26 07:06

Paul S.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!