Skip to content

Instantly share code, notes, and snippets.

@sxywu
Last active April 28, 2016 22:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sxywu/92841c212b11c534713782544cfdf10f to your computer and use it in GitHub Desktop.
Save sxywu/92841c212b11c534713782544cfdf10f to your computer and use it in GitHub Desktop.
openvis tweets #1
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.10.0/d3-legend.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.11.2/lodash.js'></script>
<link href='https://fonts.googleapis.com/css?family=Lora' rel='stylesheet' type='text/css'>
<style>
body {
font-family: 'Lora', serif;
margin:0;
}
#vis {
width:600px;
height: 2400px;
}
#body {
height: 100%;
position: fixed;
top: 0;
left: 650px;
right: 0px;
overflow: scroll;
}
#legend {
width: 100%;
height: 75px;
}
.tweet {
padding: 10px;
}
text {
font-size: .8em;
}
</style>
</head>
<body>
<svg id='vis'></svg>
<div id='body'>
<div>
Tweets with #openvisconf or @openvisconf. Click on the pies to view tweets.
</div>
<svg id='legend' />
<div id='title'></div>
<div id='content'></div>
</div>
<script>
d3.json('https://raw.githubusercontent.com/sxywu/fishy/master/clean-results_min.json', function(tweets) {
var radius = 40;
var width = radius * 2 + 40;
var take = 100;
var perRow = 5;
var color = d3.scale.ordinal()
.domain(['original', 'RT'])
.range(['#0088CC', '#F89406']);
var dateFormat = d3.time.format('%x %I:%M%p');
// group the tweets by user, then sort and take top 100
var usersSorted = _.chain(tweets.results)
.groupBy(function(t) {
t.date = new Date(t.postedTime);
return t.actor.preferredUsername
}).sortBy(function(t) {return -t.length})
.take(take)
.map(function(t) {
return {
tweets: t,
username: t[0].actor.preferredUsername,
length: t.length
};
}).value();
// calculate the radius for each user
var minRadius = d3.min(usersSorted, function(d) {return d.length});
var maxRadius = d3.max(usersSorted, function(d) {return d.length});
var radiusScale = d3.scale.log()
.domain([minRadius, maxRadius])
.range([radius / 4, radius]);
_.each(usersSorted, function(user) {
user.type = _.chain(user.tweets)
.groupBy(function(tweet) {
return tweet.body.match(/^RT/) || 'original'
}).map(function(tweets, type) {
return {
type: type,
tweets: tweets,
radius: radiusScale(user.length)
};
}).sortBy(function(type) {
return type.type === 'original' ? -1 : 1;
}).value();
});
//
var legend = d3.legend.color()
.shape("circle")
.shapePadding(10)
.scale(color);
d3.select('#legend')
.append('g')
.attr('transform', "translate(20,20)")
.call(legend);
var content = d3.select('#content');
var title = d3.select('#title');
// draw pies for each user
var pie = d3.layout.pie()
.value(function(type) {return type.tweets.length})
.sort(null);
var arc = d3.svg.arc()
.innerRadius(function(type) {return type.data.radius * 0.5})
.outerRadius(function(type) {return type.data.radius * 0.8});
var svg = d3.select('svg');
var circle = svg.selectAll('g')
.data(usersSorted)
.enter().append('g')
.attr('transform', function(d, i) {
return 'translate(' + ((i % perRow) * width + width / 2) +
',' + (Math.floor(i / perRow) * width + width / 2) + ')'
});
var pie = circle.selectAll('path')
.data(function(d) {return pie(d.type)})
.enter().append('path')
.attr("fill", function(type) {return color(type.data.type)})
.attr("d", arc)
.style('cursor', 'pointer')
.on('click', function(type) {
// opacity for selected pie
pie.attr('fill-opacity', 0.45);
d3.select(this)
.attr('fill-opacity', 1);
// put in the title
var user = type.data.tweets[0].actor.displayName;
var tweetLength = type.data.tweets.length;
var tweetType = type.data.type;
title.text(user + ' (' + tweetLength + ' ' + tweetType + ')');
console.log(type.data)
// add the tweets
var data = content.selectAll('.tweet')
.data(type.data.tweets);
data.enter().append('div')
.classed('tweet', true);
data.exit().remove();
// with the way data inheritance works
// it's just easier to first remove all children
// and then re-append them .____.
data.selectAll('div').remove();
data.append('div')
.text(function(d) {return dateFormat(d.date)});
data.append('div')
.style('cursor', 'pointer')
.on('click', function(d) {
window.open(d.link, '_new');
}).text(function(d) {console.log(d); return d.body});
});
circle.append('text')
.attr('y', radius)
.attr('text-anchor', 'middle')
.attr('dy', '.35em')
.style('cursor', 'pointer')
.text(function(d) {
return d.username + ' (' + d.tweets.length + ')';
}).on('click', function(d) {
window.open('http://twitter.com/' + d.username, '_new');
});
});
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment