Click the 'start svg demo' button on this page. When the page is loaded, you can click anywhere on the canvas to start the demo.
I had never got around to play with SVG text as I wanted to and
it finally happened with this demo. The demo shows how to
access the content of SVG <text>
elements and animate
individual glyphs.
The demo has a library of 'effects' which are succesively applied to quotes (from http://en.wikiquote.org/wiki/American_proverbs).
All the effects work similarly. When applied, they first break down the
text into a set of text spans which are then animated individually.
The target text element (or elements, since the effect can apply to
multiple lines of text) is (are) left unmodified and their display
property is set to 'none'. The text spans are inserted after the
text elemenet and are the target of the different animation effects.
The key DOM API method used in the process of computing individual
glyph positions is getStartPositionOfChar
on the
SVGTextContentElement
interface (see the
specification).
// Compute the different glyph positions and how many characters map to the // same glyph position (may happen with ligatures). var p = 0, pos = [], curPos, n = .. /* textContent length */ for (i = 0; i < n; i++) { p = text.getStartPositionOfChar(i); if (curPos === null || p.x !== curPos.p.x || p.y !== curPos.p.y) { curPos = { p: {x: p.x + dx, y: p.y + dy}, n: 1 }; pos.push(curPos); } else { // Same position, just increase the text run length curPos.n++; } }
As in several other demos on this web site, the animations are built
by extending the YUI 3
JavaScript and CSS library to support SVG. The code also uses a
concept of Effect
to encapsulate a number of related
animations so that they can be manipulated as a single abstraction.
For example, the 'opacity-swipe' effect has one animation on the
'fill-opacity' of each glyph, each animation starts when the previous
one ends and the user can run the effect which internally starts the
first animation, causing the whole animation chain to run. Likewise,
the user can use the onBegin
and onEnd
events
on the effect object to invoke specific code when the effect starts or
ends.
The following code snippet shows how the 'opacity-swipe' effect applies to the different text spans.
// ... // toGlyphSpans is a utility method to break down the text in multiple // elements. var spans = toGlyphSpans(text), n = spans.length, s, a, anims = []; // duration, offset and easing a defined somewhere else in the code.s for (var i = 0; i < n; i++) { s = spans[i]; a = new Animate({ node: s, from: {'fill-opacity': 0}, to: {'fill-opacity': 1}, duration: duration, easing: easing }); anims.push(a); } for (i = 1; i < n; i++) { anims[0].onBegin(anims[i], i * offset); } // The Effect utility provides a way to manipulate a group of animations // as a single entity. return new Effect(anims);
Music by Roger Kidd (with all my thanks).
The font used in this demo is "GoodDog" and can be found on Font Squirrel. See the attributions page.
Click the 'start svg demo' on the page. When the page is loaded, it has the following header:
You can do several things (which are explained later on):
The 'spray paint' check box turns the Canavs rendering on or off.
Graffitis go from the simplest scribbles to the most sophisticated artwork, as you can see on Flickr for example.
There is amazing work done to capture graffiti drawing and render them with computers graphics. Some renderings are absolutely stunning, as the work done by Chris Sugrue and Evan Roth shows.
The graffiti data is captured in the Graffiti Markup Language, GML. http://000000book.com/ (black book) is a repository of GML graffitis. Graffitis can be created with applications such as FatTagKatsu for the iPhone to draw tags and upload them to the Blackbook repository.
This demo uses and manipulates GML JSON data to render and animate
tags in the blackbook tags repository.
The graffiti data is turned into a number of SVG <path>
objects and the 'drawing' effect is simply done by animating the
stroke-dashoffset
on the different path elements.
The getTotalLength
method on the
SVGPathElement interface provides the length for each
path and lets the code compute the proper stroke-dashoffset
value. This is illustrated in the following figure.
The rendering also uses the Canvas API
to draw particles of paint as the stroke gets rendered. The particles are sprayed based on the
speed of the pen as it moves along the graffiti. The canvas with the particles is
part of the SVG tree, as a child of a foreignObject
element,
which demonstrates how well the two rendering models can be combined.
The demonstration also shows how to simply create a GML file: when the user selects the 'record' button, he/she can the draw on the canvas and then select the 'play' button when done. This will render the rendering of the captured GML content.
Finally, the demonstration illustrates an overlay filter effect.
The overlay compositing rule does not come directly in SVG as
it is not part of the
<feBlend>
modes. However, it is possible
(even though a bit computation intensive) to create an overlay by
combining the 'multiply' and 'screen' modes of <feBlend>
.
This is a bit of a sophisticated filter which I'll further describe
in a separate demo decicated to just that filter.
Several implementations (Firefox 3.6, Safari 5.0 and Chrome 6.0) have a
bug at the time of this writing and fail to correctly render stroke line
joins when the path points are closer than the stroke width. The code
contains an ugly hack to get the
visually correct result. The hack consists in adding
circles at the point poisitions to make sure the line joins are properly
rounded. This is ugly because it adds to the DOM load (many
<circle>
elements are added) and slows down the
animation.
The page header uses the HVD-Peace font.
This demo shows how to create an interactive svg webapp. Place a beard/mustache on a photo of your choice.
Hover the bottom part of the photo to show the palette of available face enhancements, and drag the one of your choice from the palette to the photo.
When an item is selected it can be rotated by pressing the right- or left-arrow key. To scale an item press up- or down-arrow key to zoom in or out respectively. To rotate/scale in smaller steps hold down the shiftkey at the same time. To remove an item, select it and then press backspace or delete.
You can also add your own photo by clicking the "Add photo" button in the palette, as well as save the result to a data uri. Per default the saved svg file only links to the photo, but it's also possible to save a standalone file by following this link (note that big photos can take a bit of time to export, and your browser may appear frozen during the encoding phase).
See attributions about the resources used in this demo.
This example illustrates the use of the following features:
Note that the demo uses setTimer to synchronize the lyrics with the audio because the new audio timeupdate event is not supported in all the browsers yet. However, as explained on Silvia Pfeiffer's site it would be a better way to synchronize the lyrics in a pure HTML5 context.
See attributions about the song and fonts used in this demo (also showing at the end of the demo). The code leverages the YUI library with an extension to allow animation of SVG transform attributes.
Click on the "Start SVG Demo" at the top of this page. When the demo has loaded, click in the center of the image. Then, once the menu has settled, click on the "ancient sun" item.
This demo illustrates the use of the getPointAtLength() API on the SVG <path> element.
The script simply accesses the path of an object and gets the coordinates of points along that path. Then, it positions a 'pebble' of random size at a pseudo-random position about the coordinates returned by getPointAtLength
Inkscape was used to convert the "SVG" and "Wow!" texts to SVG paths elements which the demo code manipulates.
See attributions for the OpenClipArt play/pause icons.
Click on the "Start SVG Demo" at the top of this page. When the demo has loaded, click in the play button at the bottom right. Once the "SVG" text has fully appeared, click on the display.
This demo shows how SVG can be used to render images retrieved from the Flickr interesting photo source and provide a dynamic, interactive user experience.
The purpose of this demo is to show illustrate that SVG can be used, just like HTML, for AJAX applications.
The magnifier effect used in this demo was inspired by Jared Tarbell's text sphere. Here, the magnifier effect is applied on a single (horizontal) axis.
See attributions for details on using the Flickr APIs.
Click on the "Start SVG Demo" at the top of this page. When the demo has loaded, move the cursor to the bottom of the display. This will make the animated menu appear. The menu's speed is controlled by the distance from the center of the menu on the horizontal axis.
Like the Photo Album demo, this demo shows how SVG can be used to render images retrieved from the Flickr interesting photo source and provide a dynamic, interactive user experience.
This demo leverages the Yahoo YUI library with extensions to make it work with SVG elements, in particular to allow the animation of the transform attribute.
The magnifier effect used in this demo was inspired by Jared Tarbell's text sphere.
See attributions for details on the YUI library.
Click on the "Start SVG Demo" at the top of this page. When the demo has loaded a first page of images, click on the 'prev' or 'next' links at the bottom left of the page to load a new page.
WARNING: the demo runs very slowly in Firefox as of version 3.6.
This demo shows interactive animated SVG filter effects.
The animation is made by animating a displacement map image, with a radial gradient mask to smoothly fade out the edges. To be able to run the animation the browser must support SVG filters, declarative animation (SMIL) and scripting.
See attributions.
Click on the "Start SVG Demo" at the top of this page.
Then click anywhere on the image to start animating a droplet ripple effect from that point.
This demo uses an animated displacement map filter to make a twirling effect on a photo.
The displacement map image was created from an identity displacementmap svg image that was rasterized to 640x480 pixels and then processed in a normal graphics editor to produce this image. That image is then animated (rotated) by SVG declarative animation (SMIL).
See attributions.
Click on the "Start SVG Demo" at the top of this page.
This example illustrates the use of
the svg <pattern>
element. The background rectangle
is drawn with a simple pattern made of dots and rectangles,
similar to that found in modern art work and designs
(e.g., Vasarely, Verner Panton). The "svg" text is painted with
a similar, inverted pattern.
Patterns a common in computer graphics. However, SVG patterns are powerful in that they can be defined not only as bitmap content, which is the common case in graphics libraries, but also as vector content. In other words, the content of an SVG pattern can be any arbitrary SVG graphics. Furthermore, SVG patterns can be created by scripts.
In the initial rendering, there is actually no outline for the text, and our perception still makes out the 'svg' shape outline by assuming continuity between unconnected path segments. This is an optical illusion similar to what happens with the famous Kanizsa triangle.
Note, however, that even though there is no real "svg" shape in the visual rendering, a shape is actually filled with a different pattern...
After loading the demo, move the cursor over the rectangle. This will first show the 'SVG' text filled with a different pattern. Then, move the cursor over the text iteself to show the text in another, colored pattern.