SVG hacking: getting a cartoon giraffe to blink

cartoon giraffe Most people who create SVG vector images like this cute giraffe do it in Inkscape, which tends to mask the fact that, unlike PNGs or JPGs, SVG files are plain text files that you can edit, like HTML. In fact, SVG is a distant cousin of HTML, so the code looks kind of similar. The brilliant thing about this is it means even someone like me with no artistic skills at all can do interesting things with SVG. This giraffe is pretty cute, but I want to make her look more lifelike by making her blink.

Step 1 is to download the SVG file from clker.com. The artist who created this image dedicated it to the Public Domain, which means I’m free to do anything I want with it.

At first glance the code can be intimidating:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.0"
width="268.95636"
height="504.60901"
id="svg2">
<defs
id="defs4" />
<g
transform="translate(-216.72685,-178.058)"
id="layer1">
<path
d="M 441.29462,560.70587 C 441.30944,610.4339 401.00107,650.75429 351.27304,650.75429 C 301.54501,650.75429 261.23664,610.4339 261.25146,560.70587 C 261.23664,510.97784 301.54501,470.65745 351.27304,470.65745 C 401.00107,470.65745 441.30944,510.97784 441.29462,560.70587 z"
transform="matrix(1.2167832,0,0,1.2167832,-76.150099,-121.55162)"
id="path2383"
style="opacity:1;fill:#ffcc00;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.28735638;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
d="M 93.338093,349.0455 A 18.031223,15.556349 0 1 1 57.275646,349.0455 A 18.031223,15.556349 0 1 1 93.338093,349.0455 z"
transform="matrix(0.4247339,-0.2447311,0.4879048,0.846765,78.433639,337.30162)"
id="path3242"
style="opacity:1;fill:#784421;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
...

But there’s a nice simple structure to it: every section of code starting with

<path 

and ending with

 />

represents one piece of the image: an ear, an eyeball, or a brown spot, for example. You can figure out which part of the code corresponds to what part of the image by commenting out code segments one at a time. SVG comments work the same as in HTML, ie

<!-- This is a comment -->

.

So I set out to make eyelids by adding in two rectangles (W3C has some nice simple tutorials on doing simple shapes in SVG). I worked out the length, width, x and y values by trial and error, and all the styles are copied from the eye code, except I made the stroke-width narrower. Here’s the code:



<!-- Left eyelid -->
<rect width="50" height="60" x="300" y="200" id="leftEyelid" style="opacity:1;fill:#ffcc00;fill-opacity:1;fill-rule:nonzero;stroke:#000000; stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;>

And here’s the giraffe, looking somewhat disgruntled that some slob has rudely stuck a pink rectangle on her head.

cartoon giraffe with a pink rectangle over its left eye

I needed the eyelid to go above the eye and the eyeball, but behind the rest of the giraffe’s head. Getting in front of the eye and eyeball was easy; in SVG unless the z-index is specified, the order of elements is the order they appear in the code, that is, the first <path … element is at the bottom of the stack and the last one is at the top. So I made sure my eyelid came further down in the code than the eye and eyeball elements. But limiting the eyelid to only appear within the circle of the eye and not outside of it, required a clip-path. Here’s the modified code:



<!-- Left eyelid -->
<rect width="50" height="60" x="300" y="200" id="leftEyelid" style="opacity:1;fill:#ffcc00;fill-opacity:1;fill-rule:nonzero;stroke:#000000; stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1; clip-path: url(#leftEyeClip)">

The clip-path refers to an anchor link called url(#leftEyeClip), which I defined in a different part of the code. The clip-path is just the path element that defined the eye, copy-pasted:

<defs>

<clipPath id="leftEyeClip">
<path
d="M 347.6435,278.41325 C 347.64723,290.9322 337.49967,301.08278 324.98073,301.08278 C 312.46178,301.08278 302.31422,290.9322 302.31795,278.41325 C 302.31422,265.89431 312.46178,255.74373 324.98073,255.74373 C 337.49967,255.74373 347.64723,265.89431 347.6435,278.41325 z"
id="path3157"
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.99999952;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</clipPath>

<clipPath id="rightEyeClip">
<path
d="M 400.3757,278.41325 C 400.37943,290.9322 390.23187,301.08278 377.71293,301.08278 C 365.19398,301.08278 355.04642,290.9322 355.05015,278.41325 C 355.04642,265.89431 365.19398,255.74373 377.71293,255.74373 C 390.23187,255.74373 400.37943,265.89431 400.3757,278.41325 z"
id="path3159"
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.99999952;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</clipPath>

</defs>

… and here’s the result (if you look closely, there is a little bit of pink eyelid showing on the right eye):

cartoon giraffe with pink eyelid

Now the eyelids are in place and all that remains is to make them blink, using the SVG animate element. Here’s the final code for the left eyelid:

    <!-- Left eyelid  -->

<rect width="50" height="60" x="300" y="200" id="leftEyelid" style="opacity:1;fill:#ffcc00;fill-opacity:1;fill-rule:nonzero;stroke:#000000; stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1; clip-path: url(#leftEyeClip)">

<animate attributeName="y" attributeType="XML"
begin="0s" dur="4s" fill="freeze" values="200;240;220;240;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200; 200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200;200" repeatDur="indefinite" />

</rect>

I started off with a single blink, moving the rectangle’s y position (vertical position) from 200 to 240 and back to 200 again, but I thought it would look better with a double-blink, with the eyelid going half-way up in between the two blinks, so the values are 200; 240; 220; 240; 200. And then the 200 is repeated a billion times because I wanted the actual blinking to be very fast, with a long pause between blinks. Probably there is a better way to do this and I just haven’t found it yet.

Sadly WordPress doesn’t allow SVG files to be embedded in blog posts, but if you go to
this link (and you have a fairly modern browser) you can see the giraffe in all its blinking glory.

Theoretically since this is a public domain image and I’ve done some work on it, I could claim it as my own copyrighted work, but since that’s just stupid, I hereby dedicate this blinking vector giraffe back to the public domain.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s