Learning to Code with SVG
Lesson Plan:
Coding Animated Waves with in SVG
Objective:
Hands-on learning of SVG by drawing a wave with animation of the amplitude.
Introduces the path Quadratic Bezier Curve commands Q & T for drawing a wave using the path element.
Introduces the <animate> element changing the path command to smoothly alter the waves amplitude.
Lab Time:
Approximately 1 hour, not including Lecture time. Students should copy and paste lines, and then change the attribute values to greatly reduce typing time and typos.
Age range:
4-12th grades, or any age student unfamiliar with SVG
Requirements:
Familiar with a simple text editor like Notepad on Windows, or Text Wrangler on a Mac.
Familiar with copy and paste shortcuts (ctrl-c and ctrl-v on windows and command-c and command-v on a Mac).
Ability to save file with a .svg extension.
Should be familiar with adding <g>, <path>, and <circle> elements in SVG
Resources:
Lecture:
Introduce the <path> Quadratic Bezier command in the eBook, Learn SVG Interactively, and the <animate> element.
Review syntax of SVG elements having child elements, i.e. using beginning and ending tags, and the rotate transformation
Procedure:
Give the students the instructions on pages 4-5.
Have students create an SVG element with a viewBox="0 0 1000 1000" in the text editor.
Save the file as waves.svg then open in a browser. Keep the text editor and browser windows open.
Save and refresh the browser regularly to see if errors were introduced and what effect the code had.
Take Away:
Students should feel comfortable creating SVG images from scratch.
Students should get a feel for the <path> element Quadratic Bezier commands Q, q, T, & t.
Students should understand the syntax for SVG elements with child elements.
Additional Activity
Students can change the path command to give the waves a different cycle.
Add or remove waves and change the rotation values.
What the Waves should look like - Page 2 of 6 in PDF
Waves
Instruction Sheet for Students - Pages 3 to 4 of 6 in PDF
Coding Animated Waves in SVG
To get started copy the code of this image into your editor:
http://steamcoded.org/lessons/grid1000x1000.svg.txt and save the file as waves.svg and open the file in a browser. In the editor, add the SVG elements (per instructions below).
1:
Copy and Paste the 1000x1000 grid from: http://steamcoded.org/lessons/grid1000x1000.svg.txt
2:
Add a <style> element as follows:
<style type="text/css"><![CDATA[
  
.s1 {fill:none;stroke:black;stroke-width:6px;}
]]>
</style>
3:
After the line , Add a <path> element with attributes
d="M0,500q100,-137,200,0" class="s1"
Note: the q command is lower case so the coordinates are relative to the starting point (0,500)
It defines a quadratic bezier curve with control point (100,-137) and ending at (200,0).
In absolute coordinates the control point is at (100,363) and ends at (200,500)
4:
Append to the <path> d attribute "t200,0" so it now reads
d="M0,500q100,-137,200,0t200,0"
Note: the lower case t means relative to where the path left off. The t command tells
the browser to create another quadratic bezier curve by reflecting the previous command's control point
and end at (200,0) relative to where the path left off, which will end at (400,500) in absolute coordinates.
5:
Continue appending "t200,0" to the path definition until reaching absolute coordinate (1000,500) - 3 more times,
but refresh the browser after adding each one so you see the effect of adding the commands.
6:
Now reflect the wave back by copying the "q100,-137,200,0" command and appending the copied text to the end
of the path command, then change the q command control point to be (-100,137) and the ending point to (-200,0)
7:
Append to the <path> d attribute "t-200,0" 4 times, refreshing the browser each time
8:
Make this path a symbol so it can be reused by adding a <defs> section near the top of the code
after the </desc> tag
Create a <symbol> element with attributes id="wave" overflow="visible"
<defs>
  
<symbol id="wave" overflow="visible">
  
</symbol>
</defs>
9:
Copy the <path> element created in steps 3-7 and paste as a child of the <symbol> element.
Then change the attribute class="s1" to style="stroke-linejoin:round;"
<symbol id="wave">
  
child elements go between the start and ending tags
</symbol>
10:
Delete the original <path> that was copied, then add a <g> element with attribute class="s1".
Remember the closing </g> tag
<g class="s1">
</g>
11:
As a child of the group element in step 10 add a <use> element with attribute xlink:href="#wave"
<use xlink:href="#wave" />
12:
In the <style> section create a new style by adding a line after the s1 definition
.c1 {fill:none;stroke:red;stroke-width:6px;}
13:
Copy the <use> element from step 11 and paste after the closing </g> tag and add attribute
class="c1"
14:
Change the s1 style definition to have stroke-width:12px; (was 6px), this will make the
colored path appear to be stroked black.
15:
Add the following <style> definitions by adding these lines below the c1 definition
Note copy the c1 defintion and change the color and name c2-c9
.c2 {fill:none;stroke:orange;stroke-width:6px;}
.c3 {fill:none;stroke:yellow;stroke-width:6px;}
.c4 {fill:none;stroke:turquoise;stroke-width:6px;}
.c5 {fill:none;stroke:lime;stroke-width:6px;}
.c6 {fill:none;stroke:cyan;stroke-width:6px;}
.c7 {fill:none;stroke:blue;stroke-width:6px;}
.c8 {fill:none;stroke:pink;stroke-width:6px;}
.c9 {fill:none;stroke:magenta;stroke-width:6px;}
16:
Copy the <use> element with class="c1" and paste it on the next line, then change the
class attribute to "c2" and add attribute transform="rotate(20,500,500)" which rotates
the element by 20 degrees about point (500,500), the center of the grid.
17:
Continue copy and pasting and changing class attributes to c3-c9 and rotate each by an
additional 20 degrees until rotated 160 degrees.
Note 180 degrees would just overwrite the first use element
18:
Copy the <use> element in the group with class="s1" and paste on the next line, then add attribute
transform="rotate(20,500,500).
19:
Repeat step 18 rotating an additional 20 degrees until the last one rotated at 160 degrees
20:
Add a <circle> element as the first line inside the group with class="s1" with attributes:
cx="500" cy="500" r="504" style="stroke-width:2px;"
21:
Animate the design by adding an <animate> element as a child of the <path> in symbol with id="wave"
Change the <path> element so it ends > instead of />, then on the next line add an ending </path>
22:
Add an <animate> element as a child of the <path> element in step 21 as shown:
<animate attributeName="d" dur="2s" repeatCount="indefinite"
values="
M0,500q100,-1,200,0t200,0t200,0t200,0t200,0q-100,1,-200,0t-200,0t-200,0t-200,0t-200,0;
M0,500q100,-560,200,0t200,0t200,0t200,0t200,0q-100,560,-200,0t-200,0t-200,0t-200,0t-200,0;
M0,500q100,-1,200,0t200,0t200,0t200,0t200,0q-100,1,-200,0t-200,0t-200,0t-200,0t-200,0;" />

Note: Copy the d attribute of the <path> element in step 21 and paste 3 times after the
<animate> element's values attribute - each on it's own line as shown above. Append a ; to each line
to separate the values used in the animation. Then change
the x-coordinate of the control points (-137 and 137) to be -1 and 1 on the first and third lines.
Then change the x-coordinate of the control points (-137 and 137) to be -560 and 560 on the
second line.

Remember to add the ending quotation to the values attribute and
close the <animate> element by ending it with />
When complete, change the style attribute of the first element from "display:initial" to "display:none" which hides the grid. Then change the style attribute of the second element from "opacity:0.5" to "opacity:1"

Add a margin by changing the viewBox attribute of the <svg> element to "0 0 1020 1020" and
adding a transformation to the <g style="opacity:1"> element to move the image down and right 10 pixels
<g style="opacity:1" transform="translate(10,10)">
Answer Sheet for Instructor - Pages 5 to 6 of 6 in PDF
Coding Animated Waves in SVG
Answer Sheet
Common mistakes: closing the opening element tag with a /, missing a closing tag, missing double quote marks around attribute values, missing space between attributes, and missing the start < and ending > symbols.
1:
<svg width="100%" height="100%" viewBox="0 0 1000 1000"
    
xmlns="http://www.w3.org/2000/svg"
    
xmlns:xlink="http://www.w3.org/1999/xlink">

<svg>
2:
<style type="text/css"><![CDATA[
  
.s1 {fill:none;stroke:black;stroke-width:6px;}
]]>
</style>
3:
<path d="M0,500q100,-137,200,0" class="s1" />
4:
<path d="M0,500q100,-137,200,0t200,0" class="s1" />
5:
<path d="M0,500q100,-137,200,0t200,0t200,0t200,0t200,0" class="s1" />
6:
<path d="M0,500q100,-137,200,0t200,0t200,0t200,0t200,0q100,137,-200,0" class="s1" />
7:
<path d="M0,500q100,-137,200,0t200,0t200,0t200,0t200,0q100,137,-200,0t-200,0t-200,0t-200,0t-200,0" class="s1" />
8:
<defs>
  
<symbol id="wave" overflow="visible">
  
</symbol>
</defs>
9:
<defs>
  
<symbol id="wave" overflow="visible">
    
<path d="M0,500q100,-137,200,0t200,0t200,0t200,0t200,0q100,137,-200,0t-200,0t-200,0t-200,0t-200,0"
      
style="stroke-linejoin:round;" />
  
</symbol>
</defs>
10:
<g class="s1">
</g>
11:
<g class="s1">
  
<use xlink:href="#wave" />
</g>
12:
<style type="text/css"><![CDATA[
  
.s1 {fill:none;stroke:black;stroke-width:6px;}
  
.c1 {fill:none;stroke:red;stroke-width:6px;}
]]>
</style>
13:
<g class="s1">
  
<use xlink:href="#wave" />
</g>

<use xlink:href="#wave" class="c1" />
14:
.s1 {fill:none;stroke:black;stroke-width:12px;}
15:
<style type="text/css"><![CDATA[
  
.s1 {fill:none;stroke:black;stroke-width:12px;}
  
.c1 {fill:none;stroke:red;stroke-width:6px;}
  
.c2 {fill:none;stroke:orange;stroke-width:6px;}
  
.c3 {fill:none;stroke:yellow;stroke-width:6px;}
  
.c4 {fill:none;stroke:turquoise;stroke-width:6px;}
  
.c5 {fill:none;stroke:lime;stroke-width:6px;}
  
.c6 {fill:none;stroke:cyan;stroke-width:6px;}
  
.c7 {fill:none;stroke:blue;stroke-width:6px;}
  
.c8 {fill:none;stroke:pink;stroke-width:6px;}
  
.c9 {fill:none;stroke:magenta;stroke-width:6px;}
]]>
</style>
16:
<use xlink:href="#wave" class="c1" />
<use xlink:href="#wave" class="c2" transform="rotate(20,500,500)" />
17:
<use xlink:href="#wave" class="c1" />
<use xlink:href="#wave" class="c2" transform="rotate(20,500,500)" />
<use xlink:href="#wave" class="c3" transform="rotate(40,500,500)" />
<use xlink:href="#wave" class="c4" transform="rotate(60,500,500)" />
<use xlink:href="#wave" class="c5" transform="rotate(80,500,500)" />
<use xlink:href="#wave" class="c6" transform="rotate(100,500,500)" />
<use xlink:href="#wave" class="c7" transform="rotate(120,500,500)" />
<use xlink:href="#wave" class="c8" transform="rotate(140,500,500)" />
<use xlink:href="#wave" class="c9" transform="rotate(160,500,500)" />
18:
<use xlink:href="#wave" transform="rotate(20,500,500)" />
19:
<use xlink:href="#wave" transform="rotate(40,500,500)" />
<use xlink:href="#wave" transform="rotate(60,500,500)" />
<use xlink:href="#wave" transform="rotate(80,500,500)" />
<use xlink:href="#wave" transform="rotate(100,500,500)" />
<use xlink:href="#wave" transform="rotate(120,500,500)" />
<use xlink:href="#wave" transform="rotate(140,500,500)" />
<use xlink:href="#wave" transform="rotate(160,500,500)" />
20:
<circle cx="500" cy="500" r="504" style="stroke-width:2px;" />
21:
<defs>
  
<symbol id="wave" overflow="visible">
    
<path d="M0,500q100,-137,200,0t200,0t200,0t200,0t200,0q100,137,-200,0t-200,0t-200,0t-200,0t-200,0"
      
style="stroke-linejoin:round;" >
    
</path>
  
</symbol>
</defs>
22:
<defs>
  
<symbol id="wave" overflow="visible">
    
<path d="M0,500q100,-137,200,0t200,0t200,0t200,0t200,0q100,137,-200,0t-200,0t-200,0t-200,0t-200,0"
      
style="stroke-linejoin:round;" >
      
<animate attributeName="d" dur="2s" repeatCount="indefinite"
        
values="
        
M0,500q100,-1,200,0t200,0t200,0t200,0t200,0q-100,1,-200,0t-200,0t-200,0t-200,0t-200,0;
        
M0,500q100,-560,200,0t200,0t200,0t200,0t200,0q-100,560,-200,0t-200,0t-200,0t-200,0t-200,0;
        
M0,500q100,-1,200,0t200,0t200,0t200,0t200,0q-100,1,-200,0t-200,0t-200,0t-200,0t-200,0;" />
    
</path>
  
</symbol>
</defs>