book

More Drills

This and the next page contain several exercises to set you up on a path to become proficient in generating SVGs for visualizing data. For each exercise, a "desired viz" is given. You need to modify the code block and the template block to come up with your own solution to create a visualization as close to the desired visualization as possible. The SVG code of the desired viz is shown to give you a target as to what set of SVG tags and attributes you need to generate in order to render the desired visualization. You can also see the SVG code your code generates. You want to get your version of the SVG code as close as possible to the target SVG code.

By close, you don't need to get to the exact precision. For instance, if you see x='143.31413124123' in a SVG tag in the target code, it is good enough for your code to somehow get x to that range (e.g., 142, 143, 144) to produce a visualization that look almost identical to human eyes.

Note that the solution template code is slightly modified from the previous page in order to put all Javascript code in the same code block.

Exercises

Color the bar corresponding to USA[top]

Data [{"name":"China","pop":1393783836},{"name":"India","pop":1267401849},{"name":"USA","pop":322583006},{"name":"Indonesia","pop":252812243}]
Desired Viz
Actual Viz
<rect x="0"
      y="0"
     width="20"
     height="400"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="20"
      y="0"
     width="20"
     height="363.7298169958114"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="40"
      y="0"
     width="20"
     height="92.57762865891063"
     style="fill:blue;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="60"
      y="0"
     width="20"
     height="72.5542186586242"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="0"
     width="20"
     height="400"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="20"
      y="0"
     width="20"
     height="363.7298169958114"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="40"
      y="0"
     width="20"
     height="92.57762865891063"
     style="fill:blue;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="60"
      y="0"
     width="20"
     height="72.5542186586242"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: SVG Template
<rect x="${d.x}"
      y="0"
     width="20"
     height="${d.height}"
     style="fill:${d.color};
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: Javascript
function computeX(d, i) {
    return i * 20
}

function computeHeight(d, i) {
    return d.pop * (400 / 1393783836)// TODO
}

function computeColor(d, i) {
    if(d.name == 'USA'){
        return 'blue'
    }
    return 'red'
}

var viz = _.map(data, function(d, i){
            return {
                x: computeX(d, i),
                height: computeHeight(d, i),
                color: computeColor(d, i)
            }
         })
console.log(viz)

var result = _.map(viz, function(d){
         // invoke the compiled template function on each viz data
         return template({d: d})
     })
return result.join('\n')
Console
[{"x":0,"height":400,"color":"red"},{"x":20,"height":363.7298169958114,"color":"red"},{"x":40,"height":92.57762865891063,"color":"blue"},{"x":60,"height":72.5542186586242,"color":"red"}]

Align the bars at the bottom[top]

Data [{"name":"China","pop":1393783836},{"name":"India","pop":1267401849},{"name":"USA","pop":322583006},{"name":"Indonesia","pop":252812243}]
Desired Viz
Actual Viz
<rect x="0"
      y="0"
     width="20"
     height="400"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="20"
      y="36.270183004188596"
     width="20"
     height="363.7298169958114"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="40"
      y="307.4223713410894"
     width="20"
     height="92.57762865891063"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="60"
      y="327.4457813413758"
     width="20"
     height="72.5542186586242"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="0"
     width="20"
     height="400"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="20"
      y="36.270183004188596"
     width="20"
     height="363.7298169958114"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="40"
      y="307.4223713410894"
     width="20"
     height="92.57762865891063"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="60"
      y="327.4457813413758"
     width="20"
     height="72.5542186586242"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: SVG Template
<rect x="${d.x}"
      y="${d.y}"
     width="20"
     height="${d.height}"
     style="fill:${d.color};
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: Javascript
function computeX(d, i) {
    return i * 20
}

function computeHeight(d, i) {
    return d.pop * (400 / 1393783836)
}

function computeY(d, i) {
    return 400 - d.pop * (400 / 1393783836)
}

function computeColor(d, i) {
    return 'red'
}

var viz = _.map(data, function(d, i){
            return {
                x: computeX(d, i),
                y: computeY(d, i),
                height: computeHeight(d, i),
                color: computeColor(d, i)
            }
         })
console.log(viz)

var result = _.map(viz, function(d){
         // invoke the compiled template function on each viz data
         return template({d: d})
     })
return result.join('\n')
Console
[{"x":0,"y":0,"height":400,"color":"red"},{"x":20,"y":36.270183004188596,"height":363.7298169958114,"color":"red"},{"x":40,"y":307.4223713410894,"height":92.57762865891063,"color":"red"},{"x":60,"y":327.4457813413758,"height":72.5542186586242,"color":"red"}]

Add some margins between every two bars[top]

Data [{"name":"China","pop":1393783836},{"name":"India","pop":1267401849},{"name":"USA","pop":322583006},{"name":"Indonesia","pop":252812243}]
Desired Viz
Actual Viz
<rect x="0"
      y="0"
     width="20"
     height="400"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="30"
      y="36.270183004188596"
     width="20"
     height="363.7298169958114"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="60"
      y="307.4223713410894"
     width="20"
     height="92.57762865891063"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="90"
      y="327.4457813413758"
     width="20"
     height="72.5542186586242"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="0"
     width="20"
     height="400"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="30"
      y="36.270183004188596"
     width="20"
     height="363.7298169958114"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="60"
      y="307.4223713410894"
     width="20"
     height="92.57762865891063"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="90"
      y="327.4457813413758"
     width="20"
     height="72.5542186586242"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: SVG Template
<rect x="${d.x}"
      y="${d.y}"
     width="20"
     height="${d.height}"
     style="fill:${d.color};
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: Javascript
function computeX(d, i) {
    return i * 30
}

function computeHeight(d, i) {
    return d.pop * (400 / 1393783836)
}

function computeY(d, i) {
    return 400 - d.pop * (400 / 1393783836)
}

function computeColor(d, i) {
    return 'red'
}

var viz = _.map(data, function(d, i){
            return {
                x: computeX(d, i),
                y: computeY(d, i),
                height: computeHeight(d, i),
                color: computeColor(d, i)
            }
         })
console.log(viz)

var result = _.map(viz, function(d){
         // invoke the compiled template function on each viz data
         return template({d: d})
     })
return result.join('\n')
Console
[{"x":0,"y":0,"height":400,"color":"red"},{"x":30,"y":36.270183004188596,"height":363.7298169958114,"color":"red"},{"x":60,"y":307.4223713410894,"height":92.57762865891063,"color":"red"},{"x":90,"y":327.4457813413758,"height":72.5542186586242,"color":"red"}]

Reverse the order of the bars[top]

Data [{"name":"China","pop":1393783836},{"name":"India","pop":1267401849},{"name":"USA","pop":322583006},{"name":"Indonesia","pop":252812243}]
Desired Viz
Actual Viz
<rect x="0"
      y="327.4457813413758"
     width="20"
     height="72.5542186586242"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="20"
      y="307.4223713410894"
     width="20"
     height="92.57762865891063"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="40"
      y="36.270183004188596"
     width="20"
     height="363.7298169958114"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="60"
      y="0"
     width="20"
     height="400"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="60"
      y="0"
     width="20"
     height="400"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="40"
      y="36.270183004188596"
     width="20"
     height="363.7298169958114"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="20"
      y="307.4223713410894"
     width="20"
     height="92.57762865891063"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="327.4457813413758"
     width="20"
     height="72.5542186586242"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: SVG Template
<rect x="${d.x}"
      y="${d.y}"
     width="20"
     height="${d.height}"
     style="fill:${d.color};
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: Javascript
var size=(_.size(data)-1)*20
function computeX(d, i) {
    return size-i * 20
}

function computeHeight(d, i) {
    return d.pop * (400 / 1393783836)
}

function computeY(d, i) {
    return 400 - computeHeight(d,i)
}

function computeColor(d, i) {
    return 'red'
}

var viz = _.map(data, function(d, i){
            return {
                x: computeX(d, i),
                y: computeY(d, i),
                height: computeHeight(d, i),
                color: computeColor(d, i)
            }
         })
console.log(viz)

var result = _.map(viz, function(d){
         // invoke the compiled template function on each viz data
         return template({d: d})
     })
return result.join('\n')
Console
[{"x":60,"y":0,"height":400,"color":"red"},{"x":40,"y":36.270183004188596,"height":363.7298169958114,"color":"red"},{"x":20,"y":307.4223713410894,"height":92.57762865891063,"color":"red"},{"x":0,"y":327.4457813413758,"height":72.5542186586242,"color":"red"}]

Display bars horizontally[top]

Data [{"name":"China","pop":1393783836},{"name":"India","pop":1267401849},{"name":"USA","pop":322583006},{"name":"Indonesia","pop":252812243}]
Desired Viz
Actual Viz
<rect x="0"
      y="0"
     width="300"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="20"
     width="272.79736274685854"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="40"
     width="69.43322149418297"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="60"
     width="54.415663993968145"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="0"
     width="300"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="20"
     width="272.79736274685854"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="40"
     width="69.43322149418297"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<rect x="0"
      y="60"
     width="54.415663993968145"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: SVG Template
<rect x="${d.x}"
      y="${d.y}"
     width="${d.width}"
     height="${d.height}"
     style="fill:${d.color};
            stroke-width:3;
            stroke:rgb(0,0,0)" />
Solution: Javascript
function computeX(d, i) {
    return 0
}

function computeHeight(d, i) {
    return 20
}

function computeWidth(d, i) {
    return d.pop * (300 / 1393783836)
}

function computeY(d, i) {
    return 20 * i
}

function computeColor(d, i) {
    return 'red'
}

var viz = _.map(data, function(d, i){
            return {
                x: computeX(d, i),
                y: computeY(d, i),
                height: computeHeight(d, i),
                width: computeWidth(d, i),
                color: computeColor(d, i)
            }
         })
console.log(viz)

var result = _.map(viz, function(d){
         // invoke the compiled template function on each viz data
         return template({d: d})
     })
return result.join('\n')
Console
[{"x":0,"y":0,"height":20,"width":300,"color":"red"},{"x":0,"y":20,"height":20,"width":272.79736274685854,"color":"red"},{"x":0,"y":40,"height":20,"width":69.43322149418297,"color":"red"},{"x":0,"y":60,"height":20,"width":54.415663993968145,"color":"red"}]

Display a number next to each bar[top]

Data [{"name":"China","pop":1393783836},{"name":"India","pop":1267401849},{"name":"USA","pop":322583006},{"name":"Indonesia","pop":252812243}]
Desired Viz 1393783836 1267401849 322583006 252812243
Actual Viz 1393783836 1267401849 322583006 252812243
<g transform="translate(0 0)">
<rect width="300"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<text x="330" y="10">1393783836</text>
</g>
<g transform="translate(0 20)">
<rect width="272.79736274685854"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<text x="330" y="10">1267401849</text>
</g>
<g transform="translate(0 40)">
<rect width="69.43322149418297"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<text x="330" y="10">322583006</text>
</g>
<g transform="translate(0 60)">
<rect width="54.415663993968145"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<text x="330" y="10">252812243</text>
</g>
<g transform="translate(0 0)">
<rect width="300"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<text x="100" y="10">1393783836</text>
</g>
<g transform="translate(0 20)">
<rect width="272.79736274685854"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<text x="100" y="10">1267401849</text>
</g>
<g transform="translate(0 40)">
<rect width="69.43322149418297"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<text x="100" y="10">322583006</text>
</g>
<g transform="translate(0 60)">
<rect width="54.415663993968145"
     height="20"
     style="fill:red;
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<text x="100" y="10">252812243</text>
</g>
Solution: SVG Template
<g transform="translate(${d.x} ${d.y})">
<rect width="${d.width}"
     height="${d.height}"
     style="fill:${d.color};
            stroke-width:3;
            stroke:rgb(0,0,0)" />
<text x="100" y="10">${d.label}</text>
</g>
Solution: Javascript
function computeX(d, i) {
    return 0
}

function computeHeight(d, i) {
    return 20
}

function computeWidth(d, i) {
    return d.pop * (300 / 1393783836)
}

function computeY(d, i) {
    return 20 * i
}

function computeColor(d, i) {
    return 'red'
}

function computeLabel(d, i) {
    return d.pop
}

var viz = _.map(data, function(d, i){
            return {
                x: computeX(d, i),
                y: computeY(d, i),
                height: computeHeight(d, i),
                width: computeWidth(d, i),
                color: computeColor(d, i),
                label: computeLabel(d, i)
            }
         })
console.log(viz)

var result = _.map(viz, function(d){
         // invoke the compiled template function on each viz data
         return template({d: d})
     })
return result.join('\n')
Console
[{"x":0,"y":0,"height":20,"width":300,"color":"red","label":1393783836},{"x":0,"y":20,"height":20,"width":272.79736274685854,"color":"red","label":1267401849},{"x":0,"y":40,"height":20,"width":69.43322149418297,"color":"red","label":322583006},{"x":0,"y":60,"height":20,"width":54.415663993968145,"color":"red","label":252812243}]