I need to setup a section of a template I'm building out for a client that contains a parallax. This means I wont always know where that section will end up on the page. This creates a problem, the y-axis of my parallax is often off because the current parallax technique I'm using requires me to set the start and stop points.
I could possibly get around this if I could set the image on repeat and set the spacing between images to prevent it from showing in that window, that said, background-repeat: space; doesn't seem to be adjustable.
I'm currently using http://www.franckmaurin.com/blog/the-parallax-effect-with-jquery/ does anyone know of a work around to make parallax images look great when it's left to the clients hands or another javascript technique that would do this for me?
Thank you.
$.fn.parallax = function(options){
var $$ = $(this);
offset = $$.offset();
var defaults = {
'start': 100,
'stop': offset.top + $$.height() + 800,
'coeff': 0.95
};
var opts = $.extend(defaults, options);
console.log("Parallax Works!");
return this.each(function(){
$(window).bind('scroll', function() {
windowTop = $(window).scrollTop();
if((windowTop >= opts.start) && (windowTop <= opts.stop)) {
newCoord = windowTop * opts.coeff;
$$.css({
'background-position': '0 '+ newCoord + 'px'
});
}
});
});
};
// //parllax bind
if ($('.commit').length){
$('.commit').parallax({ 'start': 51 , 'stop':offset.top + $$.height(), 'coeff':-0.65 });
}
Not a lot to show as far as code goes, this script may just not be robust enough to do the job.
Without further ado, in similar cases, I recommend using an out of the box solution like Parallax.JS, which only needs to add an image input and is widely configurable.
But for parallax effects, there is no need for JavaScript as it is an inbuilt feature with CSS3, with background-attachment: fixed;. For an actual example check out this w3 article. In this very case it is really recommended to use this version simply for performance reasons, as CSS is enhanced by the GPU, while, if written wrong, JavaScript is not. On your provided link the effect feels slow and cloggy, and believe me, not my computer is the problem.
In general terms, always use CSS for animation and such effects, and with parallax, you only have to use this one command.
Related
First, thanks in advance for any help.
Second, I would like to mention that I have looked at different questions related to this topic as well as read documentation for both animate() and scrollLeft() on MDN I think my question is actually more based on syntax rather than function usage and that is why the other questions have not been as helpful to me.
Now, on to the issue. I am attempting to modify javascript code that I have previously written so that one function can react to the viewport of any user.
On the HTML side, I have a table with one <tr> and 3 <td>'s. The 3 <td>'s are filled with a picture and info and when the user clicks on buttons below, the table scrolls itself to the appropriate content. The buttons work fine. The problem is actually that the images are bigger than the viewport (on any device) and so on initial page load, the image needs to be scrolled by a distance proportional to both the viewport and the asset size (I load different assets based on viewport also). The formula for scroll distance, I discovered, is
0.5( assetWidth ) - 0.5( viewportWidth ).
So, here is the JS I have come up with (this is all inside a jQuery(document).ready(function($){
var scrollDistance;
if ($('#interactive-row:visible').length == 0) {
//Viewport > 801px
var assetWidth = 1920;
console.log("bouta set scrolDistance");
scrollDistance = ( 0.5 * assetWidth ) - ( 0.5 * $( window ).width() );
} else {
//Viewport < 800px
var assetWidth = 1428;
scrollDistance = ( 0.5 * assetWidth ) - ( 0.5 * $( window ).width() );
}
//scroll to zero so that whne user goes "back" slider position is reset (w/o variable lastClick gets messed up)
$('.table-container').animate({
scrollLeft: 0
}, "slow");
console.log( "Scroll Distance is " + scrollDistance + " calculation is about to begin." );
//move slider to middle of SSI screen
$('.table-container').animate({
scrollLeft: += scrollDistance.valueOf()
}, "slow");
The problem (I believe) is on the second-to-last line at which point my intentions are to have the browser scroll to whatever number is inside scrollDistance.
Note: here is what firefox and chrome say: "SyntaxError: expected expression, got '+='[Learn More]"
Also, I have already tried using scrollDistance with out adding the .valueOf(). I put that on recently in case there was some sort of type issue in javascript that I wasn't aware of.
Feel free to take a look at this graphic to better understand what I am trying to do. Graphic of what browser should display
Thanks in advance for the help, I am new to Javascript and anything at all that you all can tell me (even just general pointers about how I write my code) is much appreciated!
Edit: It just occurred to me that it may also worth noting that my console.log() is not working at all but I could care less about that if the scroll starts working :D
I'd like to achieve effect of the fixed container that changes in the last phase of scrolling. I'm not sure how to call it professionally, so sorry for lack of appropriate words.
Actually, how it should be called? :)
I mean sth like that: https://media.giphy.com/media/26gsscmNiRJW039XG/source.gif
The effect can be seen live on the UX London page http://2016.uxlondon.com/
I'm not superexperienced with JS, but if you could share any tutorials or examples with similar effects it would be awesome.
I believe you might use this example for that purpose:
https://codepen.io/Funsella/pen/yLfAG
js: $( window ).ready(function() {
var wHeight = $(window).height();
$('.slide')
.height(wHeight)
.scrollie({
scrollOffset : -50,
scrollingInView : function(elem) {
var bgColor = elem.data('background');
$('body').css('background-color', bgColor);
}
});
});
To avoid confusion and before you read on, this is NOT "how many pixels down" but at, for example, <section id="smaller"> then it would add a class. I'm new to javascript so please take that with a grain of salt. Thanks.
I'm trying to change the header by adding a new attribute class to the header file. Following code works ok on desktop when your width never changes but what if your on a phone and your design is responsive? Yes, this is exactly why I need your help. I tried so many thing already and don't know how to get this setup like I want. I am new to web dev and this is one of my first few websites.
My code right now:
function init() {
window.addEventListener('scroll', function (e) {
var distanceY = window.pageYOffset || document.documentElement.scrollTop, header = document.querySelector("header");
if (distanceY > 606) {
header.setAttribute("class", "smaller");
} else {
header.removeAttribute("class");
}
});
}
window.onload = init();
Couple of things I need to clear up, and/or if you're a little confused:
the header is the actual <header> not a div with a header class or id.
like I said, this does work right now but is only useful for a fixed width for every screen size
I'm including this code on a js file which is linked just before the ending of the <body> tag.
"606" being the length down the page in pixels when the change happens
Is there a way to add an attribute to the header when you reach a certain place on the web page? If anyway could give me some guidance, that would be great. Thanks a bunch for reading this and enjoy the rest of your day. :)
Use element.getBoundingClientRect() to retrieve screen position information of your object. This will give you an object containing bottom, height, left, etc., for your task you might want to use top and height. In combination with window.innerHeight you can code what you want.
window.addEventListener('scroll', function() {
var r = header.getBoundingClientRect();
if (r.top < 300)
header.setAttribute("class", "smaller");
else
header.removeAttribute("class");
});
However, there are probably better ways to do this, have a look at "css media queries", they offer almost anything you might require to make your pages responsive.
I have figured out a way to do it with .position();. Here's my explanation:
#sub-services is the element I want to get the position of.
el is the position of the #sub-services.
And smaller is a class added to the <header>.
Here's the full code which I'm using in my site:
var el = $( "#sub-services" );
var position = el.position();
function init() {
window.addEventListener('scroll', function (e) {
var distanceY = window.pageYOffset || document.documentElement.scrollTop, header = document.querySelector("header");
if (distanceY > position.top) {
header.setAttribute("class", "smaller");
} else {
header.removeAttribute("class");
}
});
}
window.onload = init();
It is much easier to do it with jquery. Thanks to #caramba for pointing me in the right direction.
i'm pretty sure a few of you guys know the website medium.com articles page.
For example, here: Click
There is a very "easy" effect on this page when you scroll down – opacity and transform changes. Not a big deal at first sight. I've implemented the same effect probably more then 10 times on websites already.
But if you take a closer look at it, you can see how absolutely perfect smooth this is. Seems like the text is perfectly gliding above the surface. (Im checking it on the latest Chrome)
I was keen if this is just imagination, and quickly built up the same thing to check this. So i came up with this code:
var windowTop;
var limit = 420;
function parallax(){
parallaxElem.css({
"opacity": (1 - (windowTop / limit)),
"-webkit-transform":"translate3d(0," + (100 * (windowTop / limit)) + "px,0)",
"-ms-transform":"translate3d(0," + (100 * (windowTop / limit)) + "px,0)",
"transform":"translate3d(0," + (100 * (windowTop / limit)) + "px,0)"
});
}
$(window).on('scroll', function(){
windowTop = $(window).scrollTop();
parallax();
});
And it's by far not as smooth as the code on the Medium website.
Anyone any idea, what they are doing to get this super smooth scroll transform effect? I just can't find it out – their code is too complex/too compressed for me, to get any information out of it.
Thank's a lot for any answer in advance!
Regards
Mark
The biggest improvement is to go from this:
$(window).on('scroll', function(){
windowTop = $(window).scrollTop();
parallax();
});
to:
$(window).on('scroll', function(){
window.requestAnimationFrame(parallax);
});
Store windowTop inside of the parallax function. There's no point in making that an out of scope variable.
Additionally, although you don't have it in your sample code "parallaxElem" should be an out of scope variable, because you don't want to do a DOM search for the element on every scroll.
I have a horizontally scrolling website, and I have a block that I want to stay in frame at all times as the user scrolls right. It looks perfectly smooth in webkit browsers, but is crazy jagged in Firefox and I don't really care about IEs.
function fixMyId(){
$('#myId').css({'margin-left': 150 + $(window).scrollLeft()});
}
function fixMyIdAlt(){
$('#myId').stop().animate({'margin-left': 150 + $(window).scrollLeft()}, 300);
}
And then I have it triggered on window scroll.
What would be a best way to average out the scrolling, so that maybe every so many seconds or pixels of scrolling it fires the function, or upon stopping the scrolling it animates the block into place? I tried playing with delay() but that doesn't do anything. And this one just looks stupid (plus I have no idea what the overhead of this kind of crunching is):
function fixMyIdStupid(){
window.scrollCounter++;
if(window.scrollCounter % 20 == 0) $('#myId').stop().animate({'margin-left': 150 + $(window).scrollLeft()}, 300);
}
So what do I do? setTimeout and setInterval may be required, but those always make my head hurt.
EDIT: Here's a jsfiddle of it in action: http://jsfiddle.net/xsxSq/
The #f0f square is the #myId.
I tried to do such things as well, problem is that the scroll event isn't fired as much as you want. A nice workaround was subscribing the calculation function to the mousemove event, so it triggers A LOT. But on the other hand, I came up with another solution.
Why not turn things around and ask yourself:
Lets make it a position:fixed object and calculate what happens on resize. Because you actually are trying to create a position-x:fixed; and a position-y:absolute;
I actually did the following for the opposite kind of thing. A block that has to be exactly in the middle of the x-document, but in the y it was fixed.
$(document).ready(function ()
{
replaceFixed();
$(window).resize(replaceFixed);
$('#content').ajaxSuccess(replaceFixed);
$(window).scroll(replaceFixed);
function replaceFixed()
{
var jEl = $('#centeredFixedContainer');
var winW = $(window).width();
var docW = $(document).width();
var scrL = $(window).scrollLeft();
var divW = jEl.width();
var result = 0;
// window bigger than the element
if(winW > divW)
{
result = -scrL + ((docW-winW)/2);
}
else
{
result = $('#mainContainer').offset().left - scrL;
}
jEl.css('left',result);
}
});
Copying this code will not give you the solution, but will indicate another way to look at your problem.