Slow jQuery animation on iPad2 - javascript

I'm currently building iPad-optimised website. I have some chunks of text that I should show/hide when user touches appropriate button. The text is inside of < p> tag. I use jQuery for toggling the visibility of the text:
$("my selector").toggle("fast");
But it is really choppy ... Is there some iOS specific way to do the animation, maybe another framework or something else ?
I don't think it should be that slow ...

There are several animation scripts that targets iOS, but the basics are that you should use CSS animations instead, and more specifically the translate3d property (for positioning) that triggers the iOS hardware.
For toggling opacity, you can use a regular -webkit-transition and toggleClass, f.ex:
p { -webkit-transition: opacity 0.2s linear; opacity:1 }
p.hide { opacity:0 }
and then:
$("my selector").toggleClass('hide');
I made a simple demo for you here: http://jsfiddle.net/rQFZd/
You can detect touch devices and serve css animation specifically to those that supports (and prefers) it.
EDIT: example of animating height: http://jsfiddle.net/rQFZd/1/. I’m not sure about iOS performance though, but I think it should be better than jQuery.
You can also add another container and then use translate3d to reposition the element instead of shrinking it, that should most certainly be smoother on iOS. Example: http://jsfiddle.net/rQFZd/2/

Related

Is there a fluid CSS height property for elements entering the DOM? Jank happens when using Semantic-UI-React Transitions

I am not sure if this is the proper place to ask this question; I considered Software Recommendations however I figured I'd give it a shot here first.
I am creating a PWA and with every iteration I'd really like to focus on making it look/feel like less janky and as smooth as possible. Well, like a native app.
So here is the problem—I am using transitions (animations) provided by Semantic-UI-React, and while it works beautifully when an element which is occupying its on space, I was wondering if there a practice or pattern which handles the behavior of adjacent DOM elements to one that is being animated?
I supplied a GIF below to illustrate what I mean. I suppose I could just move the animated elements out of the container of the form to prevent jank, but I wondered if there was a more elegant pattern or approach to this...
Merci!
Unfortunately, there is no particularly elegant approach to this.
Regarding the question in the title of your post, a common approach is to animate the height of the new elements. If you don't know the height of the elements, unfortunately animating from 0px to auto does not yet work but you can fudge it by animating max-height from 0px to a value slightly larger than the maximum size you expect the element to be.
But don't do that.
It will cause the browser to layout the page on every animation frame and will almost certainly jank on lower-end devices.
Instead, you're better off to animate transform.
The most common approach is to:
Grab the original position of the elements (using getBoundingClientRect() etc.) that are going to be affected just before you add the new elements to the DOM (perhaps using getSnapshotBeforeUpdate unless you're using hooks, in which case you can use useRef to similar effect).
After you've added the new elements (which you're presumably also animating in by using transform with a suitable scale() function), calculate the delta from where the offset elements are now, compared to where they used to be.
Setup a transform animation from the negative of the delta, to zero (i.e. the FLIP approach). E.g. if the element has been shifted 300px down the page, animate transform from translateY(-300px) to none.
Of course you need to do that for all the elements in the flow that are affected so it might be easiest to put them all in one container and just animate that.
Regarding the third point you have a few choices of technology, none of which are great:
CSS transitions. These are simplest but you'll have to trigger a style flush to get the negative delta starting point to stick. e.g.
elem.style.transform = `translateY(-${offset}px)`;
elem.style.transition = `transform .3s`;
getComputedStyle(elem).transform; // Flush style
elem.style.transform = `none`;
CSS animations. Producing #keyframes rules dynamically using the CSSOM is a pain but at least you don't need to trigger a style flush (and you can set an animation with an implicit to-keyframe for convenience).
#keyframes random-id { from: { translateY(-300px); } }
Web animations. This is probably the most well-suited.
elem.animate({ transform: [ `translateY(-${offset}px)`, 'none' ] }, 300);
// In future when browsers ship support for implicit to/from keyframes:
elem.animate({ transform: `translateY(-${offset}px)`, offset: 0 }, 300);
Unfortunately Safari only has Web Animations support in Tech Preview so Safari users will get the un-animated version until the next Safari release. Edge users will also get the un-animated version until the Chromium based Edge ships. There is a polyfill too but it's not actively maintained at this point in time.
If you're using React, Animating the Unanimatable is a helpful article on all this.
The other tricky part is making sure the scroll doesn't jump for which you might need to look into scroll anchoring.

Jerky animations - Jquery / CSS3

I am trying to combine jQuery and CSS3 to give smooth animations, but I am still finding the animations can be jerky, even on desktop.
I am using the below to move my id from off the side of the page onto the page.
$(id).addClass('active').css({ left: pageWidth })
.animate({left: 0}, 500, function(e){deferred.resolve()})
.css("-webkit-transform", "translate3d(0px,0px,0px)")
.css("-moz-transform", "translate3d(0px,0px,0px)")
.css("-ms-transform", "translate3d(0px,0px,0px)")
.css("-o-transform", "translate3d(0px,0px,0px)")
.css("transform", "translate3d(0px,0px,0px)");
Can anyone give any advice if there is anything further I can do?
Use a plugin/extension like velocity to automatically use CSS animation for you behind the scenes.
We recently used it to avoid stuttering of animations on mobile devices and it improved things a lot.
If you want smoother animations and you can use CSS3 with no restrictions then you can make use of CSS3 Keyframes.
Take a look at this CSS3 animation collection called Animate.css:
http://daneden.github.io/animate.css/
This makes use of CSS3 Keyframes that runs really smooth. You can edit the animations or create new ones depending on what you want to acomplish. With Keyframes you can set the state of the animation at any frame of it so you can make it look as smooth as you want depending on how you build it.
Take a look at this article about Keyframes and if you don't want to use the ones on Animate.css try to modify them or build your own:
http://css-tricks.com/snippets/css/keyframe-animation-syntax/
For the animmation you want to get the code is not that hard. You can do this with jQuery animate as well but Keyframes will runs smoother if you work better on the frames.

How to animate DOM elements with JavaScript/CSS

I'm working on a chess game with some strategic visual overlays. One of them requires some light animation of pieces and squares, specifically, a slow and steady pulsing. My board is a with each being a single square. Pieces are shown by setting the background-image in CSS to an .svg of the piece it contains.
Can this be done in CSS? I'm using the latest browsers with no support for legacies, so I can use all the nifty CSS3 stuff. Another option I was thinking was to set the background-image of the board to an animated .gif of the piece pulsing. Would this work?
Are there any other ways to do this I haven't mentioned? I would like to avoid packages/frameworks, but I am using jQuery.
CLARIFICATION:
I want to make the chess piece kind of pulse (flash?) in place slowly for emphasis. I want it to be a slow, subtle, and consistent pulse that persists until another event turns it off.
It sounds like you're looking for CSS animations.
Take a look here: http://www.w3.org/TR/css3-animations
In particular you'll need the following timing functions:
animation-name, to specify the set of keyframes to use.
animation-duration, to specify the speed of the animation.
animation-iteration-count, to repeat the animation.
animation-direction, to alternate the direction of the animation.
And you'll need to create some keyframes, which let you specify what CSS properties are modified by the animation.
Also, you'll need vendor prefixes on everything, so you need to write -webkit-animation-name rather than animation-name (for example), and repeat everything for -moz and other vendors.
Here's an example for webkit that creates a pulsating opacity effect. You can experiment with the properties in the from and to sections to animate size, color, etc.
.chess-piece {
-webkit-animation-duration: 1s;
-webkit-animation-name: pulse;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
}
#-webkit-keyframes pulse {
from {
opacity: 0.5;
}
to {
opacity: 1;
}
}
JSFiddle example for webkit and moz
That is quite possible and easy to do. As I understand it, you want to make some kind of glowing animation of the active chess figure?
Here's how I would go implementing a solution: Create 2 pngs, one with the chess figure in its unflashy ordinary state and one with its fully illuminated state. Then use jQuery to change the opacity of the illuminated state from 0 to 100 and back to 0 again.You can send the jQuery "on animation finish" signals to achieve this. You can than just use some kind of simplified observer pattern to cancel the effect once an event occurs.

Why image opacity animation runs smooth in Firefox and Chrome but not Safari?

I have a few sibling images that are absolutely positioned at top:0 and left:0 relative to their parent div. By default, the last image is on top. I am using jQuery to fade the images one at a time by animating to opacity:0 starting with the upper most image "the last image in the parent div". For some reason the animation looks smooth in firefox and chrome, but not safari? What are some reasons why this might be happening? Thanks in advance.
Are you sure it is the animations fault? I have had a case where using box-shadow:inset... and -webkit-box-shadow:inset... caused safari to lag. If you CAN isolate it to jQuery, then I'm not sure what's going on. Do you use cycle?
I don't know off hand how jQuery handles opacity in Safari. If it's not using the webkit CSS properties, then that could be the reason. The webkit CSS properties for opacity are going to perform better.

Animating opacity, opacity in general in IE

When IE renders a filter: alpha(opacity=..) whether it's on an image or text. It looks bad.
Is there a way to make IE render normal-browser-like smooth opacity?
If no, how can I easily after a fadeIn (opacity x->1) javascript animation re-render the elements so it doesn't look bad anymore..?
Applying a background colour or an opaque background image to the element should fix this problem. This is due to the way filters work, they're ActiveX components and they're old so they have certain limitations when working with partial transparency.
You can also disable the filter when the animation has completed, using something like:
myElement.filters[0].enabled = false;
A lot of animation libraries use this technique to enable the filter only during the fading so the user will not notice the ugly aliasing as much.
There's another fix (best viewed in IE to understand the point of the post), although it's more of a hack and it's not a good solution in all cases, particularly where you need to alter the size of the image.

Categories