This is an attempt to integrate VisDock into Christopher Manning's Voronoi Diagram with Force Directed Nodes and Delaunay Links. A few modifications and addition of lines allow users to query Voronoi path elements. For more about VisDock, click here.
xxxxxxxxxx
<html>
<head>
<title>Voronoi Diagram with Force Directed Nodes and Delaunay Links</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<script src="https://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
circle {
stroke: #EFEDF5;
fill: #EFEDF5;
pointer-events: none;
}
line {
pointer-events: none;
stroke: #EFEDF5;
stroke-width: 2px;
opacity: .05;
}
path{
stroke: #EFEDF5;
stroke-width: 4px;
}
</style>
</head>
<body>
<div id="chart">
</div>
<link href="https://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.css" rel="stylesheet" type="text/css"/>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://rawgithub.com/visdockhub/newvisdock/master/master/visdock.js"></script>
<script src="https://rawgithub.com/visdockhub/newvisdock/master/master/2d.js"></script>
<script src="https://rawgithub.com/visdockhub/newvisdock/master/master/intersectionutilities.js"></script>
<script src="https://rawgithub.com/visdockhub/newvisdock/master/master/visdock.utils.js"></script>
<script type="text/javascript">
var w = 960;
h = 500;
radius = 5.25,
links = [],
simulate = true,
zoomToAdd = true,
// https://github.com/mbostock/d3/blob/master/lib/colorbrewer/colorbrewer.js#L105
color = d3.scale.quantize().domain([10000, 7250]).range(["#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"])
var numVertices = (w*h) / 3000;
var vertices = d3.range(numVertices).map(function(i) {
angle = radius * (i+10);
return {x: angle*Math.cos(angle)+(w/2), y: angle*Math.sin(angle)+(h/2)};
});
var d3_geom_voronoi = d3.geom.voronoi().x(function(d) { return d.x; }).y(function(d) { return d.y; })
var prevEventScale = 1;
var zoom = d3.behavior.zoom().on("zoom", function(d,i) {
if (zoomToAdd){
if (d3.event.scale > prevEventScale) {
angle = radius * vertices.length;
vertices.push({x: angle*Math.cos(angle)+(w/2), y: angle*Math.sin(angle)+(h/2)})
} else if (vertices.length > 2 && d3.event.scale != prevEventScale) {
vertices.pop();
}
force.nodes(vertices).start()
} else {
if (d3.event.scale > prevEventScale) {
radius+= .01
} else {
radius -= .01
}
vertices.forEach(function(d, i) {
angle = radius * (i+10);
vertices[i] = {x: angle*Math.cos(angle)+(w/2), y: angle*Math.sin(angle)+(h/2)};
});
force.nodes(vertices).start()
}
prevEventScale = d3.event.scale;
});
d3.select(window)
.on("keydown", function() {
// shift
if(d3.event.keyCode == 16) {
zoomToAdd = false
}
// s
if(d3.event.keyCode == 83) {
simulate = !simulate
if(simulate) {
force.start()
} else {
force.stop()
}
}
})
.on("keyup", function() {
zoomToAdd = true
})
VisDock.init("#chart", {width: w+200, height: h+200});//width + leftMargin + rightMargin +200, height + topMargin + bottomMargin)
VisDock.opacity = 0.5;
var viewport = VisDock.getViewport();
var svg = viewport
.call(zoom)
var force = d3.layout.force()
.charge(-300)
.size([w, h])
.on("tick", update);
force.nodes(vertices).start();
var circle = svg.selectAll("circle");
var path = svg.selectAll("path");
var link = svg.selectAll("line");
function update(e) {
VisDock.startChrome();
path = path.data(d3_geom_voronoi(vertices))
var id = 0;
path.enter().append("path").attr("class", "voronoi")
.attr("id", function(){
return "v" + id++;
})
// drag node by dragging cell
.call(d3.behavior.drag()
.on("drag", function(d, i) {
vertices[i] = {x: vertices[i].x + d3.event.dx, y: vertices[i].y + d3.event.dy}
})
)
.style("fill", function(d, i) { return color(0) })
path.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
.transition().duration(150).style("fill", function(d, i) { return color(d3.geom.polygon(d).area()) })
path.exit().remove();
circle = circle.data(vertices)
circle.enter().append("circle")
.attr("r", 0)
.transition().duration(1000).attr("r", 5);
circle.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
circle.exit().transition().attr("r", 0).remove();
link = link.data(d3_geom_voronoi.links(vertices))
link.enter().append("line")
link.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()
if(!simulate) force.stop()
for (var i = 0; i < d3.selectAll(".voronoi")[0].length; i++){
var id = d3.selectAll(".voronoi")[0][i].getAttributeNS(null, "id")
d3.selectAll("#_" + id).attr("d", d3.selectAll("#" + id).attr("d"))
}
VisDock.finishChrome();
}
/*d3.timer(function(){
VisDock.startChrome();
for (var i = 0; i < d3.selectAll(".voronoi")[0].length; i++){
var id = d3.selectAll(".voronoi")[0][i].getAttributeNS(null, "id")
d3.selectAll("#_" + id).attr("d", d3.selectAll("#" + id).attr("d"))
}
VisDock.finishChrome();
})*/
VisDock.eventHandler = {
getHitsPolygon : function(points, inclusive) {
var shapebound = new createPolygon(points);
return shapebound.intersectPath(d3.selectAll(".voronoi")[0], inclusive)
},
getHitsEllipse : function(points, inclusive) {
var shapebound = new createEllipse(points);
return shapebound.intersectPath(d3.selectAll(".voronoi")[0], inclusive)
},
getHitsLine : function(points, inclusive) {
var shapebound = new createLine(points);
return shapebound.intersectPath(d3.selectAll(".voronoi")[0], inclusive)
},
setColor : function(hits) {
var circleObjects = d3.selectAll("circle")[0];
QueryManager.layers[num - 1] = [];
for (var i = 0; i < hits.length; i++) {
var d = hits[i].getAttributeNS(null, "d")
QueryManager.layers[num - 1][i] = d3.select(hits[i].parentNode).append("path")
.attr("d", d)
.attr("style", "fill: " + VisDock.color[num - 1] + "; opacity: 0.5; pointer-events: none")
.attr("id", "_" + hits[i].getAttributeNS(null, "id"))
}
},
changeColor : function(color, query, index) {
for (var i = 0; i < query.length; i++) {
var visibility = query[i].attr("style").split("opacity: ")[1].split(";")[0]
query[i].attr("style", "opacity: " + visibility + "; fill: " + color)
}
},
changeVisibility : function(vis, query, index) {
var color = VisDock.utils.getQueryColor(index);
for (var i = 0; i < query.length; i++) {
var color = query[i].attr("style").split("fill: ")[1].split(";")[0]
query[i].attr("style", "opacity: " + vis + "; fill: " + color)
}
},
removeColor : function(hits, index) {
for (var i = 0; i < hits.length; i++) {
hits[i].remove();
}
},
}
BirdView.init(viewport, 1160, 700)
d3.select(self.frameElement).style("width", "1160px")
d3.select(self.frameElement).style("height", "700px")
</script>
</body>
</html>
Modified http://d3js.org/d3.v3.min.js to a secure url
Modified http://d3js.org/d3.v3.min.js to a secure url
Modified http://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.js to a secure url
Modified http://rawgithub.com/VisDockHub/NewVisDock/master/master/2D.js to a secure url
Modified http://rawgithub.com/VisDockHub/NewVisDock/master/master/IntersectionUtilities.js to a secure url
Modified http://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.utils.js to a secure url
https://d3js.org/d3.v3.min.js
https://d3js.org/d3.v3.min.js
https://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.js
https://rawgithub.com/VisDockHub/NewVisDock/master/master/2D.js
https://rawgithub.com/VisDockHub/NewVisDock/master/master/IntersectionUtilities.js
https://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.utils.js