javascript - What's best way to run same function on multiple elements only when they're inside viewport? -
i have 3 elements background images want scale x 1. want begin when top of element inside viewport (this may vary little).
i have achieved effect long way:
function animatepanelbackgrounds() { var $toolsbg = $('#js-tools-bg'), $dennysbg = $('#js-dennys-bg'), $verizonbg = $('#js-verizon-bg'), $llbeanbg = $('#js-llbean-bg'); var dennystop = math.floor( $("#js-dennys").offset().top ); var dennysgo = dennystop - window.innerheight; var llbeantop = math.floor( $("#js-llbean").offset().top ); var llbeango = llbeantop - window.innerheight; var verizontop = math.floor( $("#js-verizon").offset().top ); var verizongo = verizontop - window.innerheight; var toolstop = math.floor($toolsbg.offset().top); var toolsgo = 0; var ratio, $that; if ( thiswindows.offsety() >= toolsgo ) { ratio = toolstop/(thiswindows.offsety()*10); $that = $toolsbg; $that.css({ "transform": "scale(" + (1.0 + thiswindows.offsety()*.0002) + ")", "-webkit-transform": "scale(" + (1.0 + thiswindows.offsety()*.0002) + ")", "-moz-transform": "scale(" + (1.0 + thiswindows.offsety()*.0002) + ")" }) } if ( thiswindows.offsety() >= dennysgo ) { ratio = dennystop/thiswindows.offsety()*.8; $that = $dennysbg; if ( ratio <= 1 ) { $that.css({ "transform": "scale(1)", "-webkit-transform": "scale(1)", "-moz-transform": "scale(1)" }) } else { $that.css({ "transform": "scale(" + ratio + ")", "-webkit-transform": "scale(" + ratio + ")", "-moz-transform": "scale(" + ratio + ")" }) } } if ( thiswindows.offsety() >= verizongo ) { ratio = verizontop/thiswindows.offsety()*.8; $that = $verizonbg; if ( ratio <= 1 ) { $that.css({ "transform": "scale(1)", "-webkit-transform": "scale(1)", "-moz-transform": "scale(1)" }) } else { $that.css({ "transform": "scale(" + ratio + ")", "-webkit-transform": "scale(" + ratio + ")", "-moz-transform": "scale(" + ratio + ")" }) } } if ( thiswindows.offsety() >= llbeango ) { ratio = llbeantop/thiswindows.offsety()*.8; $that = $llbeanbg; if ( ratio <= 1 ) { $that.css({ "transform": "scale(1)", "-webkit-transform": "scale(1)", "-moz-transform": "scale(1)" }) } else { $that.css({ "transform": "scale(" + ratio + ")", "-webkit-transform": "scale(" + ratio + ")", "-moz-transform": "scale(" + ratio + ")" }) } } } $(window).on('scroll', function() { animatepanelbackgrounds(); }
i have achieved function take couple simple parameters:
function scalebackground(element, multiplier) { var $el = $(element), eltop = math.floor( $el.offset().top), startposition = eltop - window.innerheight; $win.on('scroll', function() { if(thiswindows.offsety() >= startposition) { var ratio = eltop/thiswindows.offsety()*multiplier; if ( ratio <= 1 ) { $el.css({ "transform": "scale(1)", "-webkit-transform": "scale(1)", "-moz-transform": "scale(1)" }) } else { $el.css({ "transform": "scale(" + ratio + ")", "-webkit-transform": "scale(" + ratio + ")", "-moz-transform": "scale(" + ratio + ")" }) } } }) } scalebackground('#js-dennys-bg', '.8'); scalebackground('#js-llbean-bg', '.8'); scalebackground('#js-verizon-bg', '.8');
i feel should handled in loop of sorts, haven't had luck. here's basic attempt, i've tried tweaking little things in along way 0 success:
var panels = $('.panel__bg'); ( = 0; < panels.length; i++ ) { var $that = $(panels[i]), begin = $that.offset().top; if ( begin <= window.scrolly ) { var ratio = begin/(window.scrolly * 10); if ( ratio <= 1 ) { $that.css({ "transform": "scale(1)", "-webkit-transform": "scale(1)", "-moz-transform": "scale(1)" }) } else { $that.css({ "transform": "scale(" + ratio + ")", "-webkit-transform": "scale(" + ratio + ")", "-moz-transform": "scale(" + ratio + ")" }) } } }
my question, finally, simply: best way this. "best way", extremely concerned performance , secondly concerned readability/fewest lines of code.
here critique code. it's untested, addresses of concerns.
// .each easier understand, , cleaner looking loop $('.panel__bg').each(function(i, panel){ // name makes more sense "$that", e.g. "$panel" var $panel = $(panel), begin = $panel.offset().top; if ( begin <= window.scrolly ) { // caps ratio=1. no need if/else block var ratio = math.min(1, begin/(window.scrolly * 10)); // on so, helps show code relevant issue $panel.css({"transform": "scale(" + ratio + ")" }); } });
i assume code being run every time scroll event fired. might run trouble on ios because js execution blocked during scroll. see issue.