I created a parallax effect, as it was described here:
Is there a way to make parallax work within a DIV
This method works pretty well, but I have a problem with it. My page is basically composed of alternating DIVs. White DIVs with text and DIVs with a picture in it, which moves with the parallax effect. This works pretty well, unless, that I have to manually adjust the position of each picture DIV. Here is the code from the header:
<script type="text/javascript">
$(window).scroll(function () {
parallax();
});
function parallax() {
var ev = {
scrollTop: document.body.scrollTop || document.documentElement.scrollTop
};
ev.ratioScrolled = ev.scrollTop / (document.body.scrollHeight - document.documentElement.clientHeight);
render(ev);
}
function render(ev) {
var t = ev.scrollTop;
var y = Math.round(t * 2/3) - 100;
$('#ff-section01').css('background-position', 'center ' + y + 'px');
$('#ff-section03').css('background-position', 'center ' + (y - 1000) + 'px');
$('#ff-section05').css('background-position', 'center ' + (y - 1700) + 'px');
$('#ff-section07').css('background-position', 'center ' + (y - 2750) + 'px');
}
</script>
As you can see, each section got another vertical position in the background-position value at the bottom. 0, 1000, 1700, 2750. This works well so far, but as soon as the intermediate Text DIVs change in height, this method doesn't work, as the value is always calculated from the top of the page. The HTML of one section looks like this:
<div class="ff-section03" id="ff-section03"></div>
So very simple, and combined with the CSS:
.ff-section03 {
width: 100%; height: 550px;
position: relative;
background: url('system/urbansolutions.jpg') center -300px no-repeat;
}
Also very simple. What can I do, that the calculations are not dependent of the page height? I basically don't want to subtract a superficial number from the background-position, so that the parallax effect works, not dependent of the location on the website.
Thanks a lot!
Sebastian
I'm using a precoded Parallax JQuery as part of a Wordpress theme called Parallax by Studiopress. It works fairly well, but I end up missing the top half of the image when scrolling and I'd like the user to be able to see that as well when they scroll down. Currently, the background-position starts at "50% 0px" and the px goes into negative figures when you scroll the page. I figure if I set it to start at 200 or 300px the majority of the image can be viewed. However, I can't set the CSS as that gets overridden by JQuery.
I'm fairly new to JQuery so I'm wondering if there's any pointers or method that can be given to help me?
This is the code :
jQuery(function ($) {
// Enable parallax and fade effects on homepage sections
$(window).scroll(function () {
scrolltop = $(window).scrollTop()
scrollwindow = scrolltop + $(window).height();
$(".home-section-2").css("backgroundPosition", "50% " + -(scrolltop / 6) + "px");
if ($(".home-section-4").length) {
sectionthreeoffset = $(".home-section-4").offset().top;
if (scrollwindow > sectionthreeoffset) {
// Enable parallax effect
backgroundscroll = scrollwindow - sectionthreeoffset;
$(".home-section-4").css("backgroundPosition", "50% " + -(backgroundscroll / 6) + "px");
}
}
})
});
For the top image - change scrolltop to scrolltop = $(window).scrollTop() + -1000 The larger the number makes the starting px larger as well.
Every other image requires a duplicate of scrolltop called scrolltop2 which does not contain the number. This is referred to in scrollwindow.
scrolltop2 = $(window).scrollTop()
scrollwindow = scrolltop2 + $(window).height();
Then add the number to backgroundscroll
eg: backgroundscroll = scrollwindow - sectionthreeoffset + -1500;
I wanted to achieve an effect like this http://www.offset.com/
as you can see when it scrolls it slowly covering the carousel rather than scrolling with it.
I've tried using background fixed but the problem is the elements inside it will not stay in its position
Maybe there is a good technique in achieving this, Thanks
this is called parallax scrolling here is an example of how to do this using Jquery :
Live Demo
// Y axis scroll speed
var velocity = 0.5;
function update(){
var pos = $(window).scrollTop();
$('.container').each(function() {
var $element = $(this);
// subtract some from the height b/c of the padding
var height = $element.height()-18;
$(this).css('backgroundPosition', '50% ' + Math.round((height - pos) * velocity) + 'px');
});
};
$(window).bind('scroll', update);
an other example it might help DEMO
So I am trying to show a tooltip like box as I scroll my webpage and I would like it to follow the scrollbar along the right side of the page.
I looked around and found something to attempt to accomplish that as shown below:
function returnPercentHeight(){
var a = document.getElementById('rightPanel').scrollTop;
var b = document.getElementById('rightPanel').scrollHeight - document.getElementById('rightPanel').clientHeight;
return ((a/b) * 100);
}
I then append a % to the end and set the top margin of the tooltip to that returned value. This works pretty well (sort of) I have to adjust the return((a/b) * x) part (x) to make it follow the scrollbar based on the size of the browser window. Is there a better way to accomplish what I am trying to do? (NOTE: I can only use javascript, no JQuery please.)
EDIT:
Only the div given an ID of 'RightPanel' is scrolling, I am not using the scrollbar on the browser, but a scrollbar on an inner div.
There are three ways to do so:
First:
is to use the fixed position as following;
Position: Fixed;
Second:
With jQuery;
$(function(){
$(window).on('scroll', function() {
var scrollPOS = $(document).scrollTop();
$('.scroll').css({
top: scrollPOS
});
}).scroll();
});
Third:
Same as the previous, only animated;
$(window).on('scroll', function() {
$("#div").stop().animate({
"marginTop": ($(window).scrollTop()) + "px",
"marginLeft":($(window).scrollLeft()) + "px"}, "slow" );
});
Although IE doesn't support, this is the coolest I've seen:
// get
var x = window.scrollX,
y = window.scrollY;
// set
window.scrollTo(1, 2);
I am trying to obtain the image effect that 99designs is obtaining when hovering a mouse over a design.. [99designs.ca] Logo design contest: Runningbug Needs Logo 220626
I am currently obtaining the position of the mouse on mousemove, then using that to move my popover <img>, and everything works fine, but it is very laggy.. and presumably its from so many calls being made.
To get the position of the mouse:
jQuery(document).ready(function(){
//$("#special").click(function(e){
$(".imgWrap").mousemove(function(e){
//$('#status2').html(e.pageX +', '+ e.pageY);
//alert(e.pageX + ', ' + e.pageY);
mouseX = e.pageX;
mouseY = e.pageY;
});
})
I'm not sure of another way I can do this.. any ideas?
On the full course of events is the following:
User mouses over an img tag.
I get the position of the mouse as per above.
The <img> tag also calls a js function which changes the position of an img tag to the position of the mouse.
Actually, you can check it here: pokemonsite
update: I see there is a bounty placed (thanks !). I'm a little busy at the moment and can't check all the other answers, but I'll make sure to check them asap
There are several ways to improve performance when using mousemove events.
Use backface-visibility: hidden on popover element to force hardware acceleration. Same thing can be achived with transform: translate3d(0,0,0) but that makes difficult to use CSS transform function (see point #2).
Use CSS transform function for absolute positioning to avoid repaints but keep popover element absolute or fixed positioned.
When setting inline CSS via JS use requestAnimationFrame to avoid unnecesary layout trashing.
(maybe, optionally) hide cursor when hovering and use popover element as position indicator.
Move everything you can from JS to CSS ie. :hover state can be used to toggle display of popover element.
I made demo example combining all things listed. There is still some latency between cursor position and popover image and none of example links in original question work so I can't compare against it but I hope someone finds this useful.
DEMO
<div id="imgHolder" class="imgHolder">
<img src="//placehold.it/200x200" alt="" />
</div>
<div id="bigImgHolder" class="imgHover">
<img src="//placehold.it/500x500" alt="" />
</div>
.imgHover {
display: none;
backface-visibility: hidden;
position: fixed;
top: 0; left: 0;
pointer-events: none;
}
.imgHolder:hover ~ .imgHover { display: block; }
// uncomment if it makes sense
//.imgHolder:hover { cursor: none; }
var posX, posY;
$('#imgHolder').mousemove(HoverImg);
function HoverImg(e) {
posX = e.pageX;
posY = e.pageY;
window.requestAnimationFrame(showBigImg);
}
function showBigImg() {
$('#bigImgHolder').css({'-webkit-transform': 'translateX(' + posX + 'px) translateY(' + posY + 'px)', 'transform': 'translateX(' + posX + 'px) translateY(' + posY + 'px)' });
}
references:
http://davidwalsh.name/translate3d
http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/
https://css-tricks.com/using-requestanimationframe/
Try this:
jQuery(document).ready(function(){
$(".imgWrap").mousemove(function(e){
e.stopPropagation();
mouseX = e.pageX;
mouseY = e.pageY;
});
})
Use e.offsetX and e.offsetY or (recommended) e.clientX and e.clientY instead of pageX and pageY. Maybe this will be a better solution. Note: offsetx and offsety do not work in Firefox as far as I know.
If the absolute (x, y) position is not so important (meaning: some pixel-values can be omitted without destroying your logic), you could try to skip some frames of your mousemove-event.
var globalSkipCounter = 0;
var globalSkipRate = 5;
$(".imgWrap").mousemove(function(e){
if(globalSkipCounter >= globalSkipRate){
var mouseX = e.pageX;
var mouseY = e.pageY;
do_stuff(mouseX, mouseY);
globalSkipCounter = 0;
}
else{
globalSkipCounter+=1;
}
});
This way, you omit redrawing your image on every mousemove-event, instead your draw-routines (do_stuff) are only invoked, once every 5 events.
Cache the position and wrap the update in an if(oldpos !== newpos) type check (remembering to update oldpos inside it).
Use requestAnimationFrame to handle the update - if you have a normal function and pass that as the callback then it will only get called once per frame (ie, don't use an anonymous function).
Finally make use of transform:translate(x,y) to set the position and make better use of the GPU etc. Related to this, there's no harm in making use of the css will-change keyword if you want to use top/left instead.
try a maximum event per second based approach:
jQuery(document).ready(function(){
var now, then, delta, interval = 1000/60; //maximum 60 eps, you can change
//$("#special").click(function(e){
$(".imgWrap").mousemove(function(e){
now = Date.now();
delta = now - then;
if (delta > interval) {
then = now - delta % interval; //subtract extra waited time
//$('#status2').html(e.pageX +', '+ e.pageY);
//alert(e.pageX + ', ' + e.pageY);
mouseX = e.pageX;
mouseY = e.pageY;
// do your thing
}
});
})
EDIT: didn't know then is a reserved word in javascript, you can rename it.
I have a sortable listview in angular, but dragging items with the mouse in chrome was lagging a lot. I tried disabling all chrome extensions and now the lag is totally gone.
It turned out that TamperMonkey was causing it.
Instead of using "left" or "right" property of CSS rather try to use
"transform" I was trying to do the same thing as asked in question, and using "transform" worked for me like a charm.
for example:
transform: translate(30px);
this will move the element, 30px to the right.
by using transform we can move elements to left, right, top and bottom according to the need.