jquery - dynamically set a height or width when animated - javascript

I was curious on how to set a height or width dynamically based on when a div is animated.
JQUERY
$(document).ready(function() {
var div1dimensions = 50 / 180 +'px';
$("#div1").animate({
width: divdimensions,
height: "100px",
opacity: 1,
}, 1500 );
});
Can I not just create a variable and place it where the width or height is? Or is that only for CSS values such as 100px?
Thank you.

Something that is important is that when using the object form of the .css() method, any numerical values placed there are inherently assumed to be pixel values:
$(document).ready(function() {
var div1dimensions = (50 / 180);
$("#div1").animate({
width: div1dimensions,
height: 100,
opacity: 1,
}, 1500 );
});
Notice the lack of quotation marks. If you go about it this way, you can use a variable very easily:
$(document).ready(function() {
var div1dimensions = (50 / 180),
divHeight = div1dimensions * 1.5;
$("#div1").animate({
width: divdimensions,
height: divHeight,
opacity: 1,
}, 1500 );
});
Or any other variable calculation you wish, this is just an example. Additionally, as-of jQuery 1.4 you can pass in a function for that calculation. The example used in the jQuery .css() documentation modified to reflect your example:
$(document).ready(function() {
var div1dimensions = (50 / 180);
$("#div1").animate({
width: div1dimensions,
height: function(i){
return i * 50;
},
opacity: 1,
}, 1500 );
});
That one can get tricky pretty quickly, and is really only helpful in very specific scenarios, but is handy when needed.

Related

Animate progress bars upwards

I am looking to animate this progress bars, but I'm having a different behavior using jQuery animate() method. I want to animate the progress bars one by one with a 0.1s delay. I will need help with choosing the right animation, because now my animation is behaving downwards. I'd like to do it in the simplest way possible.
Here is what I have so far:
$('.vertical-bars .progress-fill span').each(function() {
var percent = $(this).html();
var pTop = 100 - (percent.slice(0, percent.length - 1)) + "%";
$(this).parent().css({
'height': percent,
'top': pTop
});
$(this).parent().animate({
height: "toggle"
}, {
duration: 900,
specialEasing: {
height: "swing"
}
});
});
I have prepared a JSFiddle with my progress bars HERE.
The right behavior is to fill the progress-bars upwards, like in THIS example.
You need to animate both the height and top of your bars, or you need to construct them such that they are pinned to the horizontal axis when you change the height. The second takes a little more thought, but the first, although not as elegant, is straight forward.
To animate top you can't use toggle (as it is animating to 100% and back, not to 0), so you will need to animate both the shrink and grow separately using done to trigger a second animation. Taking the same style as you used above:
$('.vertical-bars .progress-fill span').each(function () {
var percent = $(this).html();
var pTop = 100 - ( percent.slice(0, percent.length - 1) ) + "%";
$(this).parent().css({
'height': percent,
'top': pTop
});
var self=this;
$(this).parent().animate({
height: 0,
top: "100%"
}, {
duration: 900,
specialEasing: {
height: "swing",
top: "swing"
},
done:function(){
$(self).parent().animate({
height: percent,
top: pTop
}, {
duration: 900,
specialEasing: {
height: "swing",
top: "swing"
}
})
}
});
});
Of course you can also achieve the same thing using css animation. If I have time to figure it out I'll post an edit.
I don't know what height: "toggle" does but you basically want to set 0 height and 100% offset from top and then start animation that adjusts both styles.
The 100ms between animations is done simply by using setTimeout and incrementing the timeout.
https://jsfiddle.net/kss1su0b/1/
var elm = $(this).parent();
elm.css({
'top': '100%',
'height': 0
});
setTimeout(function() {
elm.animate({
'height': percent,
'top': pTop
}, {
duration: 900,
specialEasing: {
height: "swing"
},
});
}, animOffset);
animOffset += 100;
The simplest and most performing way to invert the animation direction is to align the bars at the bottom with css:
vertical-bars .progress-fill {
position: absolute;
bottom: 0;
}
Then you don't need to set the top any more with jQuery and set a delay:
$('.vertical-bars .progress-fill').each(function (index) {
var percentage = $(this).find('.percentage').html();
$(this).delay(index * 100).animate(
{
height: percentage
}, {
duration: 900,
done: function () {
$(this).find('span').show("normal");
}
}
);
});
jsfiddle

Raphael js | how to animate with two images

i am making a image scroller for my website,and i have two pictures.
i want the user to click on the next button,the image to rotate 180 degrees over the course of 250 milliseconds,change pictures,and the rotate 180 degrees again into position over the course of 250 milliseconds.
would there be a way to do that?
back.node.onclick=function(){
kitaimage1.animate({
transform : "r180",
kitaimage1.hide();
testimg1.show();
testimg1.animate({ transform : "r180" });
},250);
}
is what i have so far,but it doesnt work.
thanks in advance,noam haber
That's absolutely possible, although there are a lot of ways you could structure it. Here is one of many possible solutions. I assume the presence of a Raphael paper object named paper throughout.
Location and Dimensions
var cx = 180, cy = 125; /* These are the coordinates of the center point of your image(s) inside the paper */
var dx = 320, dy = 240; /* dx and dy describe the dimensions of the desired image interface. */
Image Information
I'd assume you'd want to load this information dynamically via ajax (depending on how your gallery is structured) or be able to re-use it. This example uses an array of objects describing the url, width, and height of each item in the list. For instance...
var imageList =
[
{
url: '/tests/images/sunset1.jpg',
width: 1600,
height: 900,
},
{
url: '/tests/images/moonrise1.jpg',
width: 1024,
height: 768,
},
{
url: '/tests/images/cityscape.jpg',
width: 1920,
height: 1080,
},
{
url: '/tests/images/forest03.jpg',
width: 500,
height: 325,
},
];
The Code
Last but not least, run this code when your DOM is ready (or after your images have loaded, or whatever other event should trigger it). This just creates a function to do the transition and then calls it to get the first image into place.
var imageIndex = 0;
var rotationMultiplier = 1;
var currentImage = null;
function rotateTransitionNext()
{
rotationMultiplier *= -1;
imageIndex++;
if ( imageIndex >= imageList.length )
imageIndex = 0;
if ( currentImage )
{
currentImage.animate( { transform: ["...r", 180 * rotationMultiplier, cx, cy], opacity: 0.0 }, 1000, '<>', function()
{
this.remove();
} );
}
var newImage = paper.image( imageList[imageIndex].url, cx - dx / 2, cy - dy / 2, dx, dy )
.attr( { transform: [ "r", -180 * rotationMultiplier, cx, cy], opacity: 0.0 } )
.animate( { transform: [ "...r", 180 * rotationMultiplier, cx, cy ], opacity: 1.0 }, 1000, '<>', function()
{
currentImage = this;
this.click( rotateTransitionNext );
} );
}
rotateTransitionNext();
Loose Ends
As a rough starting point, there are a few things that should be done to wrap this up:
For goodness' sake, wrap this stuff up in its own namespace to avoid cluttering the global scope with detritus (my bad)
Preserve aspect ratios of different images. Right now, all images are being forced to conform to the globally defined dimensions (dx and dy)
Happy coding.
UPDATE: here is a staged example of this code at work. Just click on the image to cause it to rotate to the next.

Change menu option width with jQuery

I have got a menu on my homepage and on hover I would like them to enlarge. This is exactly what I have achieved, except there is one flaw:
When I move off before the animation ends, the option stops the animation and subtracts 30 from the width that left off from the previous animation. So it always intersects with the other animation and causes false results.
Example:
I move quickly to menu option 1, it only expands little - let's say by 10px - while I am on it, and as I move off the width decreases by 30px, which is more than the previously moved 10px, which results in a smaller button overall.
I would like to somehow capture how much it has moved during the mouseover animation and only decrease the width in the leaving function by that amount. Or, of course some other easy solution, if there is one...
Here's the code:
$('.menu_option').hover(
function() {
var w = $(this).width()+30+"";
$(this).stop().animate({ width:w}, 150, 'easeOutQuad');
}, function() {
var w = $(this).width()-30+"";
$(this).stop().animate({ width:w}, 150, 'easeOutQuad');
});
What you can do is make another variable which is the origin width then when you put it back go back to the origin:
js:
var o = $('.menu_option').width();
$('.menu_option').hover(function () {
var w = $(this).width() + 30 + "";
$(this).stop().animate({
width: w
}, 150, 'easeOutQuad');
}, function () {
$(this).stop().animate({
width: o
}, 150, 'easeOutQuad');
});
http://jsfiddle.net/Hive7/qBLPa/6/
You need to complete the previous animation before the width is calculated
$('.menu_option').hover(function () {
var $this = $(this).stop(true, true);
var w = $this.width() + 30;
$this.animate({
width: w
}, 150, 'easeOutQuad');
}, function () {
var $this = $(this).stop(true, true);
var w = $this.width() - 30 + "";
$this.animate({
width: w
}, 150, 'easeOutQuad');
});
Demo: Fiddle

Javascript (jQuery) Scale an Image to Its Container's Center Point

This seems like it should be quite simple, but for some reason I can't quite wrap my brain around it. I have an image inside a "viewport" div, of which the overflow property is set to hidden.
I've implemented a simple zooming and panning with jQuery UI, however I am having trouble getting the zoom to appear to originate from the center of the viewport. I did a little screencast from Photoshop the effect I'm trying to reproduce: http://dl.dropbox.com/u/107346/share/reference-point-zoom.mov
In PS you can adjust the scaling reference point an the object will scale from that point. Obviously this is not possible with HTML/CSS/JS, so I'm trying to find the appropriate left and top CSS values to mimic the effect.
Here is the code in question, with a few unnecessary bits removed:
html
<div id="viewport">
<img id="map" src="http://dl.dropbox.com/u/107346/share/fake-map.png" alt="" />
</div>
<div id="zoom-control"></div>
javascript
$('#zoom-control').slider({
min: 300,
max: 1020,
value: 300,
step: 24,
slide: function(event, ui) {
var old_width = $('#map').width();
var new_width = ui.value;
var width_change = new_width - old_width;
$('#map').css({
width: new_width,
// this is where I'm stuck...
// dividing by 2 makes the map zoom
// from the center, but if I've panned
// the map to a different location I'd
// like that reference point to change.
// So instead of zooming relative to
// the map image center point, it would
// appear to zoom relative to the center
// of the viewport.
left: "-=" + (width_change / 2),
top: "-=" + (width_change / 2)
});
}
});
Here is the project on JSFiddle: http://jsfiddle.net/christiannaths/W4seR/
Here's the working solution. I will explain the logic at the next edit.
Function Logic:
Summary: Remember the center position of the image, relatively.
The calculations for width and height are similar, I will only explain the height calculationThe detailled explanation is just an example of function logic. The real code, with different variable names can be found at the bottom of the answer.
Calculate the center (x,y) of the #map, relative to #viewport. This can be done by using the offset(), height() and width() methods.
// Absolute difference between the top border of #map and #viewport
var differenceY = viewport.offset().top - map.offset().top;
// We want to get the center position, so add it.
var centerPosition = differenceY + viewport.height() * 0.5;
// Don't forget about the border (3px per CSS)
centerPosition += 3;
// Calculate the relative center position of #map
var relativeCenterY = centerPosition / map.height();
// RESULT: A relative offset. When initialized, the center of #map is at
// the center of #viewport, so 50% (= 0.5)
// Same method for relativeCenterX
Calculate the new top and left offsets:
// Calculate the effect of zooming (example: zoom 1->2 = 2)
var relativeChange = new_width / old_width;
// Calculate the new height
var new_height = relativeChange * old_height;
// Calculate the `top` and `left` CSS properties.
// These must be negative if the upperleft corner is outside he viewport
// Add 50% of the #viewport's height to correctly position #map
// (otherwise, the center will be at the upperleft corner)
var newTopCss = -relativeCenterY * new_height + 0.5 * viewport.height();
Change the CSS property
map.css("top", newTopCss);
Demo: http://jsfiddle.net/W4seR/12/
var map = $('#map');
var viewport = $('#viewport');
// Cache the size of the viewport (300x300)
var viewport_size = {
x: viewport.width(),
y: viewport.height()
};
map.draggable();
$('#zoom-control').slider({
min: 300,
max: 1020,
value: 300,
step: 24,
create: function() {
map.css({
'width': 300,
'left': 0,
'top': 0
});
},
slide: function(event, ui) {
var old_width = map.width();
var old_height = map.height();
var viewport_offset = viewport.offset();
var offset = map.offset();
offset = {
top: viewport_offset.top - offset.top + .5*viewport_size.y +3,
left: viewport_offset.left - offset.left + .5*viewport_size.x +3
};
// Relative offsets, relative to the center!
offset.top = offset.top / old_height;
offset.left = offset.left / old_width;
var new_width = ui.value;
var relative = new_width / old_width;
var new_height = relative * old_height;
offset = {
top: -offset.top * new_height + .5*viewport_size.y,
left: -offset.left * new_width + .5*viewport_size.x
};
var css_properties = {
width: new_width,
left: offset.left,
top: offset.top
};
map.css(css_properties);
trace((map.position().left));
}
});
I have always relied on the kindness of strangers. Pertinent changes:
// Calculate the offset as a percentage, accounting for the height of the window
var x_offset = ((map.position().left-150))/(old_width/2);
var y_offset = ((map.position().top-150))/(old_width/2);
var css_properties = {
width: new_width,
// Set the offset based on the existing percentage rather than 1/2
// then readjust for the height of the window
left: (new_width * x_offset /2 ) + 150 + "px",
top: (new_width * y_offset /2 ) + 150 + "px"
};
Replace the hardcoded 150 with a variable set on viewport instantiation if necessary.
Here is a quick working version:
http://jsfiddle.net/flabbyrabbit/chLkZ/
Probably not the neatest solution but seems to work nicely, hope it helps.
Update: sorry this only works if zoom is 0 when the map is moved.

Expand and collapse a div

I have a list of items & they are holding images, each image is 800w x 600 H. The original div height is 800 W x 300 H. I figured out how to expand the div when it is clicked, but i want to know how to collapse it when you clicked it while it is already expanded. Right now i just expands the div even further
$('.expand').bind('click', function() {
var currHeight = $(this).css('height').replace(/px/,'');
currHeight = currHeight * 1;
var newHeight = currHeight + 500;
$(this).animate({
height: newHeight
},1000);
});
any idea on how to create an if else statement that would say, IF the div is already expanded then collapse on click, or if the div is collapse, then expand to # of px.
You can detect the current height and branch:
$('.expand').bind('click', function() {
var $this = $(this),
height = $this.height();
if (height > 500) {
height -= 500;
}
else {
height += 500;
}
$this.animate({
height: height
},1000);
});
I've done a couple of other things in there. You can use height rather than css('height') to get the value without units, and no need for the * 1 trick. I've also done the $(this) once and reused it, since there are multiple function calls and an allocation involved when you call the $() function. (It doesn't matter here, but it's a good habit to get into provided you're not caching it longer than you mean to [via a closure or such].)
Alternately, you can remember that you've done it another way (using the data feature):
$('.expand').bind('click', function() {
var $this = $(this),
height = $this.height(),
expanded = $this.data('expanded');
if (expanded) {
height -= 500;
}
else {
height += 500;
}
$this.data('expanded', !expanded);
$this.animate({
height: height
},1000);
});
Or combine those to store the original height in case it gets influenced by something else:
$('.expand').bind('click', function() {
var $this = $(this),
height = $this.height(),
prevHeight = $this.data('prevHeight');
if (prevHeight) {
height = prevHeight;
$this.data('prevHeight', undefined);
}
else {
$this.data('prevHeight', height);
height += 500;
}
$this.animate({
height: height
},1000);
});
Take your pick!
I would use CSS to set the height of the div in both original and expanded versions, and then when the div is clicked, toggle a class to change the height:
/* CSS for the height */
.expand {
height: 300px;
}
.expand.expanded {
height: 600px;
}
and then in the click method, just:
$(this).toggleClass("expanded");
A few pointers with jQ:
.click(function(){})
.css({height: "300*1px"}) // Why are you multiplying Anything by ONE?!
And you can use
if($(this).css("height") == "300px") {
Do stuff
} else {
Do other stuff
}
Edit: But other options above are far better.
You can check the .height() at the time of the click event and .animate() the height += or -= accordingly (something .animate() supports), like this:
$('.expand').click(function() {
$(this).animate({
height: $(this).height() > 300 ? "+=500px" : "-=500px"
}, 1000);
});
Or, use .toggle(), like this:
$('.expand').toggle(function() {
$(this).animate({ height: "+=500px" }, 1000);
}, function() {
$(this).animate({ height: "-=500px" }, 1000);
});
Pure Jquery, check the documentation Jquery Animate
$( "#clickme" ).click(function() {
$( "#book" ).animate({
height: "toggle"
}, {
duration: 5000,
specialEasing: {
height: "linear"
},
complete: function() {
//DO YOUR THING AFTER COMPLETE
}
});
});

Categories

Resources