Slow scroll when detect image - javascript

I have the problem with the scenario.
We have a page with text which is scrollable
When image is detected, scrolling should be slower
When image is over, scrolling gets back to default speed.
I have detection of element and trying to do slowing scroll with using transform, but without luck. It is slower a little bit, but it does not look like properly.
function elementInViewport2(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
}
/*window.addEventListener('scroll', function(e) {
var el = document.getElementById('slides');
console.log(elementInViewport2(el));
});*/
$.fn.moveIt = function(){
var $window = $(window);
var instances = [];
$(this).each(function(){
instances.push(new moveItItem($(this)));
});
window.addEventListener('scroll', function(){
var scrollTop = $window.scrollTop();
var el = document.getElementById('slides');
if (elementInViewport2(el)) {
instances.forEach(function(inst){
inst.update(scrollTop, -20);
});
}
}, {passive: true});
}
var moveItItem = function(el){
this.el = $(el);
console.log(el);
this.speed = parseInt(this.el.attr('data-scroll-speed'));
};
moveItItem.prototype.update = function(scrollTop, speed){
this.el.css('transform', 'translateY(' + -(scrollTop / speed) + 'px)');
};
// Initialization
$(function(){
$('[data-scroll-speed]').moveIt();
});
https://jsfiddle.net/pnrszyzn/

Related

javascript : Lazy loading for images using eventlistener and debounce

I have several div with class 'comp'. Each comp has images inside. What I want to achieve is to implement lazy loading for images insdie each comp. So, that when a specific comp element enters in the viewport I want the images to be loaded.
I want to use eventlistener and debounce as a polyfill approach as I tried the intersection observer DOM API but it has a limitation i.e. it is not supported by some recent Safari and IE versions.
Any help in this regards will be really appreciated.
Code:
const options = {
threshold: 0
};
const io = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
loadImage(entry.target);
entry.target.classList.add('loaded');
io.unobserve(entry.target);
}
});
}, options);
const targetElements = document.querySelectorAll(".comp");
for (let element of targetElements) {
if (document.body.className.match(/\bintersection-observer-supported\b/)) {
io.observe(element);
} else {
var domRect = element.getBoundingClientRect();
}
}
function loadImage(imageElement) {
setTimeout(() => {
console.dir(imageElement.querySelector('img'));
imageElement.querySelector('img.target-image').src = imageElement.querySelector('img.target-image').dataset.src;
}, 500);
}
//Polyfill
function elementInViewport(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
}

trigger animation at the end of debounced requestanimationframe

I followed Paul Lewis's guide to debounce and requestAnimationFrame. I'm translating an image across the screen on scroll when it comes into view.
var bicycles = $('.tandem-bike', context),
lastScrollY = 0,
ticking = false;
function update() {
var windowHeight = window.innerHeight,
windowWidth = $(window).width(),
bikeTop = [];
bicycles.each( function (i, el) {
bikeTop[i] = $(this).offset();
});
bicycles.each(function(i, el) {
var position = bikeTop[i];
var fromTop = position.top - windowHeight;
var imgHeight = $(this).height();
// When this image scrolls into view.
if (lastScrollY > fromTop && lastScrollY < position.top + imgHeight && i == 1 ) { // 375 ~= height of image
var translate = Math.floor((lastScrollY - fromTop) / ((windowHeight + imgHeight + 300) / windowWidth));
console.log('add tp tranlate ', translate);
$(this).css('transform', 'translateX(' + (translate - 275) + 'px)');
}
});
ticking = false;
}
function onScroll() {
lastScrollY = window.scrollY;
requestTick();
}
function requestTick() {
if(!ticking) {
requestAnimationFrame(update);
ticking = true;
}
}
window.addEventListener('scroll', onScroll, false);
This works great and the bicycle-built-for-two slides effortlessly across the screen. However, I want the image to "bounce" when the user stops scrolling. I figure an easy way would be to add a class when the animation ends, and pull it off when the animation starts. The obvious place to do that is within the if block in requestTick().
if(!ticking) {
$('.tandem-bike').removeClass('bounce');
requestAnimationFrame(update);
$('.tandem-bike').addClass('bounce');
ticking = true;
}
or
if(!ticking) {
requestAnimationFrame(update);
$('.tandem-bike').addClass('bounce');
ticking = true;
} else {
$('.tandem-bike').removeClass('bounce');
}
}
Neither works, and I don't love then because I'm whole-sale adding classes to all the animated images on the page. (I would live with that if it worked)

Continuous Scroll Loop between two divs

I am trying to alter this JSFiddle so that the container is infinitely scrollable both up and down (in a loop). How do I set window.scrollY to handle scrolling up and down on the Y axis?
Here the javascript I am working with:
window.addEventListener('load', function() {
var box = document.getElementById('box'),
box2 = document.getElementById('box2'),
container = document.getElementById('container'),
outer_container = document.getElementById('outer-container'),
current_box = box,
docHeight = document.documentElement.offsetHeight;
window.addEventListener('scroll', function() {
// normalize scroll position as percentage
var scrolled = window.scrollY / (docHeight - window.innerHeight),
scale = 1 - scrolled
transformValue = 'scale(' + (scale) + ')';
current_box.style.WebkitTransform = transformValue;
current_box.style.MozTransform = transformValue;
current_box.style.OTransform = transformValue;
current_box.style.transform = transformValue;
if (scale == 0) {
outer_container.appendChild(current_box);
var older_box = current_box;
current_box = current_box == box ? box2 : box;
container.appendChild(current_box);
window.scrollTo(0, 0);
older_box.style.WebkitTransform = "0";
older_box.style.MozTransform = "0";
older_box.style.OTransform = "0";
older_box.style.transform = "0";
}
}, false);
document.getElementById('nav').addEventListener('click', function(event) {
var level = parseInt(event.target.getAttribute('href').slice(1), 10),
// normalize scroll position
scrollY = (level / 4) * (docHeight - window.innerHeight);
// enable transitions
current_box.className = 'transitions-enabled';
// change scroll position
window.scrollTo(0, scrollY);
}, false);
function transitionEnded(event) {
// disable transition
current_box.className = '';
}
current_box.addEventListener('webkitTransitionEnd', transitionEnded, false);
current_box.addEventListener('transitionend', transitionEnded, false);
current_box.addEventListener('oTransitionEnd', transitionEnded, false);
}, false);

Why is (window.innerwidth > 1025) working in all browsers except Firefox?

I'm using (window.innerwidth > 1025) to allow parallax code in windows larger than 1025px wide. This works perfectly in all browsers (Chrome, IE, Safari) except Firefox.
When I remove the first line, the parallax works as expected in Firefox.
if (window.innerWidth > 1025){
var $window = $(window);
var windowHeight = $(window).height();
var pos = $window.scrollTop(); //position of the scrollbar
var $this = $(this);
//setup defaults if arguments aren't specified
if(xpos == null){xpos = "50%"}
if(adjuster == null){adjuster = 0}
if(inertia == null){inertia = 0.1}
if(outerHeight == null){outerHeight = true}
height = $this.height();
$this.css({'backgroundPosition': newPos(xpos, outerHeight, adjuster, inertia)});
function newPos(xpos, windowHeight, pos, adjuster, inertia){
return xpos + " " + Math.round((-((windowHeight + pos) - adjuster) * inertia)) + "px";
}
//function to be called whenever the window is scrolled or resized
function move(pos, height){
$this.css({'backgroundPosition': newPos(xpos, height, pos, adjuster, inertia)});
}
$window.bind('scroll', function(){ //when the user is scrolling...
pos = $window.scrollTop(); //position of the scrollbar
inView(pos, $this);
})
}

Parallax H1 and H2

Can someone tell me how to adjust this .js? I want it to be able to apply on H1 and H2 with an ID in my html. Now it is only working on css background-image. Below is the .js I'm using. I'm a beginner with javascript;)
Hope you guys can help me out!
(function( $ ){
var $window = $(window);
var windowHeight = $window.height();
$window.resize(function () {
windowHeight = $window.height();
});
$.fn.parallax = function(xpos, speedFactor, outerHeight) {
var $this = $(this);
var getHeight;
var firstTop;
var paddingTop = 0;
//get the starting position of each element to have parallax applied to it
$this.each(function(){
firstTop = $this.offset().top;
});
if (outerHeight) {
getHeight = function(jqo) {
return jqo.outerHeight(true);
};
} else {
getHeight = function(jqo) {
return jqo.height();
};
}
// setup defaults if arguments aren't specified
if (arguments.length < 1 || xpos === null) xpos = "50%";
if (arguments.length < 2 || speedFactor === null) speedFactor = 0.1;
if (arguments.length < 3 || outerHeight === null) outerHeight = true;
// function to be called whenever the window is scrolled or resized
function update(){
var pos = $window.scrollTop();
$this.each(function(){
var $element = $(this);
var top = $element.offset().top;
var height = getHeight($element);
// Check if totally above or totally below viewport
if (top + height < pos || top > pos + windowHeight) {
return;
}
$this.css('backgroundPosition', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");
});
}
$window.bind('scroll', update).resize(update);
update();
};
})(jQuery);
It should be background-position. Can you try changing?
$this.css('background-position', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");

Categories