Creating SVG Elements from Data
FREE     Duration: 10:58
Part of Course: Introductory D3 Course
 

Takeaways:

  • Because SVG graphics are written in XML, we can use D3 to create SVG tags and set their attributes with values
  • The SVG Basic Shapes are rectangle, circle, ellipse, straight line, polyline, polygon, and path
  • The SVG XML tags must live inside of an SVG <svg> tag to be properly interpreted by the browser as being SVG
  • The D3 Data Operator joins a specified array of data with the current selection
  • Because SVG is understood by the browser and lives in the DOM, we can bind data to the SVG elements using D3
  • Because SVG can have data bound to it with D3, it means we can use the data bound to the SVG elements to set their attributes and values
  • The D3 Style Operator, if a name and value are specified, sets the CSS style property for the given selection with the given specified value (whether constant or return value from a function)

Transcript:

Creating SVG Elements from Data

SVG Revisited

<svg> ... </svg>

SVG is a Vector Based Graphics system

The SVG system creates DOM objects for each graphical element.

The SVG element is commonly referred to as the SVG Viewport.

Things within the SVG Viewport dimension's are visible

Things inside the SVG tags though outside the Viewport dimensions are not visible.


SVG Basic Shapes

  • Rectangle
  • Circle
  • Ellipse
  • Straight Line
  • Polyline
  • Polygon
  • Path

SVG comes with these basic shapes predefined so as to make it easy to draw them.

<svg width="50" height="50">
    <circle cx="25" cy="25" r="25" />
</svg>

Because SVG graphics is written in XML, which is very close to HTML, we can use D3 to create SVG tags and set their attributes with values.

d3.select("body").append("svg").attr("width","50").attr("height","50").append("circle").attr("cx","25").attr("cy","25").attr("r","25");

Which means we can write D3 code to simulate writing SVG code manually.

We can do this with all of the basic SVG shapes.


Now that we've refreshed our memory of SVG, SVG basic shapes, the SVG Viewport and how to use D3 to create the SVG Basic shapes, next we look at the D3 Data Operator Revisited.



D3 Data Operator Revisited

d3.selection.data([values[, key]])

This is the D3 Data Operator

We have seen it before when we gave it values to bind to the selection

The Data Operator joins the specified array of data with the current selection

d3.selection.data([1,2,3,4,5]);

So far we have defined our data inside of the D3 Data Operator

Though when we first talked about the D3 Data Operator

We covered that the values passed in could be an array of data values, such as an array of numbers or objects, or even a function that returns an array of values.

var myData = [...];
d3.selection.data(myData);

From now to make things more modular and easier to read

We will define a myData variable and then use that variable

To feed the D3 Data Operator.

For now we will just use a single array of many numbers

Later we cover associative arrays, JSON, and other types of data


Next we look at Binding Data to SVG Elements



Binding Data to SVG Elements

In the Video Binding Data To DOM Elements, we bound data to DOM elements

var myData = [1,2,3,4,5];
var updateSelection = d3.select("body").selectAll("p").data(myData);
var paragraphElements = updateSelection.enter().append("p");

BROWSER - Click on the tag to show the 5 paragraph elements.

Using a new barebones HTML file, the update selection was created

Then the enter selection was referenced and an HTML paragraph element

Was appended to each JavaScript Object Element created to hold each of the data points.


Because SVG is written in XML, we can do the same thing as we did with the paragraph element.

Though instead of using the Paragraph Element,

we use the SVG keyword for creating a circle.

var myData = [1,2,3,4,5];
var circleSelection = d3.select("body").selectAll("circle").data(myData);
var circleElements = circleSelection.enter().append("circle");
circleElements.data();

BROWSER - Click on the tag to show the 5 circle elements.

As you can see, we were able to bind data to 5 SVG circle Elements


An important thing to remember, is that SVG definitions must live inside of SVG tags to be able to be read and understood by the browser

var myData = [1,2,3,4,5];
var svgViewport = d3.select("body").append("svg").attr("width","400").attr("height","400");
var circleSelection = svgViewport.selectAll("circle").data(myData);
var circleElements = circleSelection.enter().append("circle");
circleElements.data();

BROWSER - Arrow up through the commands.

Which means that instead of appending the circles to the body element selection,

We have to append an SVG tag, inside of which we create the SVG elements.

We give the SVG tag viewport dimensions to make sure it fits inside of the screen

When we hover over the SVG tag in the elements section of the developer tools

You can see the highlighted dimensions on the actual HTML document

As you can see, the circle elements still have the right data bound to them

And now they live inside of the SVG viewport.


Recalling that we can add attributes to SVG Basic shapes,

We can give the circles some attributes.

circleElements.attr("cx","100").attr("cy","100").attr("r","25");

BROWSER - In the elements section, hover over all the circles

As you can see, by adding attributes to the circles,

The web browser was able to draw the SVG circles for us

However, as you can also see, each circle received the exact same attribute.

This is because we passed to the attribute operator a constant value.

Which means that the constant value is given to every element in the selection.


The attribute operator also behaves like most D3 operators in that it is also able to take in a function.


Next, we look at the using JavaScript Functions to Use Data Bound to SVG Elements



Use Data Bound to SVG Elements

d3.selection.attr(name[, value])

Before, we covered that this operator inserts an attribute and a value, if specified, into the elements in the selection.

Then it returns a selection.

The examples covered used a constant as the value.

d3.selection.attr(name, function () {...} )

What we didn't cover is the case where we can pass in a function to the attribute operator.

And the return value of the function is used to set the name attribute value.


Let's try some simple examples to see how it works.


First, we do a simple example using an HTML paragraph element.

d3.select("body").insert("p").attr("class","first_p");

BROWSER - open body and highlight the paragraph

As you can see, we set the class attribute of the paragraph to be the constant value "first_p"


Next, let's write a named function that returns a string

function myFunction() { return "function_p"; };


Then, let's insert a paragraph with a class attribute.

d3.select("body").insert("p").attr("class", myFunction);

BROWSER - Highlight the newly insert paragraph element

As you can see, the myFunction function was applied to the paragraph element

and the returned the value function_p as the class attribute value.


Next, let's write an anonymous function that returns a string

and use it directly in the D3 attribute operator


d3.select("body").insert("p").attr("class", function () { return "anon_p"; });

BROWSER - Highlight the newly insert paragraph element

As you can see, the anonymous function was applied to the paragraph element

and the return value anon_p was set as the class attribute value.


Now, let's go back to our SVG circle example.

BROWSER - Clear the screen and restart with these variables already typed in.

var myData = [1,2,3,4,5];
var svgViewport = d3.select("body").append("svg").attr("width","400").attr("height","400");
var circleSelection = svgViewport.selectAll("circle").data(myData);
var circleElements = circleSelection.enter().append("circle");

We set the data variable

then We create the SVG viewport

then We bind the data to the circle elements

Then we append the circle elements.


Next - instead of setting the attributes as constants,

Let's define a named function to set the attribute values.

function myFunction () { return 25; }
myFunction();

We define myFunction to return the value of 25.

When evaluated - We see that the function returns the value of 25


Next let's put it into the circleElements attribute operators.

circleElements.attr("cx",myFunction).attr("cy",myFunction).attr("r",myFunction);

BROWSER - Hover over the circle elements.

As you can see this set all of the circleElement attributes we defined ... to 25


Recall that the D3 operators give us the data attribute of the element as the letter d as well as the selection index number as the letter i.


Now, let's write a simple named function that takes in these elements and does something with them.

function functionTwo (d,i) { return d * 25; }
functionTwo(1,2);


Next, let's change the circle Elements attributes by calling the attributes again, though this time with the functionTwo as the function we are passing in.

circleElements.attr("cx",functionTwo).attr("cy",functionTwo).attr("r",functionTwo);

BROWSER - Hover over the SVG circles

As you can see, the functionTwo was applied to each element.

And the D3 attribute operator provided the D and I arguments to the function.


Next, let's leave the radius constant and play around with the CX and CY variables

circleElements.attr("cx",functionTwo).attr("cy",functionTwo).attr("r",
		"25");

So now we know how to use the data bound to SVG elements.


Next, we look at how to use JavaScript Functions to style the different SVG elements according to their bound data.



Using Data to Style SVG Elements

selection.style(name[, value[, priority]])

The Style Operator, if a name and value are specified, sets the CSS style property for the given selection with the given specified value.

Earlier we set the style as a constant.

As you can now probably imagine, we can pass a function into the style operator as well.

The style operator provides us with the D for data and I for index variables.


Let's try a simple example to see how it works.


Going back to the SVG circle example.

BROWSER - Clear the screen and restart with these variables already typed in.

var myData = [1,2,3,4,5];
var svgViewport = d3.select("body").append("svg").attr("width","400").attr("height","400");
var circleSelection = svgViewport.selectAll("circle").data(myData);
var circleElements = circleSelection.enter().append("circle");

We set the data variable

We create the SVG viewport

We bind the data to the circle elements

Then we append the circle elements.


Next - let's use anonymous functions to set the CX and CY circle attributes

While leaving the radius constant.

circleElements.attr("cx",function(d,i) { return d * 25; })
    .attr("cy",function(d,i) { return d * 25; })
    .attr("r","25");

This gives us the 5 circles spread out diagonally towards the bottom right of the screen.


Next, let's write a function that colors the circles green or red

Depending on whether the index is odd or even.

function greenRed(d,i) {
    if (i % 2 === 0) { return "green"; }
    else { return "red"; };
}

This function takes in the variable d and i.

if i is divisible by two (using the modulus) then we return green

if i is not divisible by two then we return red.


We test it out

greenRed(1,2);

As and expected this returns "green".


Alright - let's style our circles

var circleStyle = circleElements.style("fill",greenRed);

As you can see, the circles are now alternating in color.

Also worth noting is that because D3 selections are zero-based arrays

The first circle is green.


There are many ways to style SVG and HTML elements based on functions.

D3 even provides some operators specifically for colors.

We will cover that later.

And with that, you can see how we can use the Data bound to SVG elements to style them.

<< Back To D3 Screencast and Written Tutorials Index