Composing CSS animations with transforms - css

I want to compose two separate CSS keyframe animations to make an image vibrate and rotate (see http://jsfiddle.net/3zAeZ/). The problem I believe I'm running into is: I'm setting the transform attribute in both keyframe rules, therefore one rule is clobbering the other.
I know this works using top & left instead of translate, but the keyframes rule will be much easier to reuse in the future if I do a transform (for example, in case I ever need to position the image differently).
I'm stumped. Can I do this? Is there a better way I should be doing it?

You can use multiple transforms like
transform: rotate(1337deg) scale(1.5) translate(6em, 300px);
Now I realize that you need two different animation durations as well.
So the best I can come up with is using two elements http://jsfiddle.net/3zAeZ/1/

Related

Using `calc()` vs `transform` when placing elements

Is there a reason one would want to use calc() over the transform property when placing an element, or vise versa, when the size of the element is known?
For example...
.element {
bottom: 100%;
transform: translateY(-9px);
}
Produces the same results as:
.element {
bottom: calc(100% + 9px);
}
If the size of the element is not known, I see the advantage of using transform. However, if the size is known (as above) I can just as easily use calc() to adjust.
"calc() uses just one line, while transform requires two lines"
Fair enough. But (in my case) I'm already using transform to adjust along the other axis (because I don't know the initial size), so I could easily combine the translateY() and translateX() to actually reduce the number of lines.
"Because browser support"
Assume we have full browser support across both solutions.
Is there a standard, or performance situation, that would suggest one solution is better than the other?
transform is a monster capable of doing much more powerful things than simple translations.
Therefore, it has some collateral effects like establishing a containing block for its descendants, even if they are in a fixed position!
Therefore, as a rule of thumb, when you only want simple translations, I would recommend to avoid transform. I prefer calc(), margins, etc.
Transforms can be affected by other transforms, which may cause a difference in rendering. For example, if you were using the perspective transform, translateY() would take place inside that perspective. So, the perspective would be applied, and then the element would be transformed according to the vanishing point you set.
If you were using calc(), instead, the element would be positioned on the page irrespective of the set perspective. It’s probably a subtle difference, but it’s there.
If you’re not using a 3D transform like perspective, however, or if translate() is the only transform you’re using, I don’t think there’s a difference.

How can I animate infinite marker movement down an SVG path without very high CPU usage?

I wish to implement flow indicators on the links of my D3 graph, as in this block.
The block uses stroke-dashoffset keyframe CSS animation to achieve the flow, and while it looks good, CPU usage sits at almost 100.
I read that you can trick some browsers into triggering GPU acceleration by including certain CSS properties, but other sources indicated that this no longer works, and certainly I couldn't see any benefit when trying to add transform: translateZ(0); (for example).
I have been investigating other options, and I tried to implement a moving marker along a line, in this style. For only one marker performance is better, but when I added multiple performance was worse.
Is there another, more performant option for animating a marker down an SVG path?
Failing another approach, I will try adding controls to stop / start the animation, but that would be a last resort.
Thanks in advance!
It seems indeed that animating the stroke-dashoffset attribute causes a lot of calculations. The original example causes a CPU usage at around 50% when I open it in Firefox.
There's another approach that seems to give better results: manually increment the stroke-dashoffset and loop that using setInterval. Here's a proof of concept:
http://bl.ocks.org/kmandov/raw/a87de2dd49a21be9f95c/
Here's how I update the dashoffset:
var lines = d3.selectAll('.flowline');
var offset = 1;
setInterval(function() {
lines.style('stroke-dashoffset', offset);
offset += 1;
}, 50);
I know that it doesn't look very good but it (surprisingly) performs a lot better than relying on css animations or transitions. In Firefox I now get CPU usage at about 15%.
I can imagine that this approach won't perform very well if you have a lot of links, because the update will take too long. But maybe it's a viable hack for simpler use cases where you animate linearly a fixed amount of links.

Separate png vs transition:opacity for :hover state - which is better (efficiency)?

I'm having several buttons that I want to get darker when user hovers over. Which method is better (faster, more efficient, more safe in terms of browser compatibility):
Create 2 separate .png images, one normal one _hover
Use transition:opacity css property.
Images are small, each approx. 600 bytes big (20x20 pxl), but having approximately 30 of them makes me wonder which method is better in terms of speed efficiency and older browsers support (but not to the point trying to please IE6 either)
if opacity is doing your job of darkening the image- Use it.
You said darkening image? so i assume u start with lower opacity value and chage to something higher.opacity is more like transparency of the pic-dosent darken it.
If opacity is not giving the desired results you can use hover change of image-use image sprites this way you dont have to request for 60 svg's(30 svgs considering you use a combination of 2 pics instead of one)
LINK for sprites.
I suggest using SVG filter gives you better image effects-Browser support

Is there a way to use CSS -transform and not affect children elements

I created a mockup to demonstrate my problem. I fear the solution falls in what I did with the first example (box1).
Just not sure why I can't apply a css transform to a parent element and avoid applying it to the child element or at least override it.
Let me know if there is a way to get the effect of the first example using the transform property. I don't want the second image to be scaled as well. Just the parent div.
Note
I'm trying to use this property to enable GPU acceleration.
Have not played with this in any other browser but the chrome.
But it looks like overflow hidden set on parent element implies resizing inheritance on image.
So if you set overflow auto on the boxes to which animation is applied, it should fix the resizing inheritance.
http://jsfiddle.net/gnrlbzik/5Q8EC/ tests the overflow set to auto, that keeps image dimensions in tact.
To be semantic I don't think you should be able to stop it from transforming a child element being you are transforming/scaling it's container, not resizing it. A transform is not just animating the width like the example on box 1, it scales the x.
I believe this question is about trying to gain some performance boost by using features that use the GPU to process animations. This is possible, I believe, by effectively treating the elements as an image that the GPU then animates. Thus you are not able to have an element inside that dynamically keeps its size/shape during an animation. Maybe there is a way to counter the animation by transforming the element within that you would like to keep static, but this will probably not be efficient nor effective.
Note: I am not well versed in the actual technology webkit uses to render these transformations. So sorry if the finer details of the rendering are not quite accurate. I will update this if anyone comments with a better description of how transform works.
I wanted to use -transform to get the GPU performance perk. I guess I'll continue to use the width animation: http://jsfiddle.net/Vyaf3/22/ but with applying a css3 property that would enable the GPU acceleration.

Is there a proper way to dynamically update parts of transforms and transitions programmatically? e.g. transform-origin or duration

I am building an iOS Safari touch-based app and find CSS transitions and transforms work great.
But I have two things I can't seem to achieve using just JavaScript and CSS.
Usually I want the element to translate with a duration of 0.2s. But in code I occasionally want to instantly translate (initial positioning). If I update the duration to 0 or remove the transition style entirely, it doesn't seem to have an effect (acts as if the 0.2s is immutable)
When zooming I want to update the transform-origin property. This also does not seem to work, and seems stuck at my original stylesheet-set value. Specifically I am trying to do this on the gesturestart and gestureend events
Hopefully there is an approach to making this work. Maybe setTimeout async processing?
Update:
I have a js fiddle example to better illustrate my problem in #1, and it turns out that setTimeout fixes it, but it's a strange solution that I'd be interested in improving:
http://jsfiddle.net/w9E7t/
It seems like I'm unable to do these steps synchronously:
set appropriate classes for an instant transition
apply transition style
reset classes to their default (with transition) state
You can accomplish this by using two CSS classes, one which sets the timing-duration to 0s and the other which sets it to 200ms and then applying the classes programmatically in JS. Take a look at this JSFiddle for an example.
One of Web development's best practices is to separate your document's parts into structure/content (HTML), presentation (CSS), and interaction/behavior (JS). In the example above, the presentation of the content (a timed translation) stays defined in CSS while JS is used only to respond to an interaction (a MouseClick event).
You should be able to change an element's transform-origin using the WebkitTransformOrigin style property in JS. Here is an example JSFiddle. I tested this on my iPhone4 and it correctly logged the new transform-origins in the console. Again, this can also be achieved by using JS only to listen for the gesture events and updating the element's class, while keeping the style rules of the class defined in your presentation logic (CSS).
Note well: In my examples, I am updating the element's .className. Since it is possible that your elements already have many classes, you may need to implement addClass/removeClass functions to properly set the correct classes, several examples of which can found on the Web.
Update:
Sorry for the delay... There are two ways you can approach this problem and the first you have already discovered.
Another way to handle switching back the class name is to use the webkitTransitionEnd property. This fires whenever a transition on the element finishes. It would look like this:
document.getElementById('puck').addEventListener('webkitTransitionEnd', function() {
puck
.removeClass('without_transition')
.addClass('with_transition')
}, false);
Unfortunately, when the transition-duration property is set to 0, this event is not fired :( I'm not sure if that is by design or a bug, but that's just how it's currently implemented (though I'm guessing it's by design since at this point the browser is not really doing a transition but rather just applying the transformation). The workaround in this approach is to set the transition-duration to 1ms (which will essentially look instant).
While the setTimeout approach looks hackish, many mobile framework groups use it throughout their code since the function will fire after the transition that occurs from switching classes (similar to transitionEnd). Take a look at Sencha Touch and you will find it numerous times.
I've forked your JSfiddle to show my example here.

Resources