Posts Tagged ‘ART’

Convert a SVG Path to CSS Animation Keyframes

Monday, September 12th, 2011 by Sebastian Markbåge

Click Here to Test The Tool

It’s not easy to generate keyframes for CSS3 AnimationsThis new CSS Path Animation tool can help you convert SVG paths into CSS keyframes.

SVG

Using SVG you can use the animateMotion element to move and rotate content following along a complex curved path. However, some vendors have turned away from SVG for animation and prefer CSS as the way to do animations. For HTML content it tends to be very invasive. Using SVG with foreign objects tend to be poorly implemented as well.

JavaScript

Most JavaScript frameworks for vector graphics (including ART) can do the same thing with JavaScript animations.

Some people think that CSS animations inherently provide better performance than JavaScript animations. This is not strictly true. It is the hardware compositing step that’s the important part. You can use JavaScript animations together with requestAnimationFrame and 3D transforms to trigger hardware compositing. You get the same level of performance as with CSS.

However, this won’t work in JavaScript-free environments, such as some banner ad sandboxes. CSS animations provide a nice separation of concerns and easy of use.

NOTE: If available, JavaScript is the preferred way to do this kind of animation efficiently. In a later post, I’ll show you how to do this with ART.

Another aspect is that the JavaScript to run this animation can be very small.

CSS

If you prefer CSS Animations, how do you create the keyframes to animate an object along a complex path?

If you only have straight lines, it is easy. Just apply a CSS Transform to the X and Y coordinates of each point along the path. The rotation can be adjusted based on the angle of the line if you need it.

CSS Curve Animation

Things get much more complicated when you consider smooth curved paths. I.e. bezier curves or arcs.

The typical way to handle curves, is to subdivide them into very small straight line segments. However, if you generate this many CSS keyframes, the document would be huge. That’s not an option. We need a better technique.

The Arc Rotation Technique

For arcs, you can adjust the transform origin and rotate the element around the arc’s center point. This is the optimal technique for simple arcs such as circles and ellipses. You can approximate bezier curves using several arc segments. This can generate very small files for simple curves, or very big files for complex curves. This means it’s unreliable for an automated conversion tool.

If you want to avoid rotating the element and only move along a path, then you need an additional nested element to counter act the rotation.

The Timing Function Technique

A future new best friend of mine pointed out to me that you can animate the X and Y axis using different easing functions. That way the timing will cause the animation to be a smooth curve. The CSS animation standard specifies a timing function based on a cubic bezier. This gives us a lot of flexibility to define an easing function.

The trick is in defining the timing function used. A simple implementation would specify bezier curve control points on the second and forth argument to the timing function, leaving the first and third argument at 0 and 1 respectively. This gives a perfect motion along the path. Unfortunately, it doesn’t move at a constant speed.

To get the animation to move across the curve at a constant speed we have to use a little black magic math to approximate the motion at constant speed.

Not all curves can be animated using this technique due to limitations placed on the timing function. If a complex curve is found, we split it into two, until we have curves that can be animated this way. This provides us with a generic technique that can be used reasonably well for any path.

Hardware Acceleration

The arc technique uses a single CSS transform and is therefore easily hardware accelerated.

The timing function technique, requires different easing functions for each axis. That means that each axis needs it’s own animation.

Luckily we can apply multiple animations on a single element by animating the “left” and “top” properties independently. This is simple to use and non-invasive. However, this doesn’t currently provide the hardware compositing with sub-pixel accuracy, like the “transform” property does.

Unfortunately, we can’t animate each axis of a transform independently. The way to solve this is to use three nested elements and apply one transform for each element. This is a bit more invasive but provides the best visuals.

(UPDATE: The IE10 preview has a bug in nested transforms. At least in software mode. The previous method works well though and it’s hardware accelerated in IE. If the bug remains, I’ll update the converter to take this into account.)

Conclusion

In the conversion tool I use the timing function technique with three nested elements. This gives us a generic solution that is also hardware accelerated in current Webkit and Mozilla browsers.

The resulting CSS is very bloated. GZIP:ing does a lot to the size but it’s still fairly big. There are a few action points browser vendors and W3C people could do to help:

1) Hardware accelerate left/top absolute positioning with sub-pixel precision. IE9 did this from the start. This is where the full(er) hardware pipeline of IE9 shines. This would allow us to use a single element for this hack.

2) Drop vendor prefixes on specs that are far along. CSS keyframes can be very bloated and they have to be multiplied in full for each vendor.

3) Standardize something like SVG’s animateMotion, but for CSS. SVG isn’t less verbose but there’s a specialized element to handle this scenario. This same hack would be even more bloated in SVG.

A CSS rule could be used to name a SVG-style path. This name can then be referenced by the “animation-name” property to apply a transform to an element along a path. The current hack can be used to provide backward compatibility.

#target {
  animation: myMotion 1s infinite;
}
 
@motion myMotion {
  path: 'm0,0 l100,100 ...';
}

I think I’ll prototype something like this for LESS.js.

UPDATE:
I’ve started a discussion about standardizing this pattern on the www-style mailing list.

The current idea is to add a “motion” property that’s valid only within the context of keyframes.

#target {
  animation: myMotion 1s infinite;
}
 
@keyframes myMotion {
  0% {
    motion: m0,0 l100,100 ...;
  }
  50% {
    motion: M100,100 L0,0 ...;
  }
}

WebGL – Not just for 3D

Thursday, November 18th, 2010 by Sebastian Markbåge

UPDATED: The demos are now updated to work around some bugs in the ANGLE implementation currently in Chrome 9 beta and Firefox 4 beta 8.

Those of you who are following me on Twitter know that I’ve been really getting into WebGL lately. Basically it’s 1:1 JavaScript bindings to OpenGL ES 2.0 including GLSL (OpenGL Shading Language). This will allow you to access the power of GPU hardware directly in your website.

Safari, Chrome and Firefox all have WebGL enabled in their latest betas/nightly builds. Opera is on the working group as well. Additionally modern iOS and Android devices have OpenGL ES support so mobile support is probably not far away. Firefox already has WebGL support on Maemo.

Microsoft is not yet on board

While Microsoft is constantly bragging about the fully hardware accelerated rendering in IE9 using DirectX. They’re the only one of the major players not yet in the WebGL working group. WebGL is supposedly designed so that it can be implemented on top of DirectX. This allows for stronger implementations on Windows where OpenGL support is poor. Mozilla and Google are already doing this in their implementations.

Microsoft obviously have a lot invested in DirectX and may not want to support an API so close to the competing OpenGL. However, given their recent effort to support standards I’m hopeful they’ll get on board for IE 10.

Fallbacks

Given that no browser supports WebGL yet, other than in beta versions. We will obviously need some fallback.

Mr. Doob is doing some great progress on a 3D API with Canvas 2D and SVG fallback support – called three.js. However, I think this will be of limited use in most real-world scenarios.

For any proper 3D beyond gimmicks you’ll want to use hardware acceleration. The exception being data visualization.

Flash and Silverlight already have pixel shader support. This doesn’t help 3D much but they do help for 2D special effects etc. Although these are not hardware accelerated, they can run multi-core and they’re faster than anything you can do with 2D canvas.

Additionally Adobe has announced hardware accelerated 3D support through the Molehill APIs. I’m sure Microsoft is not far behind with Silverlight. Once these get out to IE users, we’ll have direct hardware capabilities on all the major platforms.

Abstractions

WebGL is a horrible looking API. It’s intentionally a direct translation of the C interface. The intension is that people will provide abstractions on top of it. E.g. a general game engine or a data visualization API built on top of it.

Some have tried to make thin wrappers around it. Like MooTools or jQuery wraps the DOM in a thin API abstraction. I think that is a mistake. You really need to optimize for performance and to do that you need a higher level abstraction that works directly to the WebGL API.

I have no intension of making a thin GL wrapper nor a single generic 3D API. Although…

It’s not just for 3D

Those of you following me on GitHub know that I’ve been doing a lot of work on the MooTools vector graphics library – ART. We already have great SVG and VML support. Next for me is to focus on high performance scenarios.

To start off, I’ve implemented two 2D use cases that are otherwise difficult to do properly using CPU only.

Diffusion Curves

A Diffusion Curve is a new vector primitive. To understand what they are and why they’re incredibly cool, I recommend watching the video from the authors of the original research paper. Implementing a rasterizer of Diffusion Curves involves a diffusion and blur step that are both very computationally expensive. However, using a clever implementation you can take advantage of GPU hardware acceleration to get acceptable performance. There have been talks about introducing diffusion curves in SVG 2.0. But until that gets into browsers, we can already use it through the power of WebGL.

Page Curl Effect

A page curling effect can be implemented many different ways. However, to get a smooth realistic effect on dynamic content you really need some acceleration. This applies to many special effects that you can apply to 2D content.

Safari doesn’t implement SVG filters yet. Such filters can be implemented in terms of WebGL and extended further to advanced blending effects and crazy transforms.

Computation

WebGL is a great complement to JavaScript. JavaScript can be used to implement business logic and UI components while WebGL is used for computationally expensive tasks. Many of the use cases of NaCi (Native Client) goes out the window. You can even use WebGL to performance non-graphics tasks such as audio signal analysis/transformation.

Now all we need is a JavaScript based OpenCL like API for running GPU accelerated workers. There are already several projects doing something similar with Python.

Learning more about WebGL

The best way to learn WebGL is to head over to Learning WebGL and check out Giles Thomas‘ excellent introductory lessons.

Coming Up

Lessons Learned – WebGL

Lessons Learned – Diffusion Curves