//@ init $(document).ready(function(){ var $doc = $(document); var $win = $(window); //@ dimensions - we want to cache them on window resize var windowHeight, windowWidth; var fullHeight, scrollHeight; var streetImgWidth = 1024, streetImgHeight = 640; calculateDimensions(); var currentPosition = -1, targetPosition = 0; var $videoContainer = $('.street-view'); var video = $('.street-view > video')[0]; var $hotspotElements = $('[data-position]'); //@ handling resize and scroll events function calculateDimensions() { windowWidth = $win.width(); windowHeight = $win.height(); fullHeight = $('#main').height(); scrollHeight = fullHeight - windowHeight; } function handleResize() { calculateDimensions(); resizeBackgroundImage(); handleScroll(); } //@ set the target position to the relative (0..1) scroll position function handleScroll() { targetPosition = $win.scrollTop() / scrollHeight; } //@ main render loop window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(/* function */ callback, /* DOMElement */ element){ window.setTimeout(callback, 1000 / 60); }; })(); //@ on every loop: approximate current to target position function animloop(){ if ( Math.floor(currentPosition*5000) != Math.floor(targetPosition*5000) ) { currentPosition += (targetPosition - currentPosition) / 5; render(currentPosition); } requestAnimFrame(animloop); } animloop(); //@ rendering function render( position ) { // position the elements var minY = -windowHeight, maxY = windowHeight; $.each($hotspotElements,function(index,element){ var $hotspot = $(element); var elemPosition = Number( $hotspot.attr('data-position') ); var elemSpeed = Number( $hotspot.attr('data-speed') ); var elemY = windowHeight/2 + elemSpeed * (elemPosition-position) * scrollHeight; if ( elemY < minY || elemY > maxY ) { $hotspot.css({'visiblity':'none', top: '-1000px','webkitTransform':'none'}); } else { $hotspot.css({'visiblity':'visible', top: elemY, position: 'fixed'}); } }); renderVideo( position ); } //@ video function renderVideo(position) { if ( video.duration ) { video.currentTime = position * video.duration; } } //@ image function resizeBackgroundImage(){ // get image container size var scale = Math.max( windowHeight/streetImgHeight , windowWidth/streetImgWidth ); var width = scale * streetImgWidth , height = scale * streetImgHeight; var left = (windowWidth-width)/2, top = (windowHeight-height)/2; $videoContainer .width(width).height(height) .css('position','fixed') .css('left',left+'px') .css('top',top+'px'); } //@ setting up scroll and resize listeners $win.resize( handleResize ); $win.scroll( handleScroll ); handleResize(); });