3

I am using SVG to generate video animations my making a sequence of images and converting that to a video file. One effect I need is to to be able to smoothly pan/zoom text. I'm attempting to do this by applying a transformation to a graphic context containing the text. Each frame has a small fractional change in the scale/translation. This technique has worked well for static images. But not for text. What I see is not a smooth effect as you'd expect. There is a certain jerkiness/shimmering of the text from frame to frame. It's as if font rendering rules are being applied post-transform (not pre-transform).

So the question: how to I achieve a smooth scale/pan effect with text?

Example of one frame:

<svg width='320' height='180'>
<rect x='0' y='0' width='320' height='180' fill='white' />
<g transform='scale(5.999999999999893)'><text x='50' y='50'>Hello World!</text>
</g></svg>

Here is a video clip demonstrating what I mean: http://www.youtube.com/watch?v=TrEjDeGlPhA&list=UUfWuDb3rpD5OInqUpNivjdA&index=1

Or you can create from scratch: I wrote a small Java program that will generate these frames, and create an AVI file to demonstrate (assuming Linux, mencoder, rsvg-convert available).

import java.io.File;
import java.io.Writer;
import java.io.FileWriter;
import java.io.IOException;

public class MakeTextScaleAnimation {

public static void main (String[] arg) throws Exception {

    double s;

    int frame = 0;
    for (s=1.0; s < 8.0; s+=0.005) {
        String framePrefix = "frame" + String.format("%04d", frame);
        File frameFile = new File (framePrefix + ".svg");
        FileWriter w = new FileWriter(frameFile);
        writeFrame(w,s);
        w.close();

        frame++;

        System.out.println ("rsvg-convert " + frameFile.getName() + " > " + framePrefix + ".png");
    }
}

private static void writeFrame(Writer w, double s) throws IOException {
    w.write ("<svg width='320' height='180'>\n");
    w.write ("<rect x='0' y='0' width='320' height='180' fill='white' />\n");
    w.write ("<g transform='scale(" + s + ")'>");
    w.write ("<text x='50' y='50'>Hello World!</text>\n");
    w.write ("</g></svg>");
}
}

And this script to run:

#!/bin/bash
javac MakeTextScaleAnimation.java 

# Make SVG animation frames and generate script to convert to PNG
java MakeTextScaleAnimation  > svgtopng.sh

# Convert SVG frames into PNG images
. svgtopng.sh

# Convert the PNG images into a movie file
mencoder mf://frame*.png -mf fps=24:type=png \
-ovc lavc -lavcopts vcodec=mpeg4:vbitrate=3200 \
-o output.avi
jdesbonnet
  • 251
  • 3
  • 7
  • 1
    You might try setting text-rendering. geometricPrecision would seem to be what you need. (http://www.w3.org/TR/SVG/painting.html#TextRenderingProperty) Of course your UA may not support this property. – Robert Longson Mar 06 '13 at 17:06
  • text-rendering property seemed a promising solution: but it didn't make any difference whatsoever (with librsvg2). Thanks for the tip. – jdesbonnet Mar 07 '13 at 15:48

1 Answers1

1

The best way I've found is to turn the text into a path. I use Inkscape, which has an 'object to path' function. I keep design files all in text to make changes easy, and create a path version for display. It was the best work-around I could find, and it also means you're not depending on system fonts. If you've got a lot of text it will make huge files though!

Martin
  • 11
  • 1