Upload
agileleague
View
262
Download
6
Tags:
Embed Size (px)
Citation preview
D3 + SVGsSmileys in realtime
Who is this guy?
• Micah Wedemeyer
• @micahwedemeyer
• The Agile League - Ruby on Rails consulting shop based in Atlanta
• http://www.agileleague.com
What is Smiler?
• Test app for showing off a few things you can do with D3 and SVGs
• Very fragile! Please be gentle. No extra points for hacking it. Any script kiddie could do it.
Log In!http://smiler.agileleague.com
Priming the PumpWhat do you think of…
Our Data Model
• A big array of votes
• Who, what, when
• How do we want to visualize it?
Charts: The Boring AnswerSure, they display the data
clearly…but is it coooooool?
D3: The Fun Answer** some assembly required
Heartbeat CheckAnyone still awake out there?
D3: Marrying Data to DOM• We have an array of votes
• We want cool stuff on the page
• D3 lets us map arrays onto DOM elements easily and without iterating
• We simply describe how we want a single array member handled, D3 extrapolates to the rest
TablesThe classic D3 Example
voteRow = d3.select('table.vote-list tbody’) .selectAll('tr').data(votes).enter().append('tr'); !voteRow.append('td').html(function(d) { return "<img src='" + d.get('user.avatarUrl') + "' />"; }); !voteRow.append('td').html(function(d) { if (d.get('score') > 0) { return "<img src='upvote.svg' />"; } else { return "<img src='downvote.svg' />"; } }); !voteRow.append('td').classed('timestamp', true).html(function(d) { var t; t = moment.unix(d.get('createdAt')); return "<time datetime='" + t.toISOString() + "'>" + t.fromNow() + "</time>"; });
Enter, Update, ExitTell D3 what to do in each case.
Dynamic Table
voteRow = d3.select('table.vote-list tbody') .selectAll('tr').data(votes); !// Update voteRow.select('td.timestamp').html(function(d) { var t = moment.unix(d.get('createdAt')); return "<time datetime='" + t.toISOString() + "'>" + t.fromNow() + "</time>"; }); !// Enter voteRow = voteRow.enter().append('tr'); voteRow.append('td').html(function(d) { return "<img src='" + d.get('user.avatarUrl') + "' />"; }); !voteRow.append('td').html(function(d) { if (d.get('score') > 0) { return "<img src='upvote.svg' />"; } else { return "<img src='downvote.svg' />"; } }); !voteRow.append('td').classed('timestamp', true).html(function(d) { var t; t = moment.unix(d.get('createdAt')); return "<time datetime='" + t.toISOString() + "'>" + t.fromNow() + "</time>"; });
Learn to Love JoinsYeah…it looks a little weird at first
voteRow = d3.select('table tbody') .selectAll('tr').data(votes) .enter().append('tr')
Still awake?Let’s double check
SVGsFor when you realize tables are boring
The Primitives
• rect
• circle
• ellipse
• line
• path - the ultimate primitive
Follow the spec
Finally, a W3C doc actually worth reading
Problem:We have data. We need x,y
coordinates.
Solution: ScalesScales translate your domain into another range
(often data domain to x,y for SVG)
someScale = d3.scale.linear() .domain([0, totalWorldPopulation]) .range([0, 100]); !!someScale(chinaPopulation) // => will be ~ 19 someScale(usaPopulation) // => will be ~ 4.5 someScale(japanPopulation) // => will be ~ 1.5 someScale(theMoonPopulation) // => will be 0 someScale(numStarsInTheUniverse) // => can go over 100..
Real ExampleColumn height in Smiler
var scoreScale = d3.scale.linear() .domain([-10, 0, 10]) .range([0, maxBarHeight, 0]) .clamp(true); !// Assume g is an SVG 'g' grouping var rect = g.select('rect'); rect.attr('y', function(d) { return scoreScale(d.score); }).attr('height', function(d) { return maxBarHeight - scoreScale(d.score); });
User Columns in Smiler
var scoreScale = d3.scale.linear() .domain([-10, 0, 10]) .range([0, maxBarHeight, 0]) .clamp(true); !// Assume g is an SVG 'g' grouping var rect = g.select('rect'); rect.attr('y', function(d) { return scoreScale(d.score); }).attr('height', function(d) { return maxBarHeight - scoreScale(d.score); });
Other Scales
• Time => (x,y)
• Value => Color
• Value => Angle
• Value => Transform / Scale
Putting it all togetherWith scales and SVG primitives comes great power
AnimationJust add .transition()
Can’t Draw? Cheat!Use someone else’s SVGs
M 297.29747,550.86823 C 283.52243,535.43191 249.1268,505.33855 220.86277,483.99412 C 137.11867,420.75228 125.72108,411.5999
91.719238,380.29088 C 29.03471,322.57071 2.413622,264.58086 2.5048478,185.95124 C 2.5493594,147.56739 5.1656152,132.77929
15.914734,110.15398 C 34.151433,71.768267 61.014996,43.244667 95.360052,25.799457 C
119.68545,13.443675 131.6827,7.9542046 172.30448,7.7296236 C 214.79777,7.4947896 223.74311,12.449347 248.73919,26.181459 C
279.1637,42.895777 310.47909,78.617167 316.95242,103.99205 L 320.95052,119.66445 L
330.81015,98.079942
Questions?