A plugin for d3.js. It follows the D3’s new 4.0 module pattern see Let’s Make a (D3) Plugin.
This layout is based on the excellent work of Ben Frederickson. It tries to be in line with d3.layout approach and declaration. Layouts take a set of input data, apply an algorithm or heuristic, and output the resulting positions/shapes for a cohesive display of the data.
One possible use case of this layout is to display a set of labelled nodes on their respective set as in the figure below:
An alternative and somehow more flexible approach is also available under the d3-foci layout
Venn sets are calculated on the basis of nodes set
properties .
Basically, it takes nodes data of this form :
var data = [
{"set":["A"],"name":"node_0"},
{"set":["B"],"name":"node_1"},
{"set":["B","A"],"name":"node_2"}
{"set":["B","A"],"name":"node_3"}
]
and calculates Venn sets like :
sets = [
{sets: ['A'], size: 1, nodes : ['node_0']},
{sets: ['B'], size: 1, nodes : ['node_1']},
{sets: ['A','B'], size: 2, nodes ['node_2', 'node_3']}
];
For calling and computing the layout :
var layout = d3.layout.venn().nodes(data);
By default, set area size are a count of nodes in the set.
- [interactive example](http://bl.ocks.org/christophe-g/2a491630dcc716fcb270) - [with d3.layout force and foci ](http://bl.ocks.org/christophe-g/b6c3135cc492e9352797) - [interactive, with area size as log of number of nodes](http://bl.ocks.org/christophe-g/c41f09c1c2bc71f10a20)# d3.layout.venn
Creates a new venn layout with the default settings: the default set accessor assumes each set data is an array of venn sets; the default size is 1×1; a default padding of 0 is applied; the default value accessor looks for value
property; the layout is caculated on the basis of venn.venn and nodes are packed inside their respective sets using d3.layout.pack. Also by default, the size of each sets are a count of the number of nodes.
# venn.nodes([nodes])
Runs the venn layout, returning the array of nodes. Each node is populated with the following attributes:
value
- the node value, as returned by the value accessor.x
- the computed x-coordinate of the node position.y
- the computed y-coordinate of the node position.r
- the computed node radius.
# venn.sets()
Returns a d3.map
of sets computed by the layout.
Each set has the folling properties:
center
- x,y key-value object representing the center of the set erea (computed by venn.computeTextCenter ).innerRadius
- the radius of the inner circle.d
- attrTween function for the path of the set area.nodes
- array of nodes contained by this set.
Once the layout created and runned We can draw the venn diagram like this:
colors = d3.scale.category10();
var vennArea = svg.selectAll("g.venn-area")
.data(layout.sets().values(), function(d) {
return d.__key__;
});
var vennEnter = vennArea.enter()
.append('g')
.attr("class", function(d) {
return "venn-area venn-" +
(d.sets.length == 1 ? "circle" : "intersection");
})
.attr('fill', function(d, i) {
return colors(i)
})
vennEnter.append('path')
.attr('class', 'venn-area-path')
.attr('d', function(d) {
return d.d(1)
});
vennEnter.append('circle')
.attr('class', 'inner')
.attr('fill', 'grey');
vennEnter.append("text")
.attr("class", "label")
.attr("text-anchor", "middle")
.attr("dy", ".35em")
vennArea.selectAll("text.label")
.text(function(d) {
return d.__key__;
})
.attr("x", function(d) {
return d.center.x
})
.attr("y", function(d) {
return d.center.y
});
In case of a transition, we would use attrTween like this:
vennArea.selectAll('path.venn-area-path').transition()
.duration(isFirstLayout ? 0 : test.duration())
.attrTween('d', function(d) {
return d.d
});
# venn.circles()
Returns key-value object of circles computed by they layout. Keys are are a concatenation of ordered set keys, joined with [,]
.
# venn.centres()
Returns key-value object with centers of all areas computed by the layout.
# venn.setsAccessor([setsAccessor])
When setAccessor is specified, defines the way sets are accessed for nodes. By default, it is the node.set
property. Otherwise, returns the current setsAccessor
# venn.setsSize([setsSize])
When setSize is specified, defines the way area size are modulated. By default, area set size are a count of the number of nodes they contain example of layout using log of set area size.
If not specified, this method return the currnet venn.setsSize
function.
# venn.packingStragegy([packingStragegy])
When packingStragegy is specified, defines the algorithm by which nodes' position are calculated. By default, d3.layout.pack is used for packing each node on the set area inner circle.
If packingStragegy is not specified, returns the current packingStragegy. Other startegies are available
# venn.packer()
Returns the current layout strategy ().
# venn.packingConfig([packingConfig])
Specify configs to be passed to the venn.packingStrategy
.
For example when the packing strategy is set to `venn.force' we can apply config to the force layout like :
venn.packingConfig({
charge: 0,
ticker: function() {
points.attr("cx", function(d) {
return d.x
})
.attr("cy", function(d) {
return d.y
})
}
})
//start the force layout
venn.packer().start()
# venn.size([size])
If size is specified, sets the available layout size to the specified two-element array of numbers representing x and y. If size is not specified, returns the current size, which defaults to 1×1.
# venn.orientation([orientation])
Orientation of the venn layout. by default, PI
/ 2.
# venn.normalize([normalize])
Set normalize to false
to prevent layout normalization.
# venn.pack(venn)
This is the default algorithm for packing nodes.
# venn.force(venn)
Use a d3.layout.force
, with foci at centers of each set eara.an example is available here.
In addition to the usual properties of the d3.layout.force
, this stategy can be further configures with :
collider
- a boolean value to resolve collision between nodes (default totrue
).maxRadius
- maximum radius for nodes used by the collider (default to8
).padding
- padding between nodes (default to3
).ticker
- a function called on every force layout tick.starter
- a function called onforce.start
event.ender
- a function called onforce.end
event.
# venn.distribute(venn)
Using random distribution to put nodes inside their area see an example here.
var layout = d3.layout.venn().
.packCircleFunction(d3.layout.venn.distribute);