|
svg = d3.select('svg') |
|
width = svg.node().getBoundingClientRect().width |
|
height = svg.node().getBoundingClientRect().height |
|
|
|
treemap = d3.layout.treemap() |
|
.size([width, height]) |
|
.value((node) -> node.freq) |
|
.sort((a,b) -> a.freq-b.freq) |
|
.ratio(4) |
|
.round(false) # bugfix: d3 wrong ordering |
|
|
|
correct_x = d3.scale.linear() |
|
.domain([0, width]) |
|
.range([0, width*1.05]) |
|
correct_y = d3.scale.linear() |
|
.domain([0, height]) |
|
.range([0, height*3/4]) |
|
|
|
color = (txt, light) -> |
|
Math.seedrandom(txt+'abcdef') |
|
noise = (W) -> Math.random()*W - W/2 |
|
d3.hcl(0+noise(360), 40, 40) |
|
|
|
# translate the viewBox to have (0,0) at the center of the vis |
|
svg |
|
.attr |
|
viewBox: "#{-width/2} #{-height/2} #{width} #{height}" |
|
|
|
# append a group for zoomable content |
|
zoomable_layer = svg.append('g') |
|
|
|
# define a zoom behavior |
|
zoom = d3.behavior.zoom() |
|
.scaleExtent([1,30]) # min-max zoom |
|
.on 'zoom', () -> |
|
# GEOMETRIC ZOOM |
|
zoomable_layer |
|
.attr |
|
transform: "translate(#{zoom.translate()})scale(#{zoom.scale()})" |
|
|
|
# bind the zoom behavior to the main SVG |
|
svg.call(zoom) |
|
|
|
# group the visualization |
|
vis = zoomable_layer.append('g') |
|
.attr |
|
transform: "translate(#{-width/2},#{-height/2})" |
|
|
|
#d3.json 'http://wafi.iit.cnr.it/cas-twmon/statistics/api/getVolumes.php', (data) -> |
|
d3.csv 'kw_twitter.csv', (data) -> |
|
data.forEach (d) -> d.freq = +d.freq |
|
tree = {children: data, name: "cassandra"} |
|
nodes_data = treemap.nodes(tree) |
|
#console.log data |
|
|
|
#nodes = vis.selectAll('.node') |
|
# .data(nodes_data.filter((node) -> node.depth is 1)) |
|
# |
|
#enter_nodes = nodes.enter().append('rect') |
|
# .attr |
|
# class: 'node' |
|
# x: (node) -> node.x |
|
# y: (node) -> node.y |
|
# width: (node) -> node.dx |
|
# height: (node) -> node.dy |
|
# fill: (node) -> color(node.keyword, true) |
|
|
|
labels = vis.selectAll('.label') |
|
.data(nodes_data.filter((node) -> node.depth is 1)) |
|
|
|
enter_labels = labels.enter().append('svg') |
|
.attr |
|
class: 'label' |
|
|
|
enter_labels.append('text') |
|
.text((node) -> node.keyword.toUpperCase()) |
|
.attr |
|
dy: '0.35em' |
|
fill: (node) -> color(node.keyword, false) |
|
.each (node) -> |
|
bbox = this.getBBox() |
|
bbox_aspect = bbox.width / bbox.height |
|
|
|
node_bbox = {width: node.dx, height: node.dy} |
|
node_bbox_aspect = node_bbox.width / node_bbox.height |
|
|
|
rotate = bbox_aspect >= 1 and node_bbox_aspect < 1 or bbox_aspect < 1 and node_bbox_aspect >= 1 |
|
node.label_bbox = { |
|
x: bbox.x+(bbox.width-correct_x(bbox.width))/2, |
|
y: bbox.y+(bbox.height-correct_y(bbox.height))/2, |
|
width: correct_x(bbox.width), |
|
height: correct_y(bbox.height) |
|
} |
|
|
|
if rotate |
|
node.label_bbox = { |
|
x: node.label_bbox.y, |
|
y: node.label_bbox.x, |
|
width: node.label_bbox.height, |
|
height: node.label_bbox.width |
|
} |
|
d3.select(this).attr('transform', 'rotate(-90)') |
|
|
|
|
|
enter_labels |
|
.attr |
|
x: (node) -> node.x |
|
y: (node) -> node.y |
|
width: (node) -> node.dx |
|
height: (node) -> node.dy |
|
viewBox: (node) -> "#{node.label_bbox.x} #{node.label_bbox.y} #{node.label_bbox.width} #{node.label_bbox.height}" |
|
preserveAspectRatio: 'none' |
|
|