I'm trying to implement an animation that switches images on scroll when it's wrapping div scrolls into the viewport. My problem is that the animation starts as soon as someone starts scrolling, so the animation is already at the end when #wrapper comes into viewport.
How to achieve that the animation starts when #wrapper scrolls into the viewport?
Unfortunately my JS/jQuery knowledge is very poor but this is what I got til now:
JSFiddle
HTML:
<div class="page_content_before_image_animation">
<p>lorem ipsum …</p>
</div>
<div id="load" data-images="19"></div>
<div id="wrapper">
<img class="sequenzbilder" src="https://twdp.de/sequence/1.jpg" width="600" height="661" />
</div>
JS:
var images = [];
for (i = 1; i <= $('#load').attr('data-images'); i++) {
images.push('https://twdp.de/sequence/' + i + '.jpg');
}
$(images).each(function() {
$('<img class="sequenzbilder" />')[0].src = this;
});
var totalImages = images.length;
var pageHeight = $(document).height() - $(window).height();
var scrollInterval = Math.floor(pageHeight / 140);
var viewport = $(window),
slowdown;
viewport.on('scroll', function() {
i = Math.floor($(this).scrollTop() / scrollInterval);
$('.sequenzbilder').attr('src', images[i]);
slowdown = Math.ceil(viewport.scrollTop() / 20);
});
Related
Suppose I have 5 divs with 100vh height each in a container.
<div class="mycontainer" >
<div id="diview0" class="diview">0</div>
<div id="diview1" class="diview">1</div>
<div id="diview2" class="diview">2</div>
<div id="diview3" class="diview">3</div>
<div id="diview4" class="diview">4</div>
<div id="diview5" class="diview">5</div>
<div id="diview6" class="diview">6</div>
<div id="diview7" class="diview">7</div>
<div id="diview8" class="diview">8</div>
<div id="diview9" class="diview">9</div>
</div>
I scroll in that container but what happens is if a scroll up then it scrolls the div too much.
What I want is that it scroll a limited portion only.
For ex: if I scroll down 100px then it's good but on more than that(like 200 or 300) it should only scroll down 110px
same goes for scrolling up if I scroll up 100px then it's good but on more than that(like 200 or 300) it should only scroll up 110px.
Requirement is only of JavaScript. No jQuery or any other external library can be used.
How can I do it?
This is a way of doing it:
let maxS = 110;
let t = 2;
function isScrollable(x) {
let y = (Boolean(x))?"auto":"hidden";
document.documentElement.style.setProperty("overflow", y);
}
function timeoutScroll() {
let a = window.pageYOffset;
const temp = setInterval(function() {
if (window.pageYOffset >= a + maxS || window.pageYOffset <= a - maxS) {isScrollable(false)}},
100)
setTimeout(function() {isScrollable(true); clearInterval(temp)}, t*1000);
}
And the timeoutScroll function would stop scrolling the page for t seconds for more than maxS pixels
I'm new to web development.
I'm doing this animation with a sprite that allows you to move the image when the user scrolls or up. The problem is that the image shakes when I scroll. How can I fix this bug?
`
var rotator = $('#rotator');
var container = $(document);
var viewport = $(window);
var images = 10;
var imageHeight = 5930 / images;
var scrollHeight = container.height();
var position = images/scrollHeight;
viewport.scroll(function(event) {
rotator.css('background-position', (-position) + 'px 0');
if(position < 5930) {
position = position + imageHeight;
if (position >= 5930) {
position = 0;
}
} else {
position = 660;
}
});
`
I'm working on a progress bar animation which needs to animate from 0 to whatever percentage when the progress bar becomes visible within browser's viewport. Animation should always happen when element is scrolled into the view which means that scrolling it outside has to reset animation to start.
Here's my non-working code:
var $animation_elements = $('.progressAnimation');
var $window = $(window);
function check_if_in_view() {
var window_height = $window.height();
var window_top_position = $window.scrollTop();
var window_bottom_position = (window_top_position + window_height);
$.each($animation_elements, function() {
var $element = $(this);
var element_height = $element.outerHeight();
var element_top_position = $element.offset().top;
var element_bottom_position = (element_top_position + element_height);
//check to see if this current container is within viewport
if ((element_bottom_position >= window_top_position) &&
(element_top_position <= window_bottom_position)) {
$element.animate({
"width": (600 * $($element).data("percent")) / 100
}, 3000);
} else {
$element.animate({
"width": "0"
}, 1000)
}
});
}
$window.on('scroll resize', check_if_in_view);
$window.trigger('scroll');
body{
height:4000px;
margin-top:800px;
}
.myContainer{
width:1000px;
margin:50px auto;
}
.myContainer .progressBackground{
width:600px;
height:40px;
margin:0 auto 40px;
background-color:#eaeaea;
}
.myContainer .progressAnimation{
width:0;
height:100%;
background-color:#00f36d;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="myContainer">
<div class="progressBackground">
<div class="progressAnimation" data-percent="80">
</div>
</div>
<div class="progressBackground">
<div class="progressAnimation" data-percent="60">
</div>
</div>
</div>
Note: run code snippet in fullscreen.
Animating using Javascript within scroll/resize event isn't really wise. Without throttling the event it is wiser to do something very simple.
I haven't delved into your code and why it doesn't work, but I've devised an example based on your code, but I'm doing animation using CSS (offloading animation off of browser process), and simply changing elements' state when it's different from what it should be. This means that I'm shrinking progress bar to 0 only when element goes off screen (and not every single time a scroll/resize event fires which is what you're doing) and animating progress bar when it comes on screen only when it's been off screen.
This is the code:
var $animation_elements = $('.progressAnimation');
$(window).on('scroll resize', function(){
var viewportHeight = document.documentElement.clientHeight;
$animation_elements.each(function() {
var $el = $(this);
var position = this.getBoundingClientRect();
if (position.top > viewportHeight || position.bottom < 0) {
this.inView && $el.css({ width: 0 });
this.inView = false;
} else {
!this.inView && $el.css({ width: 6 * $el.data("percent") });
this.inView = true;
}
});
});
As you can see I've also used as much vanilla Javascript as possible to make event handler as fast as possible.
And here is a working JSFiddle.
I've created this script and it works pretty well except onload. On resize it works great and even on load it works great 90% of the time. I'm guessing that its due to the script running before the iframe is loaded but don't know what to do about it.
$( document ).ready(function() {
var content = $('#hero'); // top section container
var iframe = $('.videoWrapper iframe'); // iframe
var contentH = $(window).height() - 158; // set container height 100% of window minus some space for the header and sticky navbar
var contentW = $(window).width(); // set container width 100% of window
var iframeH = contentH - 150; // set iframe height to container height minus some space for margins and hgroup
content.css = ('height',contentH); // set container height
iframe.css = ('height',iframeH); // set iframe height
var iframeW = iframeH/9 * 16; // calculate iframe aspect ratio
iframe.css('width',iframeW); // set iframe width
} );
$('iframe').load(function() {
var content = $('#hero');
var iframe = $('.videoWrapper iframe');
var contentH = $(window).height() - 158;
var contentW = $(window).width();
var iframeH = contentH - 150;
content.css = ('height',contentH);
var iframeW = iframeH/9 * 16;
iframe.css = ('width',iframeW);
} );
$(window).resize(function() {
var content = $('#hero');
var iframe = $('.videoWrapper iframe');
var contentH = $(window).height() - 158;
var iframeH = contentH - 150;
content.css = ('height',contentH);
iframe.css = ('height',iframeH);
var iframeW = iframeH/9 * 16;
iframe.css('width',iframeW);
var margin = ($(window).width() - iframeW) / 2;
$('.videoWrapper').style.marginLeft = margin;
} );
<div id="hero">
<div class="container">
<div class="row-fluid">
<hgroup class="span12 text-center">
<h1></h1>
<h2></h2>
</hgroup>
<script src="https://www.youtube.com/iframe_api"></script>
<center>
<div class="videoWrapper">
<div id="player"></div>
</div>
</center>
<script>
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
videoId:'xxxxxxxxxxx',playerVars: {
disablekb:1,enablejsapi:1,iv_load_policy:3
}
} );
}
</script>
</div>
</div>
</div>
Here is the final result I ended up with..
See full gist here and live example here.
#hero { width:100%;height:100%;background:url('{$img_ps_dir}cms/how-it-works/hero.jpg') no-repeat top center; }
.videoWrapper { position:relative;padding-bottom:56.25%;padding-top:25px;max-width:100%; }
<div id="hero">
<div class="container">
<div class="row-fluid">
<script src="https://www.youtube.com/iframe_api"></script>
<center>
<div class="videoWrapper">
<div id="player"></div>
</div>
</center>
<script>
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
videoId:'xxxxxxxxxxx',playerVars: { controls:0,autoplay:0,disablekb:1,enablejsapi:1,iv_load_policy:3,modestbranding:1,showinfo:0,rel:0,theme:'light' }
} );
resizeHeroVideo();
}
</script>
</div>
</div>
</div>
var player = null;
$( document ).ready(function() {
resizeHeroVideo();
} );
$(window).resize(function() {
resizeHeroVideo();
});
function resizeHeroVideo() {
var content = $('#hero');
var contentH = viewportSize.getHeight();
contentH -= 158;
content.css('height',contentH);
if(player != null) {
var iframe = $('.videoWrapper iframe');
var iframeH = contentH - 150;
if (isMobile) {
iframeH = 163;
}
iframe.css('height',iframeH);
var iframeW = iframeH/9 * 16;
iframe.css('width',iframeW);
}
}
resizeHeroVideo is called only after the Youtube player has fully loaded (on page load does not work), and whenever the browser window is resized. When it runs, it calculates the height and width of the iframe and assigns the appropriate values maintaining the correct aspect ratio. This works whether the window is resized horizontally or vertically.
You're probably right. It's most likely not working because the browser doesn't have the iframe loaded yet.
If there's an onload event from the YouTube iframe API, you could try calling your function with that.
Or (quicker but hackier) simply put in a javascript timeout for a beat later:
setTimeout(
function()
{
/*your resize code*/
}, 5000);
Where the number is the delay in miliseconds.
I have the following code to make some parallax niceness which is mapped to the scroll bar.
It moves both the background position of the section and any elements in the section classed "mover"
It works fine with jQuery 1.4.x but when we upgraded to 1.5.2 the elements don't quite get back to their original positions
Does anyone know what changes in 1.5 would cause this?
var lastScrollTop = 0
var scrollTop = 0
$(window).scroll(function() {
scrollTop = $(window).scrollTop();
var move = lastScrollTop - scrollTop;
lastScrollTop = scrollTop;
$('.mover').each(function(i, element){
element = $(element);
if(!belowTheFold(element)){
var currentPos = parseInt(element.css("top"));
var speed = $(this).attr('data-scroll-speed');
var pos = currentPos + (move*speed);
element.css('top', pos);
}
});
$('.background-mover').each(function(i,element){
element = $(element);
if(!belowTheFold(element)){
var currentPos = parseInt(element.css("background-position-y"));
var speed = element.attr('data-scroll-speed');
var pos = currentPos + (move*speed);
element.css('background-position-y', pos);
}
});
});
function belowTheFold(element){
var fold = $(window).height() + $(window).scrollTop();
return fold <= element.offset().top;
}
HTML:
<section class="background-mover" data-scroll-speed="0.1" style="background:url(images/background.jpg) no-repeat; /*background-size:cover;*/ ">
Places
Nature
Landscape
Adventure
</section>
<section class="background-mover" data-scroll-speed="0.2" style="background:url('images/background-2.jpg') no-repeat; height:630px; ">
Getting Around
Events
Accomodation
</section>
<section class="background-mover" data-scroll-speed="0" style="background:url(images/background-3.jpg) no-repeat; /*background-size:cover;*/ height:1200px; ">
Culture
Must Do's
Getting Here
History
Facts
</section>