Skip to content

Instantly share code, notes, and snippets.

@unhammer
Forked from mbostock/.block
Created October 1, 2012 13:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save unhammer/3811811 to your computer and use it in GitHub Desktop.
Save unhammer/3811811 to your computer and use it in GitHub Desktop.
pan on drag with d3

pan using zoom behaviour, unfortunately not very smooth

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<style type="text/css">
body {
font-size:1em;
font-weight:400;
word-spacing:normal;
letter-spacing:normal;
text-transform:none;
font-size-adjust:.58;
color:#000;
background:#FFF;
line-height:1.58em;
border-top:0;
border-left:0;
border-bottom:0;
border-right:0;
width:auto;
margin:1.58em 5% 1.58em 8%;
padding:0;
font-family: "Headland One", serif;
}
#vis {
font-size: 0.6em;
}
.background {
fill: none;
pointer-events: all;
}
.node {
fill: #555;
}
.synset {
font-size: 100%;
}
.queried {
font-size: 140%;
font-weight: bold;
}
.synset:hover, #hits li:hover {
font-weight: bold;
}
sub {
color: #666;
}
.highlight {
font-weight: bold;
font-size: 200%;
}
.extlink {
display: none;
}
#hits li:hover .extlink {
display: inline;
}
.link {
fill: none;
stroke: #000000;
stroke-width: 1.5px;
}
/* Colours based on d3.scale.category10 */
.concerns { stroke: #ff7f0e; color: #ff7f0e; }
.domain { stroke: #d62728; color: #d62728; }
.eqHypernymOf { stroke: #e377c2; color: #e377c2; }
.eqHyponymOf { stroke: #7f7f7f; color: #7f7f7f; }
.eqSynonymOf { stroke: #8c564b; color: #8c564b; }
.hypernymOf { stroke: #2ca02c; color: #2ca02c; }
.hyponymOf { stroke: #9467bd; color: #9467bd; }
.instanceOf { stroke: #bcbd22; color: #bcbd22; }
.involvedAgent { stroke: #17becf; color: #17becf; }
.involvedInstrument { stroke: #1f77b4; color: #1f77b4; }
.involvedPatient { stroke: #8c6d31; color: #8c6d31; }
.locationHolonymOf { stroke: #e7ba52; color: #e7ba52; }
.locationMeronymOf { stroke: #bd9e39; color: #bd9e39; }
.madeBy { stroke: #fd8d3c; color: #fd8d3c; }
.madeofHolonymOf { stroke: #6b6ecf; color: #6b6ecf; }
.madeofMeronymOf { stroke: #756bb1; color: #756bb1; }
.memberHolonymOf { stroke: #9edae5; color: #9edae5; }
.memberMeronymOf { stroke: #843c39; color: #843c39; }
.meronymOf { stroke: #636363; color: #636363; }
.nearAntonymOf { stroke: #b5cf6b; color: #b5cf6b; }
.nearSynonymOf { stroke: #393b79; color: #393b79; }
.partHolonymOf { stroke: #a55194; color: #a55194; }
.partMeronymOf { stroke: #c49c94; color: #c49c94; }
.roleAgent { stroke: #7b4173; color: #7b4173; }
.rolePatient { stroke: #8ca252; color: #8ca252; }
.usedFor { stroke: #9e9aa8; color: #9e9aa8; }
.usedForObject { stroke: #9c9ede; color: #9c9ede; }
.usedForQualifiedBy { stroke: #98df8a; color: #98df8a; }
.xposNearSynonymOf { stroke: #a1a1a1; color: #a1a1a1; }
#relnames {
float: right;
line-height:1em;
}
text .left {
text-anchor: end;
}
</style>
</head>
<body>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.6.0"></script>
<div id="vis">
</div>
<script type="text/javascript" src="pan.js"></script>
</body>
</html>
// -*- indent-tabs-mode: nil; tab-width: 2; js2-basic-offset: 2; coding: utf-8 -*-
/* global d3, Modernizr, history, console, repl */
var json = {
"nodes": [
{"name": "smile", "ontological_type": "UnboundedEvent+Agentive+Communication+Social", "queried": "true", "synset_id": "31528", "synset_id_da": "21978", "synset_id_pwn": "smile%2:29:00::"},
{"name": "domain"},
{"name": "psykologi", "synset_id": "3030"},
{"name": "xposNearSynonymOf"},
{"name": "uttrykk", "synset_id": "6664"},
{"name": "hyponymOf"},
{"name": "uttrykke, uttrykkje", "synset_id": "18802"}
],
"links": [
{"source": 0, "target": 1},
{"source": 1, "target": 2},
{"source": 0, "target": 3},
{"source": 3, "target": 4},
{"source": 0, "target": 5},
{"source": 5, "target": 6}
]
};
var div = d3.select("#vis");
var width = 900,
height = 600,
padding = 20,
wordsPerSynset = 3,
precalcTicksRate = 4,
precalcTicksMin = 200;
var svg = div.append("svg")
.attr("width", width + padding * 2)
.attr("height", height + padding * 2);
var visF = svg.append("g").attr("id", "visF"); // force layout
function linkClass(d) {
return "link " +
( d.source.synset_id ?
d.target.name :
d.source.name );
}
function redrawVisF () {
visF.attr("transform","translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
}
var force = d3.layout.force()
.charge(-440)
.linkDistance(70)
.size([width, height]);
function updateForce(json) {
var nodes = json.nodes;
var links = json.links;
visF.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom().on("zoom", redrawVisF));
// I'm guessing since array indices are used as keys, the below
// exits don't fully work. How can we make exit() key on synset_id
// instead?
visF.selectAll("line.link").data([]).exit().remove();
visF.selectAll("text.node").data([]).exit().remove();
force
.nodes(nodes)
.links(links);
// Initialize the positions deterministically, for better results.
nodes.forEach(function(d, i) { d.x = d.y = width / nodes.length * i; });
// Run the layout a fixed number of times, scaled by graph size
force.start();
for (var i = precalcTicksMin+precalcTicksRate*nodes.length; i > 0; --i) force.tick();
force.stop();
var link = visF.selectAll("line.link").data(links);
var linkEnter = link.enter()
.append("svg:line")
.attr("class", linkClass)
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; })
;
link.exit().remove();
var text = visF.selectAll("text.node").data(json.nodes);
var textEnter = text.enter()
.append("svg:text")
.attr("class", function(d){
return "node"
+ (d.queried ? " queried" : "")
+ (d.synset_id ? " synset" : " relation");
})
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.attr("text-anchor", function(d) {
var xWeight = links
.map(function(l){
if (l.source==d) return l.target.x - d.x;
else if(l.target==d) return l.source.x - d.x;
else return 0; // shouldn't happen?
})
.reduce(function(a,b){ return a+b; },
0);
return xWeight < 0 ? "start" : "end";
})
.text(function(d, i) { return d.name ; })
.on("click", function(d){console.log("clicked "+d.name);});
textEnter.append("title").text(function(d){return d.synset_id ? d.synset_id + ": " + d.name : "";});
text.exit().remove();
// allow mouse-dragging of individual nodes?
//text.call(force.drag);
}
updateForce(json);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment