jQuery 动画 - 平滑的大小过渡
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/244758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery Animation - Smooth Size Transition
提问by neezer
So this might be really simple, but I haven't been able to find any examples to learn off of yet, so please bear with me. ;)
所以这可能真的很简单,但我还没有找到任何可以学习的例子,所以请耐心等待。;)
Here's basically what I want to do:
这基本上是我想要做的:
<div>Lots of content! Lots of content! Lots of content! ...</div>
....
$("div").html("Itsy-bitsy bit of content!");
I want to smoothly animate between the dimensions of the div with lots of content to the dimensions of the div with very little when the new content is injected.
当注入新内容时,我想在具有大量内容的 div 尺寸与 div 尺寸之间平滑地设置动画。
Thoughts?
想法?
回答by Shog9
Try this jQuery plugin:
试试这个 jQuery 插件:
// Animates the dimensional changes resulting from altering element contents
// Usage examples:
// $("#myElement").showHtml("new HTML contents");
// $("div").showHtml("new HTML contents", 400);
// $(".className").showHtml("new HTML contents", 400,
// function() {/* on completion */});
(function($)
{
$.fn.showHtml = function(html, speed, callback)
{
return this.each(function()
{
// The element to be modified
var el = $(this);
// Preserve the original values of width and height - they'll need
// to be modified during the animation, but can be restored once
// the animation has completed.
var finish = {width: this.style.width, height: this.style.height};
// The original width and height represented as pixel values.
// These will only be the same as `finish` if this element had its
// dimensions specified explicitly and in pixels. Of course, if that
// was done then this entire routine is pointless, as the dimensions
// won't change when the content is changed.
var cur = {width: el.width()+'px', height: el.height()+'px'};
// Modify the element's contents. Element will resize.
el.html(html);
// Capture the final dimensions of the element
// (with initial style settings still in effect)
var next = {width: el.width()+'px', height: el.height()+'px'};
el .css(cur) // restore initial dimensions
.animate(next, speed, function() // animate to final dimensions
{
el.css(finish); // restore initial style settings
if ( $.isFunction(callback) ) callback();
});
});
};
})(jQuery);
Commenter RonLugge points out that this can cause problems if you call it twice on the same element(s), where the first animation hasn't finished before the second begins. This is because the second animation will take the current (mid-animation) sizes as the desired "ending" values, and proceed to fix them as the final values (effectively stopping the animation in its tracks rather than animating toward the "natural" size)...
评论员 RonLugge 指出,如果您在同一个元素上调用它两次,这可能会导致问题,其中第一个动画在第二个开始之前还没有完成。这是因为第二个动画将当前(中间动画)大小作为所需的“结束”值,并继续将它们固定为最终值(有效地停止动画在其轨道上而不是朝着“自然”大小进行动画处理)...
The easiest way to resolve this is to call stop()
before calling showHtml()
, and passing true
for the second (jumpToEnd) parameter:
解决此问题的最简单方法是在调用stop()
之前调用showHtml()
,并传递true
第二个 ( jumpToEnd) 参数:
$(selector).showHtml("new HTML contents")
.stop(true, true)
.showHtml("even newer contents");
This will cause the first animation to complete immediately (if it is still running), before beginning a new one.
这将导致第一个动画在开始新动画之前立即完成(如果它仍在运行)。
回答by Josh Bush
回答by lucas
maybe something like this?
也许是这样的?
$(".testLink").click(function(event) {
event.preventDefault();
$(".testDiv").hide(400,function(event) {
$(this).html("Itsy-bitsy bit of content!").show(400);
});
});
Close to what I think you wanted, also try slideIn/slideOut or look at the UI/Effects plugin.
接近我认为你想要的,也试试 slideIn/slideOut 或查看 UI/Effects 插件。
回答by Daan
Here is how I fixed this, I hope this will be usefull ! The animation is 100% smooth :)
这是我解决这个问题的方法,我希望这会很有用!动画 100% 流畅 :)
HTML:
HTML:
<div id="div-1"><div id="div-2">Some content here</div></div>
Javascript:
Javascript:
// cache selectors for better performance
var container = $('#div-1'),
wrapper = $('#div-2');
// temporarily fix the outer div's width
container.css({width: wrapper.width()});
// fade opacity of inner div - use opacity because we cannot get the width or height of an element with display set to none
wrapper.fadeTo('slow', 0, function(){
// change the div content
container.html("<div id=\"2\" style=\"display: none;\">new content (with a new width)</div>");
// give the outer div the same width as the inner div with a smooth animation
container.animate({width: wrapper.width()}, function(){
// show the inner div
wrapper.fadeTo('slow', 1);
});
});
There might be a shorter version of my code, but I just kept it like this.
我的代码可能有更短的版本,但我只是保持这样。
回答by A-P
This does the job for me. You can also add a width to the temp div.
这对我有用。您还可以向临时 div 添加宽度。
$('div#to-transition').wrap( '<div id="tmp"></div>' );
$('div#tmp').css( { height: $('div#to-transition').outerHeight() + 'px' } );
$('div#to-transition').fadeOut('fast', function() {
$(this).html(new_html);
$('div#tmp').animate( { height: $(this).outerHeight() + 'px' }, 'fast' );
$(this).fadeIn('fast', function() {
$(this).unwrap();
});
});
回答by davidcondrey
You can smooth out the jQuery animation using dequeue
. Test for presence of class (set upon hover and removed on mouseOut animate callback) before staring new animation. When new animation does start, dequeue.
您可以使用dequeue
. 在开始新动画之前测试类的存在(在悬停时设置并在 mouseOut 动画回调上删除)。当新动画开始时,出列。
var space = ($(window).width() - 100);
$('.column').width(space/4);
$(".column").click(function(){
if (!$(this).hasClass('animated')) {
$('.column').not($(this).parent()).dequeue().stop().animate({width: 'toggle', opacity: '0.75'}, 1750,'linear', function () {});
}
$(this).addClass('animated');
$('.column').not($(this).parent()).dequeue().stop().animate({width: 'toggle', opacity: '0.75'}, 1750,'linear', function () {
$(this).removeClass('animated').dequeue();
});
$(this).dequeue().stop().animate({
width:(space/4)
}, 1400,'linear',function(){
$(this).html('AGAIN');
});
});
The demo is setup as 5 full-height columns, clicking any of the columns 2 thru 5 will animate toggle width of the other 3 and move the clicked element to the far left.
该演示设置为 5 个全高列,单击第 2 到第 5 列中的任何一列将使其他 3 列的切换宽度动画化,并将单击的元素移动到最左侧。
回答by snotbubblelou
To piggy-back on the jquery plugin solution (too low of reputation to add this as a comment) jQuery.html() will remove any event handlers on the appended html. Changing:
为了搭载 jquery 插件解决方案(声誉太低,无法将其添加为评论),jQuery.html() 将删除附加 html 上的任何事件处理程序。改变:
// Modify the element's contents. Element will resize.
el.html(html);
to
到
// Modify the element's contents. Element will resize.
el.append(html);
will retain the event handlers of the "html" elements
将保留“html”元素的事件处理程序
回答by micahwittman
Hello meyahoocoma4c5ki0pprxr19sxhajsogo6jgks5dt.
你好 meyahoocoma4c5ki0pprxr19sxhajsogo6jgks5dt。
You could wrap the 'content div' with an 'outer div' which is set to an absolute width value. Inject the new content with a "hide()" or "animate({width})" method, shown in the other answers. This way, the page doesn't reflow in between because the wrapper div holds a steady width.
您可以使用设置为绝对宽度值的“外部 div”包装“内容 div”。使用“hide()”或“animate({width})”方法注入新内容,如其他答案所示。这样,页面不会在中间重排,因为包装 div 保持稳定的宽度。