pan using zoom behaviour, unfortunately not very smooth
-
-
Save unhammer/3811811 to your computer and use it in GitHub Desktop.
pan on drag with d3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -*- 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