Good Morning. I am a student of web development and I am curious to know with which technologies it is possible to realize this floating effect as in this site: https://www.fbiz.com.br/
Could any of you show me a code as an example?
As far as I can tell from the (minified) source code, they are using a JavaScript that applies a transform CSS style to the 'floating' elements as the user scrolls.
Their JavaScript code might look something like this (overly simplified):
let element = document.querySelector('.foo');
window.onscroll = function(){
let value = window.scrollY / 30 + 'px';
element.style.transform = 'translateY(' + value + ')';
}
Related
I've created some effects in JavaScript (and with simple, CSS controlled animations), and they are working well, but costs a lot of hardware resources (especially GPU), so on devices with less performance, the webpage appears laggy when scrolling. The interesting thing is that I opened some webpages also with a lot of scroll-linked animations on devices with weak performance, and the animations looks smooth and nice.
I searched for solutions with performance improvement in scroll-linked effects, but the only thing I found is server-side pre-rendering (make screenshots from the webpage, and this way the page appears in one gif/video which frames are controlled depending on scroll). I was consider that it's possible to the root of the problem is that I don't use frameworks (JQuery, CSS preprocessors), but it can't be the only reason for this amount of performance cost. I tried to play with will-change in CSS, which make the effects smoother, but not enough.
An example of the effects I've created:
window.onscroll = function() {
var element = document.querySelector(.exampleElement),
elementsContainer = element.parentNode,
effect = (element.offsetTop - window.pageYOffset) / window.innerHeight;
elementsContainer.style.perspective = "1000px";
element.style.transform = "rotateX(" + effect * 90 + "deg)";
}
My question is that the only way to improve performance (to make the animations smooth on any devices) is the server-side rendering, or there are another way to do it? How other pages which uses scroll-linked animations make their effects smooth on any device?
The most obvious improvement is to move as much as possible outside of the scroll handler. Cause the handler is very vital for performance as it is triggered very often:
var element = document.querySelector(.exampleElement),
elementsContainer = element.parentNode;
elementsContainer.style.perspective = "1000px";
window.onscroll = function() {
const effect = (element.offsetTop - window.pageYOffset) / window.innerHeight;
element.style.transform = "rotateX(" + effect * 90 + "deg)";
}
I tried to experiment with parallax and started from scratch to understand the core parts of this magic. To give you an example that I like to use as inspiration, you can see it at this link here at the "Photos" section.
Latest code is down the page with related information. To get an overall look of the question see the rest of the details.
Core parts I already know are the scrollTop() of the $window and the offsetTop of the element are important to apply the parallax effect on a DOM element as well as a factor for how sensitive the effect should be respond to the scroll speed. The end result should be some formule that will calculate the translateY or translate3d coordinates in pixels or percentage.
I read on the internet that the CSS property translate is faster than, for example, top from position: absolute, and my preference would be also to use translate in combination with TweenMax GSAP. So the movement of the parallax will be very smooth. But if only the css property translate is enough that's fine too. I saw some examples that where using TweenMax, so that's why I use it for now.
JS
I have code the basic things:
var win = $(window);
var el = $('#daily .entry').find('figure');
win.scroll(function() {
var scrollTop = win.scrollTop();
var parallaxFactor = 5;
el.each(function() {
var image = $(this).find('img');
var offsetTop = $(this).offset().top;
// This is the part where I am talking about.
// Here should be the magic happen...
});
});
So I've code above code, but it doesn't do anything, of course. See CodePen from above code here. It will only console log scrollTop and offsetTop. As mentioned before, I only know the core parts like scrollTop and offsetTop to apply the parallax effect. Then there should be some area created where the parallax effect will be triggered and happen, so calculations will be only done for elements within the viewport in order to keep the performance good. After that there should be some math done, but doesn't know exactly what or how to achieve this. Only after I have a final number, I could use it within for example TweenMax from Greensock like so:
TweenMax
TweenMax.to(image, 0.1, {
yPercent: offsetPercent + '%',
ease: Linear.easeNone
});
Parallax formula
If I look around to get the formula down I came to something like this (founded on the internet):
var viewportOffset = scrollTop - offsetTop + win.height();
var offsetPercent = ((viewportOffset / win.height() * 100) - 100) / parallaxFactor;
if (viewportOffset >= 0 && viewportOffset <= win.height() * 2) {
TweenMax.to(image, 0.1, {
yPercent: offsetPercent + '%',
ease: Linear.easeNone
});
}
But if I am honest, I doesn't know what this does exactly, or why it should/could be this way. I would like to know this, so I can understand the whole process of making parallax happen. The functions of scrollTop(), offsetTop and $(window).height() are clear for me, but what the trick behind the formula is, is the part that I doesn't understand.
Updates
Update 1
#Scott has notified that the inspiration site uses a plugin called scrollmagic.io, but I am very curious about how I can create a parallax by myself without the use of a plugin. How it works and how to achieve it. With emphasis on the formula, why I should it do this or that way and what exactly will be calculated, because I don't understand it and really wanna know this, so that I can use this knowledge in the future when applying a parallax effect.
Update 2
I tried to figure out what the following code snippet exactly does. I talking about this one:
var viewportOffset = scrollTop - offsetTop + win.height();
After some good debug sessions I think that I've the clue. So scrollTop is the amount of pixels that you've scrolled down the page and that are hidden from the view. offsetTop is the start position of the element within the DOM and $(window).height is the viewport height - the part that is visible in the browser -.
This is what I think that this formula does:
Set the zero point to the point where the element starts. For example, when scrollTop is equal to 0 and the element starts at 240px from the top, then the formula is: 0 minus 240 is -240. So the current scroll position is below zero point. After scrolling 240px down, the formula will output 0 because of course 240 minus 240 is 0 (zero). Am I right?
But the part that I doesn't understand yet is why + win.height.
If we go back to above formula (at Update 2) and scrollTop is zero then the $(window).height is the space from 240px till the bottom of the viewport. When scrolling down, the amount of pixel will grow on scroll, that makes no sense to me. If someone can explain what could have been the purpose of this would be fine. 'm very curious. The second part of the formula to calculate the parallax offsetPercent I still don't understand. In general the calculation of the parallax strength on scroll.
Update 3 / 4
Advised by #Edisoni, I walked the last few days by the videos of Travis Neilson and I have become a lot wiser on the basic functionalities of parallax. A must for everyone who wants to dig in parallax. I've used the new knowledge about parallax to get my above script work:
var root = this;
var win = $(window);
var offset = 0;
var elements = $('#daily .entry figure');
if (win.width() >= 768) {
win.scroll(function() {
// Get current scroll position
var scrollPos = win.scrollTop();
console.log(scrollPos);
elements.each(function(i) {
var elem = $(this);
var triggerElement = elem.offset().top;
var elemHeight = elem.height();
var animElem = elem.find('img');
if (scrollPos > triggerElement - (elemHeight / 2) && scrollPos < triggerElement + elemHeight + (elemHeight / 2)) {
// Do the magic
TweenMax.to(animElem, 0.1, {
yPercent: -(scrollPos - elemHeight / 2) / 100,
ease: Linear.easeNone
});
} else {
return false;
}
});
});
}
However, the script works only for a certain part of the elements. The problem is that it only works for the first two elements. I have a suspicion that the "error" is located in particularly after the AND && sign in the if statement, but can't get the error solved. http://codepen.io/anon/pen/XKwBAB
When the elements, that work on the trigger are animated, they will be jumping some pixels to the bottom, don't know how to fix this to.
The jumping to: 1.135%, after the trigger is fired. So it doesn't start at 0%. I already checked if I should add the CSS property translate to the CSS and set the type of number to %, but this doesn't work for me.
-webkit-transform: translateY(0%);
-moz-transform: translateY(0%);
-o-transform: translateY(0%);
transform: translateY(0%);
Should I use the TweenMax .fromTo() function instead of using the .to() function so I can set the start position as well or is my thought about this wrong and has a different cause?
Something like this:
TweenMax.fromTo(animElem, 0.1, {
yPercent: triggerElement,
z: 1
}, {
yPercent: -(scrollPos - elemHeight / 2) / 100,
ease: Linear.easeNone
});
Beside that I trying to recreate the effect of the site that I would like to use as inspiration source without the use of the scrollMagic plugin, but I don't really know how this works, with the use of two different objects that are animated.
At last, if someone thinks the code can be better formatted, don't hesitate, I would like to hear your suggestions
My actual questions are for update 2 and 3/4:
How to calculate the parallax y coordinates to get "the magic" done?
Am I right about update 2, that the zero point will be reset to offsetTop of each element?
Why my code only works for the first two elements and why they jumping some pixels down if the inline style of translate will be added to the animated element? See update 3/4 for all info.
Parallax is actually quite simple in principle. Just make the parallax element scroll slower than the rest of the content. That being said, a parallax implementation can be as simple as dividing the scroll distance by a factor:
var parallaxFactor = 3;
window.addEventListener("scroll", function(e){
el.style.top = (document.body.scrollTop / parallaxFactor) + "px";
// This is the magic. This positions the element's y-cord based off of the page scroll
}, false);
CODEPEN
This is an extremely simple demonstration of the parallax effect. Other more thorough implementations may handle values as percentages, or attempt to smooth the animation with TweenMax. This however, is the magic you're looking for.
Live long and prosper.
Update:
This example only works for elements at the top of a screen. If this were for a more general purpose, you would want to store the default y-position of the element, then something along the lines of defaultYCord + (document.body.scrollTop / parallaxFactor).
Update 2:
A very good visualization for parallax comes from Keith Clark who made a pure css parallax scroller: http://keithclark.co.uk/articles/pure-css-parallax-websites/demo3/. If you click debug in the upper left, it gives you a nice 3d-view of the magic.
This is not an answer how to build a parallax in JS. But it shows some basics, which will often be forgotten, if your too much into the code.
Basics:
Order your graphical objects in z-layers. As higher z is, as nearer
it is to observer in front of the screen.
As higher your object is in the z-axis as faster it should move on something that appears, f.e. your scrolling
Now you get a 3-D-Effect where objects nearer to you move faster to your actions as objects more far away.
Your question
How to calculate the parallax y coordinates to get "the magic" done?
The y-position depends on your z-index. If it is far away a.k.a the z-index is low, delta-y is small. If it is near too you, delta-y is big.
Please consider the z-index is not necessarily used as Style-property, it's more like it looks like.
I would add an attribute like data-z to every parallaxing layer.
function parallaxingY(el){
//el is a parallaxing element with attribute data-z
return $(el).data('z')*window.scrollTop;
}
the suggested CSS-Solution is nice and should be preferred. There the "magic" - the "z-index" - is made by the css-style "scale".
I am looking for help / a point in the right direction / or a solution for a flicker/jump, when scrolling on a looping/infinite website, which can be seen in this fiddle.
What seems to be causing the jump is:
"$(window).scrollTop(half_way - child_height);", and what could also be a Chrome windows scrollTop bug, but it is happening in all browsers at the moment.
If I remove "- child_height" there is no longer a flicker but the page no longer scrolls correctly, which can be seen in this fiddle.
Also, on the very first scroll the right hand column jumps up by three boxes - also because of 'half_way', which I can fix by giving it a "bottom: -600px;"
The full code:
http://jsfiddle.net/djsbaker/j3d8r/1/
var num_children = $('#up-left').children().length;
var child_height = $('#up-left').height() / num_children;
var half_way = num_children * child_height / 2;
$(window).scrollTop(half_way);
function crisscross() {
$('#up-left').css('bottom', '-' + window.scrollY + 'px');
$('#down-right').css('bottom', '-' + window.scrollY + 'px');
var firstLeft = $('#up-left').children().first();
var lastLeft = $('#up-left').children().last();
var lastRight = $('#down-right').children().last();
var firstRight = $('#down-right').children().first();
if (window.scrollY > half_way ) {
$(window).scrollTop(half_way - child_height);
lastRight.appendTo('#up-left');
firstLeft.prependTo('#down-right');
} else if (window.scrollY < half_way - child_height) {
$(window).scrollTop(half_way);
lastLeft.appendTo('#down-right');
firstRight.prependTo('#up-left');
}
}
$(window).scroll(crisscross);
Okay - here is a 'working' version - and by works I mean it less flickery than before. I thought it was flicker free, and it was when I was on battery power, but plugged into the mains and the CPU is fast enough to get flicker.
As I mentioned, to get rid of the flicker you need to clone the objects, manipulate them and then replace them into the DOM, rather than just manipulating the DOM directly.
I did this by getting the contents of <div id="content"> manipulating them and then replacing them into that <div>.
Also, it's a good idea to only find things in the DOM once, and from then on use a reference to that object rather than searching repeatedly. e.g.
var leftSide = $(clone).find('.up-left');
....
lastRight.appendTo(leftSide);
....
$(leftSide).css('bottom', '-' + window.scrollY + 'px');
rather than:
lastRight.appendTo('#up-left');
$('#up-left').css('bottom', '-' + window.scrollY + 'px');
Searching the DOM is relatively slow, and so storing references can improve performance/reduce flicker.
Storing the object also makes the code easier to understand (imho) as you can easily see that you're referencing the same thing, rather than possibly different things.
I still get flickering in chrome on windows with Danack solution. For this site I would control all the scrolling (you already scroll manually one of the sides), and give elements absolute positions.
Or if you insist on using the browser scrolling, may be use animations: animate the height of the last elements till 0px then use appendTo, and then animato from 0px to the normal height...
This might be a long shot, but I had the same flickering when working with infinitescroll,
and ended up using imagesLoaded.I ended up appending the additional images (now loaded) with a fade in, and that prevented them from flickering because of the fact they were loaded.
So maybe by using the imagesloaded - or a callback on the images, you can solve the flickering. It does decrease the speed though. I can image that if you want to scroll through everything as fast as possible, this might not be the solution. Good luck!
A solution would be to not use the native scrolling functionality but to simulate scrolling. This would be done by setting the overflow of your content to "hidden" in addition with capturing the "mousewheel" event on it and triggering some action when it is called. I started to try this out here (using MooTools instead of jQuery since I'm more fimilar with it). It's currently just "working" on the left side by altering the margin-top of the first element.
My next steps would be:
Check if the negative margin-top of the first element is bigger than the height of it and move it to the right side if so.
Same logic for the last box on the right side with a negative margin-bottom.
This has some downsides, though. Simulating scrolling doesn't feel as natural as the native scrolling functionality and clicking the mousewheel doesn't work. These might be solveable but it would require some more coding to get it to work smoothly. Anyway, in the end you would have a solution without any flickering and with no sticky scrollbar at the side (An idea for a replacement could be a small area on the side that triggers the scrolling on mouseover).
Sorry if this might seem trivial for me to ask but..
I have some images and I need them to enlarge when I hover my mouse over them. But.. I want for the enlarged image to stick next to the pointer as I move it across the image. I don't know what to call it. I'm pretty sure it's only done with javascript, just css won't work here.
Something like this http://www.dynamicdrive.com/style/csslibrary/item/css-popup-image-viewer/ , but you know, it has to move with the pointer in motion.
What's the most effective way to do this?
The previous answers may be exactly what you're looking for, and you may already have this solved. But I note that you didn't mention jquery anywhere in your post and all of those answers dealt with that. So for a pure JS solution...
I'll assume from the way the question was phrased that you already know how to pop the image up? This can be done by coding an absolutely positioned hidden img tag in the html or generated on the fly with JS. The former may be easier if you are a JS novice. In my examples I'll assume you did something similar to the following:
<img src="" id="bigImg" style="position:absolute; display:none; visibility:hidden;">
Then you need an onMouseOver function for your thumbnail. This function must do three things:
1) Load the actual image file into the hidden image
//I'll leave it up to you to get the right image in there.
document.getElementById('bigImg').src = xxxxxxxx;
2) Position the hidden image
//See below for what to put in place of the xxxx's here.
document.getElementById('bigImg').style.top = xxxxxxxx;
document.getElementById('bigImg').style.left = xxxxxxxx;
3) Make the hidden image appear
document.getElementById('bigImg').style.display = 'block';
document.getElementById('bigImg').style.visibility = 'visible';
Then you'll need to capture the onMouseMove event and update the now un-hidden image's position accordingly using the same code you would have used in (2) above to position the image. This would be something like the following:
//Get the mouse position on IE and standards compliant browsers.
if (!e) var e = window.event;
if (e.pageX || e.pageY) {
var curCursorX = e.pageX;
var curCursorY = e.pageY;
} else {
var curCursorX = e.clientX + document.body.scrollLeft;
var curCursorY = e.clientY + document.body.scrollTop;
}
document.getElementById('bigImg').style.top = curCursorY + 1;
document.getElementById('bigImg').style.left = curCursorX + 1;
And that should just about do it. Just add an onMouseOut event to hide the bigImg image again. You can change the "+1" in the last two lines to whatever you like to place the image correctly in relation to the cursor.
Note that all of the code above was for demonstration purposes only; I haven't tested any of it, but it should get you on the right track. You may want to expand upon this idea further by preLoading the larger images. You could also forgoe capturing mousemove events by using setTimeout to update the position every 20 ms or so, though I think that approach is more complicated and less desirable. I only mention it because some developers (including me when I started) have an aversion to JS event handling.
I did something similar to this with a custom ColdFusion tag I wrote that would generate a floating div users could click and drag around the screen. Same principle. If you need me to I can dig that out to answer any additional questions in more depth.
Good luck!
Liece's solution is close, but won't achieve the desired effect of the large image following the cursor.
Here's a solution in jQuery:
$(document).ready(function() {
$("img.small").hover (function () {
$("img.large").show();
}, function () {
$("img.large").hide();
});
$("img.small").mousemove(function(e) {
$("img.large").css("top",e.pageY + 5);
$("img.large").css("left",e.pageX + 5);
});
});
The HTML is:
<img class="small" src="fu.jpg">
<img class="large" src="bar.jpg">
CSS:
img { position: absolute; }
Try this links [jquery with auto positioning]
1.Simple
http://jquery.bassistance.de/tooltip/demo/
2.Good with forum
http://flowplayer.org/tools/tooltip/index.html
if I understood you correctly you want to position your big image relatively to the cursor. One solution in jquery (i'm not 100% sure of the code here but the logic is there):
$('.thumb').hover(function(e){
var relativeX = e.pageX - 100;
var relativeY = e.pageY - 100;
$(.image).css("top", relativeY);
$(.image).css("left", relativeX);
$(.image).show();
}, function(){
$(.image).hide();
})
Jquery is the easiest route. position absolute is key.
^ In addition to the above, here is a working JS Fiddle. Visit: jsfiddle.net/hdwZ8/1/
It has been roughly edited so it isnt using just overall IMG css tags, easy for anyone to use with this now.
I am using this script instead of a Lightbox in my Wordpress client site, a quick zoomed in image with mouse over is much nicer IMO. It is very easy to make efficient galleries especially with AdvancedCustomFields plug-in & in the WP PHP repeater loops!
I'm trying to counteract an adjustment to the height of an element which is above the scroll offset by calculating the difference in height and then updating the current scroll position to account for it.
The problem is that there's no way that I can prevent a very quick flickering artefact. Whether I adjust the element's height and then the scroll position, or vice versa, I can't seem to prevent a quick visual jump.
Does anyone know how this could be overcome? I want these to operations to happen at the same time with no rendering in-between but I'm not sure if it's possible.
// Setup
...
var myElement = ...
var oldHeight = ...
var scrollOffset = window.scrollY;
var newHeight = 100;
var diff = newHeight - oldHeight;
// Determine if we need to counteract new size
var adjustScroll = (absoluteOffset(myElement) < scrollOffset);
// Adjust size
myElement.style.height = newHeight+'px';
// Adjust scroll to counteract the new height
if (adjustScroll) window.scrollTo(0, scrollOffset+diff);
I'm working with WebKit, specifically on iOS.
for webkit you can use CSS transitions/animations to smooth this but it's still sound like you are going the wrong way to begin with. I am sure that whatever is it you are trying to do can be solved purely with CSS (maybe with some very minimal Javaqscript). Post an example of you HTML + CSS + JS.
You could use scrollIntoView with timers to simulate multiple threads.
Or you could do it inside a document fragment beforehand.
Sorry to be reviving an old post here, but i came across this looking for a solution to a similar problem to do with browser resizing.
Stackoverflow user James Kyle created this little jsfiddle using jQuery that attempts to maintain scroll position as best as possible when a page is resized
var html = $('html'),
H = html.outerHeight(true),
S = $(window).scrollTop(),
P = S/H;
$(window).scroll(function() {
S = $(window).scrollTop();
P = S/H;
});
$(window).resize(function() {
H = html.outerHeight(true);
$(window).scrollTop(P*H);
});
http://jsfiddle.net/JamesKyle/RmNap/
you could try using this same code and trigger a 'resize' event on the html when the image has loaded by using a jQuery library like imagesLoaded