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.
<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)" />
<rect x="${d.x}"
y="0"
width="20"
height="${d.height}"
style="fill:${d.color};
stroke-width:3;
stroke:rgb(0,0,0)" />
var height = 400; // svg window height
var maxPop = _.max(data,function(d){
return d.pop;
});
var scale = 400 / maxPop.pop;
function computeX(d, i) {
return i * 20
}
function computeHeight(d, i) {
return d.pop * scale;
}
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')
<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)" />
<rect x="${d.x}"
y="${d.y}"
width="20"
height="${d.height}"
style="fill:${d.color};
stroke-width:3;
stroke:rgb(0,0,0)" />
function computeX(d, i) {
return i * 20
}
function computeHeight(d, i, scale) {
return d.pop * scale;
}
function computeY(d, i,scale) {
return 400 - (d.pop * scale);
}
function computeColor(d, i) {
return 'red'
}
var viz = _.map(data, function(d, i, data){
var height = 400; // svg window height
var maxPop = _.max(data,function(d){
return d.pop;
});
var scale = height / maxPop.pop;
return {
x: computeX(d, i),
y: computeY(d, i, scale),
height: computeHeight(d, i, scale),
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')
<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)" />
<rect x="${d.x}"
y="${d.y}"
width="20"
height="${d.height}"
style="fill:${d.color};
stroke-width:3;
stroke:rgb(0,0,0)" />
var height = 400; // svg window height
var maxPop = _.max(data,function(d){
return d.pop;
});
var scale = 400 / maxPop.pop;
function computeX(d, i) {
return i * 30
}
function computeHeight(d, i, data) {
var height = 400; // svg window height
var maxPop = _.max(data,function(d){
return d.pop;
});
var scale = height / maxPop.pop;
return d.pop * scale;
}
function computeY(d, i) {
var height = 400; // svg window height
var maxPop = _.max(data,function(d){
return d.pop;
});
var scale = height / maxPop.pop;
return height - (d.pop * scale);
}
function computeColor(d, i) {
return 'red'
}
var viz = _.map(data, function(d, i, data){
return {
x: computeX(d, i),
y: computeY(d, i, data),
height: computeHeight(d, i, data),
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')
<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="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="${d.x}"
y="${d.y}"
width="20"
height="${d.height}"
style="fill:${d.color};
stroke-width:3;
stroke:rgb(0,0,0)" />
function computeX(d, i) {
return 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'
}
// reverse data array
_(data).reverse().value();
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')
<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)" />
<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)" />
function computeX(d, i) {
return 0
}
function computeHeight(d, i) {
return 20
}
function computeWidth(d, i, data) {
var width = 300; // max desired width
var maxPop = _.max(data,function(d){
return d.pop;
});
var scale = width / maxPop.pop;
return d.pop * scale;
}
function computeY(d, i) {
return 20 * i
}
function computeColor(d, i) {
return 'red'
}
var viz = _.map(data, function(d, i, data){
return {
x: computeX(d, i),
y: computeY(d, i),
height: computeHeight(d, i),
width: computeWidth(d, i, data),
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')
<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="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(${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="${d.labelx}" y="10">${d.label}</text>
</g>
function computeX(d, i) {
return 0
}
function computeHeight(d, i) {
return 20
}
function computeWidth(d, i, scale) {
return d.pop * scale;
}
function computeY(d, i) {
return 20 * i
}
function computeColor(d, i) {
return 'red'
}
function computeLabel(d, i) {
return d.pop
}
function computeLabelX(d, i, width) {
return width+30;
}
var viz = _.map(data, function(d, i, data){
var width = 300; // max desired width
var maxPop = _.max(data,function(d){
return d.pop;
});
var scale = width / maxPop.pop;
return {
x: computeX(d, i),
y: computeY(d, i),
height: computeHeight(d, i),
width: computeWidth(d, i, scale),
color: computeColor(d, i),
label: computeLabel(d, i),
labelx: computeLabelX(d,i,width)
}
})
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')