I have elements on a page that I want to animate in to view, but after they've animated in, I want to defer further animation on them to CSS (by changing classes)... I am finding that Velocity leaves all my animated properties in the style= tag and makes CSS transitions impossible.
I have a solution below, but resetting the CSS on complete seems iffy, I was wondering if there's a better way to do it?
// first use CSS to hide the element and squish it
$el.css({
width: 0,
left: "-10px",
opacity: 0,
marginRight: 0,
transition: "none"
})
// now animate the width and margin (do this first
// so there's a little gap between existing elements
// before we fade in new element.
.velocity({
width: width,
marginRight: margin
}, {
queue: false,
duration: 230
})
// then fade and move in the new element,
// but this is the iffy bit when it completes
// I have to unset all the styles I've animated?
.velocity({
left: 0,
opacity: 1
}, {
queue: false,
duration: 100,
delay: 130,
complete: function(els) {
$(els).css({
width: "",
left: "",
opacity: "",
marginRight: "",
transition: ""
});
}
});
Typically, you want animation engines to leave styles inline; otherwise final values will pop as they get overwritten by stylesheets upon removal.
You can also do $(els).attr("style", ""); to just clear all styles.
Related
I have a simple wrapper div that I animate in using velocity.js UI pack. In the complete callback function, I am using a combination of UI pack and blast.js to animate three sentences.
The problem is that my sentences are initially shown, and only after that they are animated. They shouldn't be visible after the wrapper div is animated into view.
Everything is working fine if I don't animate the wrapper div, guess the opacity settings during animation are messing with child elements.
$('.wrap').velocity('transition.slideUpIn', {
delay: 1000,
display: null,
complete : function(){
$(".animated")
.blast({ delimiter: "character" })
.velocity("transition.fadeIn", {
display: null,
duration: 1000,
stagger: 60,
delay: 400
});
}
})
Here is the fiddle to see the problem : http://jsfiddle.net/vcsr6aqj/1/
The problem is that your p tags aren't at opacity: 0, but only their characters, which are inside a span having as class blast. Since your invisible characters are only created when you call $(".animated").blast({ delimiter: "character" }), which means once your wrapper has completed its apparition, the sentences will be visible until then. So you have two possibilities that I can think of.
Create your span characters with blast at the page load, instead at the wrapper velocity complete and then call velocity on your created spans:
$(document).ready(function() {
$(".animated").blast({ delimiter: "character" });
$('.wrap').velocity('transition.slideUpIn', {
delay: 1000,
display: null,
complete : function(){
$(".animated .blast").velocity("transition.fadeIn", {
display: null,
duration: 1000,
stagger: 60,
delay: 400
});
}
})
});
JSFiddle example
Add a class to your p tags having opacity: 0:
<p class="animated no-opacity">Sentence number one.</p>
<p class="animated no-opacity">Sentence number two.</p>
<p class="animated no-opacity">Just one sentence more.</p>
CSS:
.no-opacity {
opacity: 0;
}
When your wrapper has completed the velocity, remove the class from your p tags. Also, remove delay: 400 from your velocity attributes, otherwise the sentences will show for 400 milliseconds:
$(document).ready(function() {
$('.wrap').velocity('transition.slideUpIn', {
delay: 1000,
display: null,
complete : function(){
$animated = $(".animated");
$animated.removeClass("no-opacity");
$animated.blast({ delimiter: "character" })
.velocity("transition.fadeIn", {
display: null,
duration: 1000,
stagger: 60
});
}
})
});
JSFiddle example
Here you go (fiddle). I'm sure there are more elegant solutions.
It appears that the slideUpIn animates opacity from 0 to 1, including the opacity of .animated which is probably 'inherited'. Setting it to 0 to hide it fixes it, but then .blast() doesn't work, so we enable it again.
I have created these two functions using jquery transit that are designed to slide in a new block of html on to the page when the user presses on the right or left buttons. They work some of the time. Other times the content will load and then not unhide itself. So it will be loaded and you can inspect it with chrome and see the display is still set to none. Other times there are no problems and it works exactly as intended. There are no errors on page. Really the only JavaScript on the page is several different versions of this function that all load a different page and scroll it in, in some matter or form.
My question is: Am I using the function completes correctly from jquery Transit? Is my function working as intended or have I missed something big and there not set up properly.
function ShowPartTiles_FromLeft() {
$("#SeriesPartBrand").transition({
opacity: 0,
x: "1000px"
}, 500, "out", function() {
$("#SeriesPartBrand").transition({
opacity: 0,
x: "-1000px"
}, 0, "out")
}), $("#SeriesPartBrand").load("<?php echo uri_string() ?>/part", function() {
$("#SeriesPartBrand").transition({
opacity: 1,
x: "0"
}, 500, "in")
})
}
function ShowPartTiles_FromRight() {
$("#SeriesPartBrand").transition({
opacity: 0,
x: "-1000px"
}, 500, "out", function() {
$("#SeriesPartBrand").transition({
opacity: 0,
x: "1000px"
}, 0, "out")
}), $("#SeriesPartBrand").load("<?php echo uri_string() ?>/part", function() {
$("#SeriesPartBrand").transition({
opacity: 1,
x: "0"
}, 500, "in")
})
}
There is no transition function in jQuery, there is an animate one.
But I would advise using css3 transition property:
#SeriesPartBrand {
transition: all 0.5s;
}
function ShowPartTiles_FromLeft() {
$("#SeriesPartBrand").css({opacity: 0, left: 1000});
$("#SeriesPartBrand").off('transitionend').on('transitionend', function() {
$("#SeriesPartBrand").css({opacity: 0, left: -1000});
$("#SeriesPartBrand").load("<?php echo uri_string() ?>/part", function() {
$("#SeriesPartBrand").css({opacity: 0, left: 0});
});
});
}
This should get you started. Also don't name your JS functions with first capital letter and don't, the name would look better like this: "showPartTilesFromLeft()".
And html ids and classes must be all lowercase with words separated by comma "-".
I'm working on what I thought would be a simple chunk of code, trying to dynamically (using 'this') animate div blocks to scale (zoom) to the size of the parent container (section tag) on click.
My HTML:
<section>
<div id="project"></div><div id="project"></div><div id="project"></div>
<div id="project"></div><div id="project"></div><div id="project"></div>
</section>
My JavaScript:
$("#project").click(function() {
$(this).animate({
opacity: 0.75,
width: 100%,
height: 100%
}, 5000, function() {
});
});
Both Jquery and Jquery UI are linked correctly from Google Libraries (so says my console), my console also tells me that there is a syntax error with an unexpected ",", however I am taking this syntax straight from JqueryUI.com. Any help is appreciated!
Additionally, I want to be able to dynamically select all other divs except the currently clicked div and remove them from the DOM (using display:none), just so it looks cleaner, but I don't know how to go about 'selecting' them in my code...
Thanks all! :)
you are missing quotes around 100% so your code will be correct like this
$("#project").click(function() {
$(this).animate({
opacity: 0.75,
width: "100%",
height: "100%"
}, 5000, function() {
});
and please use unique IDs
Edit:
for using classes you can use something like that
$(".project").click(function() {
$(".project").css({'display':'none'});
$(this).css({'display':'block'});
$(this).animate({
opacity: 0.75,
width: "100%",
height: "100%"
}, 5000, function() {
});
I want to be able to dynamically select all other divs except the currently clicked div and remove them from the DOM (using display:none), just so it looks cleaner, but I don't know how to go about 'selecting' them in my code...
var $project = $(".project");
$project.click(function() {
var thisDiv = this;
$project.each(function(index, elem) {
if (elem!==thisDiv) $(elem).css('display', 'none');
});
$(thisDiv).animate({
opacity: 0.75,
width: "100%",
height: "100%"
}, 5000, function() {});
});
I'm currently trying to achieve an animation with multiply elements to achieve a focused viewport effect.
The issue I am having is that in browsers such as Safari the bottom element does not seems to be animated correctly and you see a 1px line from time to time. You also see this in from if you keep refreshing the browser.
I assume this is because the animations are not firing all at the same time..
The following is the animation code:
$("#top").animate({
height: '150px'
}, {
duration: 2000,
queue: false
});
$("#right").animate({
top: '150px',
left: '200px',
height: '50px'
}, {
duration: 2000,
queue: false
});
$("#left").animate({
top: '150px',
width: '150px',
height: '50px'
}, {
duration: 2000,
queue: false
});
$("#bottom").animate({
top: '200px'
}, {
duration: 2000,
queue: false
});
I have provide a full working fiddle of what I have so far:
http://jsfiddle.net/cjcartlidge/AKERR/
Any tips would be grateful. Note: The reason i'm doing a 4 div solutions is due to needing to support IE-8 and IE-8 not support transparent borders.
UPDATE:
I've also tried the animation in greensock.js and get the same result with the following code:
var tl = new TimelineLite();
tl.to($('#top'), 1, {height: hotspot.y + 'px'}, 0);
tl.to($('#bottom'), 1, {top: (hotspot.y + hotspot.height) + 'px'}, 0);
tl.to($('#right'), 1, { top: hotspot.y + 'px', left: (hotspot.x + hotspot.width) + 'px', height: hotspot.height + 'px'}, 0);
tl.to($('#left'), 1, { top: hotspot.y + 'px', width: hotspot.x + 'px', height: hotspot.height + 'px', }, 0);
The extra pixel is probably due to rounding error.
Two options come to mind:
Use native CSS animation and hope that browsers handle rounding more gracefully than JS libraries.
Make the four edge pieces overlap rather than merely touch, so you can't possibly have a gap. You'd have to stick them in their own container and apply opacity to the shared parent, of course.
I have found jQuery: FadeOut then SlideUp and it's good, but it's not the one.
How can I fadeOut() and slideUp() at the same time? I tried two separate setTimeout() calls with the same delay but the slideUp() happened as soon as the page loaded.
Has anyone done this?
You can do something like this, this is a full toggle version:
$("#mySelector").animate({ height: 'toggle', opacity: 'toggle' }, 'slow');
For strictly a fadeout:
$("#mySelector").animate({ height: 0, opacity: 0 }, 'slow');
Directly animating height results in a jerky motion on some web pages. However, combining a CSS transition with jQuery's slideUp() makes for a smooth disappearing act.
const slideFade = (elem) => {
const fade = { opacity: 0, transition: 'opacity 400ms' };
elem.css(fade).slideUp();
};
slideFade($('#mySelector'));
Fiddle with the code:
https://jsfiddle.net/00Lodcqf/435
In some situations, a very quick 100 millisecond pause to allow more fading creates a slightly smoother experience:
elem.css(fade).delay(100).slideUp();
This is the solution I used in the dna.js project where you can view the code (github.com/dnajs/dna.js) for the dna.ui.slideFade() function to see additional support for toggling and callbacks.
The accepted answer by "Nick Craver" is definitely the way to go. The only thing I'd add is that his answer doesn't actually "hide" it, meaning the DOM still sees it as a viable element to display.
This can be a problem if you have margin's or padding's on the 'slid' element... they will still show. So I just added a callback to the animate() function to actually hide it after animation is complete:
$("#mySelector").animate({
height: 0,
opacity: 0,
margin: 0,
padding: 0
}, 'slow', function(){
$(this).hide();
});
It's possible to do this with the slideUp and fadeOut methods themselves like so:
$('#mydiv').slideUp(300, function(){
console.log('Done!');
}).fadeOut({
duration: 300,
queue: false
});
I had a similar problem and fixed it like this.
$('#mydiv').animate({
height: 0,
}, {
duration: 1000,
complete: function(){$('#mydiv').css('display', 'none');}
});
$('#mydiv').animate({
opacity: 0,
}, {
duration: 1000,
queue: false
});
the queue property tells it whether to queue the animation or just play it right away
Throwing one more refinement in there based on #CodeKoalas. It accounts for vertical margin and padding but not horizontal.
$('.selector').animate({
opacity: 0,
height: 0,
marginTop: 0,
marginBottom: 0,
paddingTop: 0,
paddingBottom: 0
}, 'slow', function() {
$(this).hide();
});