I have this function:
function fixedFeeSize(i){
var num1 = $('#num' + i);
if (num1.hasClass("extended")) {
num1.stop(true, true).animate({height: '59px'},500);
num1.removeClass("extended");
}else{
var height = 0;
num1.animate({height: '360px'},500);
num1.addClass("extended");
}
return null;
}
Which expands / contracts a div, however I am struggling to get it to expand to the height of the div as each div (there will be 10+) is going to be different heights.
I tried num1.animate({height: 'auto'},500); which has not worked.
Is this the effect you're after?
jQuery(".menu a").mouseenter(function(){
jQuery(this).stop().animate({
height: 200, opacity: 0.5
}, 1000, "linear");
});
jQuery(".menu a").mouseleave(function(){
jQuery(this).stop().animate({
height: 18, opacity: 1
}, 1000, "linear");
});
Here's a jsfiddle:
http://jsfiddle.net/kKAZx/1/
For further reading, take a look at the full documentation of the .animate function: http://api.jquery.com/animate/
You can combine effects to make all kinds of fantastic, standard-compliant effects.
Related
I have a number of divs positioned absolutely on a background image.
On the page will also be some buttons. When those are clicked different variables will trigger, shrinking and growing these divs.
Here is the javascript I'm currently using...
$(document).ready(function() {
var title = 1;
$(".button1").click(function() {
title = 1;
});
$(".button2").click(function() {
title = 2;
});
$(document).click(function(e) {
console.log(title);
if (title==1){
$('.london').animate({ backgroundColor:'green', width:'50', height:'50' }, 300);
} else if (title==2){
$('.london').animate({ backgroundColor:'red', width:'40', height:'40' }, 300);
}
});
});
As they are absolutely positioned they are scaled from the corner they are positioned with.
see an example here.
What I need to do is shrink and grow these divs from their center point. The only solutions I've seen seem overly complicated.
I guess I could add a negative margin of half the divs width in the jQuery to counteract this? I'll try that if there are no better solutions
Thanks for any help.
bboybeatle, your "negative margin of half the divs width" idea is spot on, and not at all difficult to implement. Just include the required marginTop and marginLeft settings in the two animations.
$(function() {
var cssMap1a = {
backgroundColor: 'green'
};
var cssMap1b = {
width: 50,
height: 50,
marginTop: -10,
marginLeft: -10
};
var cssMap2a = {
backgroundColor: 'red'
};
var cssMap2b = {
width: 30,
height: 30,
marginTop: 0,
marginLeft: 0
};
$(".button1").click(function () {
$('.london').css(cssMap1a).animate(cssMap1b, 300);
});
$(".button2").click(function () {
$('.london').css(cssMap2a).animate(cssMap2b, 300);
});
});
And here's a fiddle. Fiddles are not difficult to set up. Hopefully this will help you next time you need to ask a question here.
As you will see :
"London" and the buttons are moved to a better position for demo purposes
The colour changes are separated out as separate css maps. They didn't work in the fiddle when included in the animation maps. jQuery needs a plugin to animate colours.
Thanks very much for that #Roamer-1888, I actually used some variables to make it slightly easier to apply the margin. I will remember that technique of putting multiple css properties in a variable..
Heres a snippet of my code I ended up using...
londonMargin = london/2 - london;
$('.london').animate({ width:london, height:london, marginLeft:londonMargin, marginBottom:londonMargin }, 300);
Just for fun I put together a little FIDDLE that has a function to which you pass an element name, the x and y coordinates of the center, and it will position the element in the larger element.
JS
var myelement = $('.boxdiv');
var myelement2 = $('.boxdiv2');
putmycenter( myelement, 90, 90 );
putmycenter( myelement2, 160, 280 );
function putmycenter (element, x, y)
{
var boxdivxcentre = element.width()/2;
var boxdivycentre = element.height()/2;
var boxdivposx = (x - boxdivxcentre);
var boxdivposy = (y - boxdivycentre);
element.css({
"top" : boxdivposy + 'px',
"left" : boxdivposx + 'px'
});
}
I have this semi-slider-style UI where new terms are added in from the left: http://jsfiddle.net/v4v5cvkz/. I'm using the jQuery prependTo function to do this. My issue is that I want the terms that are already displayed to perform an animated slide to the right when a new term gets added, rather than suddenly "appear" in the correct position. I did try adding a "displayed" class to terms that had successfully shown up, and tried adding a slide-to-right animation after that, but that didn't quite achieve the effect I was going for (the "displayed" objects were moved much further to the right than I expected).
Here is the problematic code (you'll probably want to view the fiddle to see it in context though):
function addToStream(term, delay) {
setTimeout(function(){
$("<div />")
.addClass("stream_term")
.html(term)
.css({
opacity: 0
})
.prependTo("#stream_terms")
.animate({opacity:1},
{ duration: 1000,
complete: function() {
$(this).addClass("displayed");
}
});
}, delay);
}
Any help here would be greatly appreciated. Thank-you!
*Note: I have access to jQuery UI in my code, though it isn't linked in the fiddle. Also, if anyone knows of a plugin that can do this sort of thing better than I can, please let me know. The closest one I was able to find was Fraction Slider, but I didn't find it obvious how to create a similar UI with it (it might also be overkill for my purposes).
Here's a way to do it:
function addToStream(term, delay) {
setTimeout(function(){
var newDiv = $("<div />");
newDiv.addClass("stream_term")
.html(term)
.css({
opacity: 0,
display: 'none'
}).prependTo("#stream_terms");
var width = newDiv.width();
var height = newDiv.height();
newDiv.css({
width: 0,
height: height,
display: 'inline-block'
})
.animate({
width: width,
margin: '0 10px',
padding: '5px 10px'
}, 1000)
.animate({opacity: 1}, 1000, function(){
$(this).addClass("displayed");
});
}, delay);
}
It also needs the following CSS changes:
.stream_term {
padding: 0;
margin: 0;
overflow: hidden;
}
DEMO: http://jsfiddle.net/StathisG/hqg29p6r/1/
i got this strange behaviour
when i do a slow hover on image everything is working, the image grows and on hover out the image shrinks.
But when i repeat the hover fast the image keeps growing and growing and the position is changing according to the hover speed
Please see fiddle
Jquery
$(document).ready(function () {
var cont_left = $("#container").position().left;
$("a img").hover(function () {
// hover in
$(this).parent().parent().css("z-index", 1);
current_h = $(this, 'img')[0].height;
current_w = $(this, 'img')[0].width;
$(this).stop(true, false).animate({
width: (current_w * 1.3),
height: (current_h * 1.3),
left: "-=50",
top: "-=50"
}, 300);
}, function () {
// hover out
$(this).parent().parent().css("z-index", 0);
$(this).stop(true, false).animate({
width: current_w + 'px',
height: current_h + 'px',
left: "+=50",
top: "+=50"
}, 300);
});
$(".img").each(function (index) {
var left = (index * 160) + cont_left;
$(this).css("left", left + "px");
});
});
Please advise how to i fix the image grow and position.
P.S: every image has a different dimentions
These lines are the key to the problem:
current_h = $(this, 'img')[0].height;
current_w = $(this, 'img')[0].width;
When you .stop the image-growing animation, it doesn't shrink back to its original size (unless you set its second param to true - but you assign false to it explicitly, and I assume you know what you're doing here). So both dimensions are set to the increased value actually.
Solution is simple: always use the original size of the images:
$(document).ready(function () {
var current_h, current_w;
// ...
current_h = current_h || $(this, 'img')[0].height;
current_w = current_w || $(this, 'img')[0].width;
JS Fiddle.
Two sidenotes here. First, there's a similar problem with positioning of these elements: move too fast, and your images will shift to the left-upper or right-lower corners (depending on the phase); that's because, again, animation is done against the current state of things, which is not the same as original when the previous animation is stopped with .stop(true, false).
Second, using $(this, 'img')[0] in this case is essentially the same as just this. Remember, in event handlers this corresponds to the DOM element having this event handler assigned.
So this is how it can be done (demo):
$("a img").hover(function() {
var $this = $(this);
$this.closest('.img').css('z-index', 1);
var orig = $this.data('orig');
if (!orig) { // caching the original sizes via `jQuery.data`
orig = {
width: this.width,
height: this.height
};
$this.data('orig', orig);
}
$this.stop(true, false).animate({
width: orig.width * 1.3,
height: orig.height * 1.3,
left: -(orig.width * 0.3 / 2),
top: -(orig.height * 0.3 / 2)
}, 300);
}, function () {
var $this = $(this),
orig = $this.data('orig');
if (!orig) {
return false;
// actually, it should never be here,
// as calling 'mouseleave' without data precached
// means 'mouseenter' has been never called
}
$this.closest('.img').css('z-index', 0);
$this.stop(true, false).animate({
width: orig.width,
height: orig.height,
left: 0,
top: 0
}, 300);
});
The problem is that when you hover quickly, your values current_h and current_w don't measure the original height and width, but the current height and width. Thus, every time, you're increasing the value.
Solution
I've used a simple .each() function here to set the original height and width of each image as data attributes which can then be accessed when you're setting current_h and current_w.
$('img').each(function(i, el) {
$(el).attr({
"data-original-width": $(this).width(),
"data-original-height": $(this).height()
});
});
current_h = $(this).attr("data-original-height");
current_w = $(this).attr("data-original-width");
WORKING FIDDLE
You don't have to use the each function though. If you know the height and width of the images before rendering, then you can set these as data attributes in your HTML
Here's my code: http://jsfiddle.net/ZspZT/
As you can see from the example, the fourth div block is flickering pretty badly, particularly on the hover-over effect, but also occasionally with the other divs as well.
Thanks in advance!
It appears that the easing function built into .animate is causing your percentage widths to add up to greater than 100%, causing the last sub-DIV to disappear. There are a few ways to solve this.
When I replace your percentage widths with fixed numerical widths, the problem vanishes. I used this in the code below (and your code had a LOT of redundancy to reduce):
$('document').ready(function() {
var speed = 450;
$('.four-ways-slide').hover(function() {
$(this).stop().animate({
width: 425
}, speed).siblings().stop().animate({
width: 25
}, speed);
}, function() {
$(this).siblings().andSelf().stop().animate({
width: 125
}, speed);
});
});
http://jsfiddle.net/mblase75/ZspZT/10/
Another possibility is to use percent widths that add up to 99% instead of 100%, and set a background color on the container DIV to hide the gap. Adding linear easing to the .animate method helps keep the total width from exceeding 100%:
$('document').ready(function() {
var speed = 450;
$('.four-ways-slide').hover(function() {
$(this).stop().animate({
width: '75%'
}, speed, 'linear').siblings().stop().animate({
width: '8%'
}, speed, 'linear');
}, function() {
$(this).siblings().andSelf().stop().animate({
width: '24.5%'
}, speed, 'linear');
});
});
#four-ways-slide-4,#four-ways-slider{background:#999999;}
http://jsfiddle.net/mblase75/ZspZT/9/
try using 'mouseenter' and 'mouseleave' rather than 'hover'. also you should assign variables rather than repeating divs
var one = $('#four-ways-slide-1');
var two = $('#four-ways-slide-2');
var three = $('#four-ways-slide-3');
var four = $('#four-ways-slide-4');
var all = $('.four-ways-slide');
thisIn = function(){
all.animate({width:'8%'},{duration: 450,queue:false});
};
thisOut = function(){
all.animate({width:'25%'},{duration: 450,queue:false});
};
one.mouseenter(function(){
thisIn();
$(this).animate({width:'76%'},{duration: 450,queue:false});
one.mouseleave(function(){
thisOut();
$(this).animate({width:'25%'},{duration: 450,queue:false});
});
});
Basically I have a small div that is initially styled to 60x60. I have created click event that animates the expansion of the div:
$("#myDiv").click(function () {
$(this).animate(
{
width: "350px",
height: "300px"
}, 500);
}
I would like to reverse this animation if someone clicks the div again. Is there anyway to toggle between the original size and the expanded size (still using the animate function) with each click?
I found the toggleClass function but I don't think this will work with animiate.
You can see a basic fiddle here: http://jsfiddle.net/NS9Qp/
$("#myDiv").toggle(function() {
$(this).stop().animate({
width: "350px",
height: "300px"
}, 500);
}, function() {
$(this).stop().animate({
width: "60px",
height: "60px"
}, 500);
});
Example.
The jQuery toggle() function allows you to define two or more functions to cycle through on each mouse click. In this case, the first one (triggered on the first click) expands the div and the second one (triggered on the second click) resets it. On the third click, it starts back at the first one, and so on.
More about toggle() here.
just to be different :
var size=[];
$("#cornerBox").click(function(){
$(this).width() >= 350 ? size=[60, 60] : size=[350, 300];
$(this).stop().animate({ width: size[0], height: size[1] },500);
});
Fiddle: http://jsfiddle.net/NS9Qp/1/
I ended up using jQuery UI's animated toggleClass effect: http://jqueryui.com/demos/toggleClass/
super simple code:
$('h2').click(function() {
$(this).next().toggleClass("hidden", 1000);
});
Do not hardcode css styles (in my example I used inline css for myDiv element, put this in css files).
<div id="myDiv" style="background:red; width: 60px; height: 60px;"></div>
<script type="text/javascript">
var div = $('#myDiv');
div
.attr('defWidth', div.width())
.attr('defHeight', div.height())
.toggle(function() {
$(this).stop().animate({width: "350px", height: "300px"}, 500);
}, function() {
$(this).stop().animate({width: $(this).attr('defWidth'), height: $(this).attr('defHeight')}, 500);
}
);
</script>
What I do for cases like this, is store a transformation array.
var transforms = { 'height0': 60, 'width0': 60, 'height1': 300, 'width1': 350};
Then, store a toggle between 0 or 1, and use the corresponding values for the animation.
EDIT: combine this with the previous example of toggle, and you've got yourself a solid working solution!