Using Modernizr.prefixed in jQuery .animate - javascript

I'm not good with jQuery syntax as PHP is my thing.
I'm trying to produce a jQuery animation but with the correct vendor prefixes on multiple values, but my understanding of the usage of Modernizr.prefixed is letting me down.
What I'm trying to get is something like:
$('.rightbox3d').animate({
opacity: 1
,top:"60px"
,Modernizr.prefixed('transform'):"translateY(-200px)"
,Modernizr.prefixed('scale'):2
}, 4000);
ie. I want to include the vendor prefixes in the list of styles that are animated, but I get syntax error - unexpected token.
I have tried using
var transformProperty = Modernizr.prefixed ? Modernizr.prefixed('transform') : 'transform';
but it only allows listing that one style
ie: $(".rightbox3d").animate(transformProperty,"translateY(-200px)");
when what I want are multiple styles like transform, opacity, scale etc.
I notice that that line of code doesn't have brace brackets around the transformProperty part, whereas a list does
eg.
$('.rightbox3d').animate({
opacity: 1
,top:"-200px"
}, 4000, function() {
// Animation complete.
});
but I just can't get my head round it. Can anyone help?

So, you're going to have to make a big head leap. CSS Transitions are different than jQuery.animate.
Here's a good intro on the matter.
https://www.webkit.org/blog/138/
So, first let's recognize that we can't do the same things anymore
if (!Modernizr.csstransitions || Modernizr.csstransforms3d) {
// use some css
} else {
// use some jQuery
}
Now, let's fill in with your example
if (!Modernizr.csstransitions || !Modernizr.csstransforms3d) {
// Old jQuery version
$('.rightbox3d').animate({
opacity: 1,
top: "-200px",
width: 2 * $('.rightbox3d').width(),
height: 2 * $('.rightbox3d').height()
}, 4000);
} else {
// Modern cool version
// The transform is moving/rotating/stretching we want to do
// The transition is the animation we want
$('.rightbox3d').css({
opacity: 1,
transform: 'translateY(-200px) scale(2)',
transition: 'all 4000ms ease-in-out'
});
}
I think that should clear it up for you. :)

Related

Different behavior of transition when launched via event listener vs direct function call [duplicate]

I'm having some major headache trying to apply CSS3 transitions to a slideshow trough JavaScript.
Basically the JavaScript gets all of the slides in the slideshow and applies CSS classes to the correct elements to give a nice animated effect, if there is no CSS3 transitions support it will just apply the styles without a transition.
Now, my 'little' problem. All works as expected, all slides get the correct styles, the code runs without bugs (so far). But the specified transitions do not work, even though the correct styles where applied. Also, styles and transitions work when I apply them myself trough the inspector.
Since I couldn't find a logical explanation myself I thought someone here could answer it, pretty please?
I've put together a little example of what the code is right now: http://g2f.nl/38rvma
Or use JSfiddle (no images): http://jsfiddle.net/5RgGV/1/
To make transition work, three things have to happen.
the element has to have the property explicitly defined, in this case: opacity: 0;
the element must have the transition defined: transition: opacity 2s;
the new property must be set: opacity: 1
If you are assigning 1 and 2 dynamically, like you are in your example, there needs to be a delay before 3 so the browser can process the request. The reason it works when you are debugging it is that you are creating this delay by stepping through it, giving the browser time to process. Give a delay to assigning .target-fadein:
window.setTimeout(function() {
slides[targetIndex].className += " target-fadein";
}, 100);
Or put .target-fadein-begin into your HTML directly so it's parsed on load and will be ready for the transition.
Adding transition to an element is not what triggers the animation, changing the property does.
// Works
document.getElementById('fade1').className += ' fade-in'
// Doesn't work
document.getElementById('fade2').className = 'fadeable'
document.getElementById('fade2').className += ' fade-in'
// Works
document.getElementById('fade3').className = 'fadeable'
window.setTimeout(function() {
document.getElementById('fade3').className += ' fade-in'
}, 50)
.fadeable {
opacity: 0;
}
.fade-in {
opacity: 1;
transition: opacity 2s;
}
<div id="fade1" class="fadeable">fade 1 - works</div>
<div id="fade2">fade 2 - doesn't work</div>
<div id="fade3">fade 3 - works</div>
Trick the layout engine!
function finalizeAndCleanUp (event) {
if (event.propertyName == 'opacity') {
this.style.opacity = '0'
this.removeEventListener('transitionend', finalizeAndCleanUp)
}
}
element.style.transition = 'opacity 1s'
element.style.opacity = '0'
element.addEventListener('transitionend', finalizeAndCleanUp)
// next line's important but there's no need to store the value
element.offsetHeight
element.style.opacity = '1'
As already mentioned, transitions work by interpolating from state A to state B. If your script makes changes in the same function, layout engine cannot separate where state A ends and B begins. Unless you give it a hint.
Since there is no official way to make the hint, you must rely on side effects of some functions. In this case .offsetHeight getter which implicitly makes the layout engine to stop, evaluate and calculate all properties that are set, and return a value. Typically, this should be avoided for performance implications, but in our case this is exactly what's needed: state consolidation.
Cleanup code added for completeness.
Some people have asked about why there is a delay. The standard wants to allow multiple transitions, known as a style change event, to happen at once (such as an element fading in at the same time it rotates into view). Unfortunately it does not define an explicit way to group which transitions you want to occur at the same time. Instead it lets the browsers arbitrarily choose which transitions occur at the same time by how far apart they are called. Most browsers seem to use their refresh rate to define this time.
Here is the standard if you want more details:
http://dev.w3.org/csswg/css-transitions/#starting

WinJS enterPage animation not working as expected

I wanted to add animations to my app on page enter, and hooked with the default WinJS.UI.Animation.enterPage(element), and that worked fine sliding in the element from right to left.
I need to slide it from bottom (100px) to top. Once I overrode the default values with WinJS.UI.Animation.enterPage(element, { top: "100px", left: "0px" }) I saw no animation at all on my screen which is weird.
However when coupled with WinJS.UI.Animation.exitPage(oldElement), the animation seemed to work but I wanted to further tweak the timing.
following as per https://msdn.microsoft.com/en-us/library/windows/apps/Dn127042(v=win.10).aspx#creating_custom_animations, didn't help. After using the example from "Combining custom animations and transitions" in the link, I could see only the opacity changing and the element fading in, however no translation at all. I tried the same pairing with WinJS.UI.Animation.exitPage(), and adding my own customExitPage - basically using from WinJS, and with just opacity... and nothing just works.
I was referring to some of the animation implementations from here as well -
https://github.com/winjs/winjs/blob/ad8691b3d5227ff1576a5d2a90a42f022498d2a9/src/js/WinJS/Animations.js, to get control over the timing.
Anyone else having this issue? or am I doing something wrong... or is it WinJS behaving bad?
EDIT:
weirdly enough the "to top" animation with enterPage(element, {top: "100px", left: "0px"}) started working. However the custom animation still remains elusive.
well, I was able to finally figure out the "weird behavior". The #keyframes should have been set in CSS, and I was trying a few other things and apparently that's the reason that it didn't work.
However, I would probably say the explanation could have been a little more clearer in the site as well.
when we are already providing the from - to values in the javascript, I would otherwise about providing the same again as part of CSS too which is still weird.
Like mentioned in the site,
add this to css: #keyframes custom-translate-in { from { transform: translateY(50px); } to { transform: none; } }
and have this in js:
function runCustomShowStoryboard() {
return WinJS.UI.executeAnimation(
target,
{
keyframe: "custom-translate-in",
property: "transform",
delay: 0,
duration: 367,
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)",
from: "translate(50px)",
to: "none"
});
}
Never was able to figure out why and how the "bottom to top" animation started working (probably restarting visual studio helped)

Successive background-color animation request failing with jQuery 1.6.1

I'm trying to "flash" an input box by changing the background color briefly and then reverting back to the original bg color using jquery to indicate an error and grab the users attention.
Here's a fiddle to demonstrate what I'm trying to do.
I have to use jquery version 1.6.1. In the fiddle demo, it's using 1.6.4 and the color of the input box never changes at all. Actually, it doesn't work even with 1.11. In my local tests with my code, the input box changes red with the first animation call, but fails to do anything for the second animation call (to revert the bg color back to white). It just stays red.
I'm using very similar code to do the same thing in another site, except using jquery 1.11 and it works fine.
Is this just a compatibility issue? Is there some way I can make this work properly with version 1.6.1 ?
Here's the code:
function flashInputBox(id) {
var input = $('#'+id);
input.focus();
input.stop(true).animate({'background-color': '#EC8686'}, 350, function() {
input.stop(true).animate({'background-color': '#FFFFFF'}, 1000);
});
}
I forgot to mention that I'm using jQuery UI v1.8.18
The problem is properly replicated now in this fiddle (same code, just added jQuery UI 1.8.18).
Do you need to use jQuery? If not, this is way easier in CSS using key frames. If it is, skip my CSS explanation.
CSS
This still uses jQuery, but it gives the animation job to CSS, making your code more legible. I set this up in jsFiddle if you want to check it out: jsFiddle Example
First, setup a keyframe:
#keyframes pulse{
from {
background: #ec8686;
}
to {
background: #ffffff;
}
}
#-webkit-keyframes pulse{
from {
background: #ffffff;
}
to {
background: #ec8686;
}
}
and attach it to your existing input:
#my-input{
...
-webkit-animation: pulse 5s infinite;
-webkit-animation-play-state: paused;
...
}
Then the jQuery becomes a matter of letting the animation play for a few seconds:
function doIt() {
$("#my-input").css("-webkit-animation-play-state", "running");
setTimeout(function() {
$("#my-input").css("-webkit-animation-play-state", "paused");
}, 5000);
}
Also, you don't even need the jQuery to trigger the animation. The button click can directly trigger a CSS animation, however I figured you have some sort of code to check what's in the box for accuracy, so that why I kept your old function.
Note that this keyframe ends suddenly, so you can totally have a 0%, 50%, 100% keyframe instead.
Now for the raw jQuery way:
jQuery
For your jQuery, its much easier just to either specify your input directly (aka $("#my-input-name")), or if its just one input, I got it working just by using the following code instead:
function doIt() {
...
input.stop().animate({'background-color': '#EC8686'}, 350, function() {
// just say input here //
input.animate({'background-color': '#FFFFFF'}, 1000);
});
}
Colors aren't numeric values, so they can't be animated. From the jQuery documentation for .animate, emphasis mine:
All animated properties should be animated to a single numeric value, except as noted below; most properties that are non-numeric cannot be animated using basic jQuery functionality (For example, width, height, or left can be animated but background-color cannot be, unless the jQuery.Color() plugin is used). Property values are treated as a number of pixels unless otherwise specified. The units em and % can be specified where applicable.
If you don't want to (or can't) use the jQuery.Color plugin, you'll need to animate the color "manually", e.g. by setting an interval and changing the color at each step.

(js) moving div x pixels smoothly with jquery or similar?

I have an image that when clicked should move a div up ~200px, I have it set through jquery to modify css without isssue but it doesn't look as 'clean' or smooth as i've seen on other websites.
Forgive me but i've been searching for a few hours and can't find the function/method to do this, I figured fadein/out would do this but i'm fairly sure it cannot.
Could anyone take a moment to point me in the right direction? Thank-you.
EDIT: After writing this I thought maybe I should quickly incrementally change the css via jquery to simulate a low-fps 'glide' .. hopefully there is an easier way
EDIT2: Currently use this, looking for a way to do it 'smoothly' if that even makes sense
$('#Table_Topbar').hide();
var pix = "px";
var fix = $('#Table_Middle1').css('top');
var fix2 = fix.replace('px','');
var fixsub = (fix2 - 200);
var fixstring = fixsub.toString();
var fixconca = fixstring.concat(pix);
$('#Table_Middle1').css('top',fixconca);
If you want to do this using only Javascript, you could also simply use an interval to update the css every xx number of milliseconds, for 60fps you'd use 16. (This is not the best way)
var i = parseInt($("#Table_Middle1").css("top"));
var animationLoop = setInterval(function() { i += 10; $("#Table_Middle1").css("top", i + "px"); }, 16);
A simpler way would be to use jQuery's animate api: http://api.jquery.com/animate/. (this is the most cross-browser friendly way)
$('#Table_Middle1").animate({top: "-=200px"}, 1000); // take 1 second to move up 200px
You could also use a CSS3 transition to accomplish the same thing, and reduce your JS to a simple class toggle (This is the most "modern" way)
jQuery:
$('#Table_Middle1").addClass("class-to-trigger-animation");
css:
#Table_Middle1 { top: 500px; transition: top 1s ease; }
#Table_Middle1.class-to-trigger-animation { top: 300px }
If you want more complex animations, you could consider a library like Greensock.
You could use a combination of js (jQuery) and CSS here, eg.
CSS:
.switch {position: absolute; top: 0; left: 0; transition: top 1s}
.switch.active {top: 160px}
jQuery:
$('.switch').click(function(){
$(this).toggleClass('active');
});
Check out the fiddle here: http://jsfiddle.net/pavkr/Lu7q2c1r/1/
You would need to adjust the parameters however, this is just a quick example.

KineticJS animation with JQuery

I am new in KineticJS and I am stacked. I want to use a simple animation with opacity but I found out that there is not so "simple" as it seems. I read the doc about animations with KineticJS (you won't say simple about this tutorial). What I want to know Is there a simple method to animate things with KineticJS like JQuery or JCanvaScript has? for example
this.animate({
opacity:0,
x: 50
}, 500);
something like this?
If there is not can we use KineticJS with JQuery to make animations simple? I found out THIS project that has very interesting piece of code:
$(logo.getCanvas()).animate({
opacity: 1,
top: "+=50px"
}, 1000);
so guys what do you think? Is it buggy to use this method?
If you just have to do your opacity animation : you should stick to JQuery which will hide the computations done for the animation (and what you were pointed to is a good solution).
If you want more controls over your animation : go with KineticJS.
Through, I think you will have more issues trying to use JQuery animations and KineticJS layers at the same time rather than using only KineticJS (and Kinetic.Animation is pretty simple once you have understand how to play with it)
edit: Quick How-To for animations :
So, as you may have seen, in Kinetic, you do not give the final position like in JQuery : you have an access to a function which is called at each frame of the animation and all the logic have to be placed in it :
<script>
// you should have an object yourShape containing your KineticJS object.
var duration = 1000 ; // we set it to last 1s
var anim = new Kinetic.Animation({
func: function(frame) {
if (frame.time >= duration) {
anim.stop() ;
} else {
yourShape.setOpacity(frame.time / duration) ;
}
},
node: layer
});
anim.start();
</script>

Categories