Skip to content

Instantly share code, notes, and snippets.

@sxywu
Last active April 29, 2016 03:06
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/8b7d381614a093195eec2636cab9ef2f to your computer and use it in GitHub Desktop.
Save sxywu/8b7d381614a093195eec2636cab9ef2f to your computer and use it in GitHub Desktop.
openvis tweets #2

Relationship between twitter users during Openvis Conf. Lines indicate mentions, from source to target in clockwise fashion.

--

Built with blockbuilder.org

forked from sxywu's block: 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;
}
svg {
width: 900px;
height: 600px;
}
text {
font-size: .8em;
}
</style>
</head>
<body>
<svg></svg>
<script>
d3.json('https://raw.githubusercontent.com/sxywu/fishy/master/clean-results_min.json', function(response) {
var radius = 40;
var force = d3.layout.force()
.size([900, 600])
.linkDistance(175)
.charge(function(d) {return -d.length * 10})
.on('tick', updatePositions);
var tweets = {};
var users = _.chain(response.results)
.filter(function(t) {
return !t.body.match(/^RT/);
}).groupBy(function(t) {
t.date = new Date(t.postedTime);
// save the tweets by their links
tweets[t.link] = t;
return t.actor.preferredUsername
}).sortBy(function(t, username) {
return -t.length;
}).reduce(function(obj, t) {
var username = t[0].actor.preferredUsername;
obj[username] = {
tweets: t,
username: username,
length: t.length
};
return obj;
}, {}).value();
var links = {};
_.each(tweets, function(tweet) {
// go through each tweet and make links
// based on mentions
var sourceUser = tweet.actor.preferredUsername;
_.each(tweet.twitter_entities.user_mentions, function(mention) {
var targetUser = mention.screen_name;
// if (!users[targetUser]) {
// users[targetUser] = {
// tweets: [],
// username: targetUser,
// length: 0
// };
// }
if (users[targetUser]) {
var link = links[sourceUser + ',' + targetUser];
if (!link) {
link = links[sourceUser + ',' + targetUser] = {
source: users[sourceUser],
target: users[targetUser],
count: 0
};
}
link.count += 1;
}
});
});
var usersArray = _.values(users);
var linksArray = _.values(links);
// calculate the radius for each user
var minRadius = d3.min(usersArray, function(d) {return d.length});
var maxRadius = d3.max(usersArray, function(d) {return d.length});
var radiusScale = d3.scale.linear()
.domain([minRadius, maxRadius])
.range([radius / 10, radius]);
var svg = d3.select('svg');
var link = svg.selectAll('path')
.data(linksArray)
.enter().append('path')
.attr('fill', 'none')
.attr('stroke', '#F89406')
.attr('stroke-width', function(d) {return d.count})
.attr('stroke-opacity', 0.25);
var circle = svg.selectAll('g')
.data(usersArray)
.enter().append('g')
.on('mouseenter', hoverNode)
.on('mouseleave', unhoverNode)
.call(force.drag);
circle.append('circle')
.attr('fill-opacity', 0.5)
.attr('fill', '#0088CC')
.attr('r', function(d) {
d.radius = radiusScale(d.length);
return d.radius;
});
circle
.append('text')
.attr('opacity', function(d) {return d.radius > radius / 8 ? 1 : 0})
.attr('text-anchor', 'middle')
.style('pointer-events', 'none')
.text(function(d) {return d.username});
force.nodes(usersArray).links(linksArray);
force.start();
function updatePositions() {
circle.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';
});
link.attr('d', linkArc);
}
// link arc function from https://bl.ocks.org/mbostock/1153292
function linkArc(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y +
"A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}
function hoverNode(d) {
var username = d.username;
var highlightedNodes = {};
// when they hover node, highlight the node
// and nodes it's attached to
link.attr('stroke-opacity', function(d) {
if (d.source.username === username ||
d.target.username === username) {
highlightedNodes[d.source.username] = 1;
highlightedNodes[d.target.username] = 1;
return .75;
}
return 0;
});
circle.selectAll('circle')
.attr('fill-opacity', function(d) {
return highlightedNodes[d.username] ? .75 : 0;
});
circle.selectAll('text')
.attr('opacity', function(d) {
return highlightedNodes[d.username] ? 1 : 0;
});
}
function unhoverNode() {
link.attr('stroke-opacity', 0.25);
circle.selectAll('circle')
.attr('fill-opacity', 0.5);
circle.selectAll('text')
.attr('opacity', function(d) {return d.radius > radius / 8 ? 1 : 0});
};
});
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment