|
(function() { |
|
var PADDING, SCALE, TIP, collapse, color, drag, get_color, get_info, global, height, redraw, svg, treemap, vis, width, zoom, zoomable_layer, |
|
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; |
|
|
|
global = {}; |
|
|
|
global.subtrees_data = []; |
|
|
|
SCALE = 200; |
|
|
|
PADDING = 0; |
|
|
|
TIP = 2; |
|
|
|
color = d3.scale.ordinal().domain(['Person', 'Organisation', 'Place', 'Work', 'Species', 'Event']).range(['#E14E5F', '#A87621', '#43943E', '#AC5CC4', '#2E99A0', '#2986EC']); |
|
|
|
treemap = d3.layout.treemap().size([SCALE, SCALE]).round(false).value(function(node) { |
|
return node.size; |
|
}); |
|
|
|
drag = d3.behavior.drag().origin(function(d) { |
|
return d; |
|
}); |
|
|
|
drag.on('dragstart', function() { |
|
return d3.event.sourceEvent.stopPropagation(); |
|
}); |
|
|
|
drag.on('drag', function(d) { |
|
d.x = d3.event.x; |
|
d.y = d3.event.y; |
|
return redraw(); |
|
}); |
|
|
|
svg = d3.select('svg'); |
|
|
|
width = svg.node().getBoundingClientRect().width; |
|
|
|
height = svg.node().getBoundingClientRect().height; |
|
|
|
svg.attr({ |
|
viewBox: "" + (-width / 2) + " " + (-height / 2) + " " + width + " " + height |
|
}); |
|
|
|
zoomable_layer = svg.append('g'); |
|
|
|
zoom = d3.behavior.zoom().scaleExtent([0.1, 10]).on('zoom', function() { |
|
return zoomable_layer.attr({ |
|
transform: "translate(" + (zoom.translate()) + ")scale(" + (zoom.scale()) + ")" |
|
}); |
|
}); |
|
|
|
svg.call(zoom); |
|
|
|
vis = zoomable_layer.append('g').attr({ |
|
transform: "translate(" + (-SCALE / 2) + "," + (-SCALE / 2) + ")" |
|
}); |
|
|
|
d3.json('http://wafi.iit.cnr.it/webvis/tmp/dbpedia/realOntologySunburst2.json', function(tree) { |
|
var subtree_data; |
|
|
|
treemap.nodes(tree); |
|
subtree_data = { |
|
tree: tree, |
|
x: 0, |
|
y: 0 |
|
}; |
|
tree.subtree = subtree_data; |
|
global.subtrees_data.push(subtree_data); |
|
return redraw(); |
|
}); |
|
|
|
redraw = function(duration) { |
|
var enter_nodes, enter_subtrees, links, nodes, subtrees; |
|
|
|
duration = duration != null ? duration : 0; |
|
links = vis.selectAll('.link').data(global.subtrees_data.filter(function(subtree_data) { |
|
return subtree_data.tree.depth !== 0; |
|
})); |
|
links.enter().append('path').attr({ |
|
"class": 'link' |
|
}); |
|
links.transition().duration(duration).attr({ |
|
d: function(subtree_data) { |
|
var alpha, parent, tip, x1, x2, y1, y2; |
|
|
|
parent = subtree_data.tree.parent.subtree; |
|
x1 = parent.x + subtree_data.tree.x + subtree_data.tree.dx / 2; |
|
y1 = parent.y + subtree_data.tree.y + subtree_data.tree.dy / 2; |
|
x2 = subtree_data.x + subtree_data.tree.x + subtree_data.tree.dx / 2; |
|
y2 = subtree_data.y + subtree_data.tree.y + subtree_data.tree.dy / 2; |
|
alpha = Math.atan2(y1 - y2, x2 - x1); |
|
tip = Math.min(TIP, subtree_data.tree.dx / 2, subtree_data.tree.dy / 2); |
|
return "M" + x1 + " " + y1 + " L" + (x2 - tip * Math.sin(alpha)) + " " + (y2 - tip * Math.cos(alpha)) + " L" + (x2 + tip * Math.sin(alpha)) + " " + (y2 + tip * Math.cos(alpha)); |
|
} |
|
}); |
|
links.exit().remove(); |
|
subtrees = vis.selectAll('.subtree').data(global.subtrees_data, function(st) { |
|
return st.tree.depth + '_' + st.tree.name; |
|
}); |
|
enter_subtrees = subtrees.enter().append('g').call(drag).attr({ |
|
"class": 'subtree' |
|
}); |
|
enter_subtrees.append('rect').attr({ |
|
"class": 'handle', |
|
x: function(subtree_data) { |
|
return subtree_data.tree.x - PADDING; |
|
}, |
|
y: function(subtree_data) { |
|
return subtree_data.tree.y - PADDING; |
|
}, |
|
width: function(subtree_data) { |
|
return subtree_data.tree.dx + 2 * PADDING; |
|
}, |
|
height: function(subtree_data) { |
|
return subtree_data.tree.dy + 2 * PADDING; |
|
} |
|
}).append('title').text(function(st) { |
|
return get_info(st.tree); |
|
}); |
|
enter_subtrees.append('text').text(function(subtree_data) { |
|
return subtree_data.tree.name + ((subtree_data.tree.parent != null) && subtree_data.tree.name === subtree_data.tree.parent.name ? ' alone' : ''); |
|
}).attr({ |
|
"class": 'label', |
|
x: function(subtree_data) { |
|
return subtree_data.tree.x + subtree_data.tree.dx / 2; |
|
}, |
|
y: function(subtree_data) { |
|
return subtree_data.tree.y; |
|
}, |
|
dy: '-0.35em' |
|
}); |
|
subtrees.transition().duration(duration).attr({ |
|
transform: function(subtree_data) { |
|
return "translate(" + subtree_data.x + "," + subtree_data.y + ")"; |
|
} |
|
}); |
|
subtrees.exit().remove(); |
|
nodes = subtrees.selectAll('.node').data(function(subtree_data) { |
|
if (subtree_data.tree.children != null) { |
|
return subtree_data.tree.children; |
|
} else { |
|
return []; |
|
} |
|
}); |
|
enter_nodes = nodes.enter().append('rect').attr({ |
|
"class": 'node', |
|
x: function(node) { |
|
return node.x; |
|
}, |
|
y: function(node) { |
|
return node.y; |
|
}, |
|
width: function(node) { |
|
return node.dx; |
|
}, |
|
height: function(node) { |
|
return node.dy; |
|
}, |
|
fill: function(node) { |
|
return get_color(node); |
|
} |
|
}); |
|
enter_nodes.on('click', function(node) { |
|
var subtree_data, x, y; |
|
|
|
if (d3.event.defaultPrevented) { |
|
return; |
|
} |
|
if (node.exploded === true) { |
|
collapse(node); |
|
redraw(); |
|
return; |
|
} |
|
node.exploded = true; |
|
x = d3.select(this.parentNode).datum().x; |
|
y = d3.select(this.parentNode).datum().y; |
|
subtree_data = { |
|
tree: node, |
|
x: x, |
|
y: y |
|
}; |
|
node.subtree = subtree_data; |
|
global.subtrees_data.push(subtree_data); |
|
redraw(); |
|
subtree_data.x += 30; |
|
subtree_data.y += 30; |
|
return window.requestAnimationFrame(function() { |
|
return redraw(1000); |
|
}); |
|
}); |
|
enter_nodes.append('title').text(function(node) { |
|
return get_info(node); |
|
}); |
|
nodes.classed('exploded', function(node) { |
|
return node.exploded; |
|
}); |
|
return nodes.exit().remove(); |
|
}; |
|
|
|
collapse = function(node) { |
|
if (node.children != null) { |
|
node.children.filter(function(n) { |
|
return n.exploded; |
|
}).forEach(function(n) { |
|
return collapse(n); |
|
}); |
|
} |
|
node.exploded = false; |
|
return global.subtrees_data = global.subtrees_data.filter(function(st) { |
|
return st.tree !== node; |
|
}); |
|
}; |
|
|
|
get_color = function(node) { |
|
var _ref; |
|
|
|
if (node.parent == null) { |
|
return '#7E7F7E'; |
|
} |
|
if (_ref = node.name, __indexOf.call(color.domain(), _ref) < 0) { |
|
return get_color(node.parent); |
|
} |
|
return color(node.name); |
|
}; |
|
|
|
get_info = function(node) { |
|
var subclasses; |
|
|
|
if (node.children != null) { |
|
subclasses = node.children.reduce((function(count, n) { |
|
if (n.name !== node.name) { |
|
return count + 1; |
|
} else { |
|
return count; |
|
} |
|
}), 0); |
|
} else { |
|
subclasses = 'no'; |
|
} |
|
return node.name + ((node.parent != null) && node.name === node.parent.name ? ' alone' : '') + '\n' + subclasses + ' subclasses' + '\n' + d3.format(',')(node.size) + ' instances'; |
|
}; |
|
|
|
}).call(this); |