jQuery animate height expand outward instead of down - javascript

I am building my sister a website at SarahNWatson.com/new. I have it set up as a big photo/video album. For actual content pages, such as her Bio, I have it so that it opens a modal window.
Right now I have the modal window so that the height starts at 0px and then animates open, however this gives me a slide down effect. I want it to open outwards as if something were in the box pushing in both directions. How can I accomplish this?
Here's the code:
function createModal(filler) {
var $this = $(this);
var $body = $('body');
var winHeight = $(window).height();
var winWidth = $(window).width();
$body.prepend('<div id="blackout">');
$("#blackout").css({ height:winHeight }).fadeIn(1800);
$body.prepend('<div id="modal_window">');
$("#modal_window").html(filler).fadeIn(2000);
var modalHeight = $("#modal_window").height();
var modalWidth = $("#modal_window").width();
var offsetH = winHeight/2 - modalHeight;
var offsetW = winWidth/2 - modalWidth/2;
$("#modal_window").css({ top:offsetH, left:offsetW, height:'0px' }).animate({ height:modalHeight });
}
And the CSS:
#modal_window {
position: absolute;
z-index: 1000;
width: 600px;
background: rgba(0,0,0,.8);
padding: 15px;
}

Start with offsetH = winHeight/2 and offsetW = winWidth/2. Then, animate all of the top, left, and height CSS properties. The final top will be (winHeight - modalHeight)/2 and final left will be (winWidth - modalWidth)/2.
function createModal(filler) {
var $this = $(this);
var $body = $('body');
var winHeight = $(window).height();
var winWidth = $(window).width();
$body.prepend('<div id="blackout">');
$("#blackout").css({ height:winHeight }).fadeIn(1800);
$body.prepend('<div id="modal_window">');
$("#modal_window").html(filler).fadeIn(2000);
var modalHeight = $("#modal_window").height();
var modalWidth = $("#modal_window").width();
var offsetH1 = winHeight/2;
var offsetH2 = (winHeight-modalHeight)/2;
var offsetW = (winWidth-modalWidth)/2;
$("#modal_window")
.css({ top:offsetH1, left:offsetW, height:'0px' })
.animate({ top:offsetH2, height:modalHeight });
}
UPDATE: Code sample updated to only animate vertically.
Essentially, you're moving the box up as it grows taller. So instead of sliding down it gives the appearance of expanding from the middle.

You could give it a margin-top of half the ultimate height (modalHeight) and add marginTop:"toggle" to your animation:
.animate({ height:modalHeight, marginTop:"toggle"})

Try using the CSS setting Bottom instead of Top. You should then use the bottom of the element to position it thus having it animte upwards instead of downwards.
.animate() always animate away from the anchor.

Related

Progressively adding opacity while scrolling

I am struggling with figuring out how to modify some existing code I have to replicate a feature I saw on a site. If you go to this site: , when you scroll down you will see the image gains opacity. My fiddle somewhat does this, but I cannot figure out how to apply a darker opacity and have the opacity progressively be added rather than all at once.
I know the level of opacity is being changed via the javascript, I am just not aware how to modify it to get the result I am after.
var scrollPosition = $(this).scrollTop();
var docHeight = $(document).height();
var diff = docHeight - scrollPosition;
console.log(scrollPosition);
$('#demolition1').css({'opacity':diff/docHeight});
Fiddle
<div id="home-main-img">
<img src="http:optimumwebdesigns.com/images/demolition1.jpg" alt="Demolition and Wrecking" id="demolition1">
</div>
<div class="height">
</div>
#home-main-img img{
width: 100%;
height: auto;
margin: 0;
display: block;
}
#home-main-img {
background: #000;
}
.height {
height:500px;
}
$(document).scroll(function(e){
var scrollPosition = $(this).scrollTop();
var docHeight = $(document).height();
var diff = docHeight - scrollPosition;
console.log(scrollPosition);
$('#demolition1').css({'opacity':diff/docHeight});
});
I think your mistake is setting diff against the doc height rather than the height of the item you want to fade out.
Your JS should be something like:
var $item = $('#demolition1');
$(document).scroll(function(e) {
var $this = $(this),
scrollPosition = $this.scrollTop(),
itemHeight = $item.height(),
diff = itemHeight - scrollPosition;
console.log(scrollPosition);
$item.css({'opacity': (diff/itemHeight) });
});
Here's a working JS Fiddle: https://jsfiddle.net/s6ta6bdc/
You can use image height, instead of document, to get the correct percentage of opacity
$(document).scroll(function(e){
var scrollPosition = $(this).scrollTop();
var imgHeight = $('#demolition1').height();
var diff = imgHeight - scrollPosition;
$('#demolition1').css({'opacity':diff/imgHeight});
});
try fiddle updated

Stick last scrolled header to the top of the viewport?

jsfiddle: http://jsfiddle.net/R3G2K/1/
I have multiple divs with content, and each one has a header. I'd like to make the last header that left the viewport to be "sticky" or fixed to the top of the viewport.
I've seen a few different approaches to this, but none of them seem to work for multiple headers.
$('.content').scroll(function(){
console.log('scrolling')
$('.itemheader').each(function(){
var top = $(this).offset().top;
console.log(top);
if(top<25){
$(this).addClass('stick');
}else{
$(this).removeClass('stick');
}
})
});
I think there might be a conflict since each header has the same class name, and no unique identifier, so my above attempt isn't working out right.
http://jqueryfordesigners.com/iphone-like-sliding-headers/
This was exactly what I was looking for:
http://jqueryfordesigners.com/demo/header-slide.html
$(document).ready(function () {
// 1. grab a bunch of variables
var $container = $('#box');
var $headers = $container.find('h2');
var zIndex = 2;
var containerTop = $container.offset().top + parseInt($container.css('marginTop')) + parseInt($container.css('borderTopWidth'));
var $fakeHeader = $headers.filter(':first').clone();
// 2. absolute position on the h2, and fix the z-index so they increase
$headers.each(function () {
// set position absolute, etc
var $header = $(this), height = $header.outerHeight(), width = $header.outerWidth();
zIndex += 2;
$header.css({
position: 'absolute',
width: $header.width(),
zIndex: zIndex
});
// create the white space
var $spacer = $header.after('<div />').next();
$spacer.css({
height: height,
width: width
});
});
// 3. bind a scroll event and change the text of the take heading
$container.scroll(function () {
$headers.each(function () {
var $header = $(this);
var top = $header.offset().top;
if (top < containerTop) {
$fakeHeader.text($header.text());
$fakeHeader.css('zIndex', parseInt($header.css('zIndex'))+1);
}
});
});
// 4. initialisation
$container.wrap('<div class="box" />');
$fakeHeader.css({ zIndex: 1, position: 'absolute', width: $headers.filter(':first').width() });
$container.before($fakeHeader.text($headers.filter(':first').text()));
});

jQuery addClass based on how far scrolled

I have written some jquery to calculate the height of 4 elements by css class and get their height, then compare the height to how far the page has been scrolled. If the page has been scrolled to or past each element then a css class is added which animates the element.
The problem that I am having is that the jquery is adding the classes to all of the elements as soon as the page is scrolled to the first element, instead of adding the class to each as it is scrolled to.
What is wrong with my jquery that it is doing this?
Here is the jsfiddle http://jsfiddle.net/94kP6/7/
This is the jquery part of the code
// element animation scroll detection
(function ($, document, undefined) {
var animation1 = $('.animation1').height();
var animation2 = $('.animation2').height();
var animation3 = $('.animation3').height();
var animation4 = $('.animation4').height();
$(window).scroll(function() {
var winTop = $(window).scrollTop();
if(winTop >= (animation1)){
$('.animation1').addClass("animate-from-left");
}
if(winTop >= (animation2)){
$('.animation2').addClass("animate-from-right");
}
if(winTop >= (animation3)){
$('.animation3').addClass("animate-from-left");
}
if(winTop >= (animation4)){
$('.animation4').addClass("animate-from-right");
}
});
})(jQuery, document);
var animation1 = $('.animation1').height();
var animation2 = $('.animation2').height();
var animation3 = $('.animation3').height();
var animation4 = $('.animation4').height();
needs to be
var animation1 = $('.animation1').offset().top;
var animation2 = $('.animation2').offset().top;
var animation3 = $('.animation3').offset().top;
var animation4 = $('.animation4').offset().top;
or some variant for personal preference, like this:
var animation1 = $('.animation1').position().top - $('.animation1').height();
var animation2 = $('.animation2').position().top - $('.animation2').height();
var animation3 = $('.animation3').position().top - $('.animation3').height();
var animation4 = $('.animation4').position().top - $('.animation4').height();
Here's a fiddle to show you need to use .offset().top instead of .height
http://jsfiddle.net/94kP6/10/
When you use height, you are asking the scroll to wait until the height of the object instead of waiting for the top position of the object
Just change your heights to offsets
UPDATE
http://jsfiddle.net/94kP6/14/
This makes it so the animation can be seen more in the middle of the screen. Just subtract a specified height (in this case, the height of the object) from the offset and it will animate at a higher scrollTop.
You can also do the same thing, only backwards by ADDING a specified amount to the var winTop = $(window).scrollTop(); line, line this: var winTop = $(window).scrollTop() + 250;

Why does an element start its css3 transition/transform from the top left of the window?

This is a bit annoying: i have a div which starts its transition from the top left of the window even when positioned anywhere else on the document. I've tried usign -webkit-transform-origin with no success, maybe i've used it wrong.
Could anybody help me? :)
Here's the code... all of it, but i've commented on the relevant parts - which are at the bottom, mainly.
Here's a live version of the code.
<style>
#pool{
width:100%;
}
.clickable{
<!-- class of the element being transitioned -->
display:inline;
margin-right: 5px;
-webkit-transition: all 500ms ease;
position: absolute;
}
.profile_image{
border: solid 1px black;
-webkit-transition: all 500ms ease;
position:relative;
}
</style>
<section id="pool"></section>
<script>
var Cache = {};
Cache.hasItem = function(item_key){
if(!localStorage.getItem(item_key)){
return false;
}else{
return true;
}
}
Cache.storeItem = function(key, value){
localStorage.setItem(key, value);
}
Cache.fetch = function(key){
return jQuery.parseJSON(localStorage.getItem(key));
}
Cache.clear = function(key){
localStorage.removeItem(key);
}
var Twitter = {};
Twitter.url = "http://api.twitter.com/1/statuses/public_timeline.json?callback=?";
Twitter.getFeed = function(){
console.log("Fetching...");
$.getJSON(Twitter.url, function(json){
Cache.storeItem('feed',JSON.stringify(json));
})
.complete(function(){
//to be implemented
console.log("Completed");
})
}
if(!Cache.hasItem('feed')){
Twitter.getFeed();
}
var feed = Cache.fetch('feed');
for(var i in feed){
var entry = feed[i];
var element = '<div id="'+i+'" class="clickable"><img class="profile_image" src="'+entry.user.profile_image_url+'"/></div>';
$("#pool").append(element);
}
</script>
<script>
$(".profile_image").click(function(e){
var target = $(e.target);
var parent = target.parent();
var windowWidth = $(window).width();
var windowHeight = $(window).height();
var newWidth = 500;
var newHeight = 100;
var newX = (windowWidth-newWidth)/2;
var newY = (windowHeight-newHeight)/3;
/************HERE'S THE PROBLEM*******/
parent.css('background-color','red');
parent.css('display','inline');
parent.css('position','fixed'); // tried absolute and inherit as well
parent.css('z-index','3');
parent.width(newWidth).height(newHeight).offset({top:newY, left:newX});
})
</script>
Results:
With help from jfriend00 i managed to fix it. Here's the code:
<style>
#pool{
width:100%;
display: inline;
}
.clickable{
display: inline-block;
margin-right: 5px;
position: scroll;
}
.profile_image{
border: solid 1px black;
}
</style>
And the Javascript:
<script>
$(".profile_image").click(function(e){
var target = $(e.target);
var parent = target.parent();
targetOffset = target.offset();
parentOffset = parent.offset();
target.css('top',targetOffset.top-5);
target.css('left',targetOffset.left-5);
parent.css('top',parentOffset.top);
parent.css('left',parentOffset.left);
var windowWidth = $(window).width();
var windowHeight = $(window).height();
var newWidth = 500;
var newHeight = 100;
var newX = (windowWidth-newWidth)/2;
var newY = (windowHeight-newHeight)/3;
parent.css('-webkit-transition', 'all 500ms ease');
parent.css('background-color','red');
parent.css('position','absolute');
parent.css('z-index','3');
parent.width(newWidth).height(newHeight).offset({top:newY, left:newX});
})
</script>
It looks to me like you change the object's position from relative to fixed upon the click (along with a few other style changes). When you change it to fixed, the object is no longer positioned in the flow of the page and it goes to it's left and top position on the page which it does not look like you've initialized - thus they are set to (0,0) so that's where the object jumps to when you change it's position to fixed (top/left of the page).
If you want them to transition from where they were, you will have to calculate their original position on the page and set top and left to those values in the same code where you set the position to fixed.
I would assume that jQuery has a function to calculate the object's absolute position in the page for you so you can use that (YUI has such a function so I assume jQuery probably does too). Since you're using "fixed", you may have to correct that for scroll position or use "absolute" instead of "fixed". One challenge here is you need to change the position and top/left without them being subject to a CSS transition because you want those attributes to change immediately. Then, you enable the transitions and set the final position.

How to make a div scroll when I scroll after certain point?

I would like to create a div, that is situated beneath a block of content but that once the page has been scrolled enough to contact its top boundary, becomes fixed in place and scrolls with the page. I know I've seen at least one example of this online but I cannot remember it for the life of me.
Any thoughts?
[Working demo]
var el = $("#sticky");
var win = $(window);
var width = el.width();
var height = el.height();
var win_height = $(window).height();
window.onscroll = function() {
var offset = el.offset().top + height - win_height;
if ( win.scrollTop() > offset ) {
window.onscroll = function() {
el.css({
width: width,
position: "absolute",
top: win.scrollTop() + win_height - height
});
};
}
};
If you don't need to support IE based browsers you can use:
position: "fixed"
bottom: 0

Categories