|
(function() { |
|
var correct_x, correct_y, height, svg, treemap, vis, width, zoom, zoomable_layer; |
|
|
|
svg = d3.select('svg'); |
|
|
|
width = svg.node().getBoundingClientRect().width; |
|
|
|
height = svg.node().getBoundingClientRect().height; |
|
|
|
treemap = d3.layout.treemap().size([width, height]).value(function(node) { |
|
return node.count; |
|
}).sort(function(a, b) { |
|
return a.polarity - b.polarity; |
|
}).ratio(4); |
|
|
|
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]); |
|
|
|
svg.attr({ |
|
viewBox: "" + (-width / 2 - 5) + " " + (-height / 2 - 5) + " " + (width + 10) + " " + (height + 10) |
|
}); |
|
|
|
zoomable_layer = svg.append('g'); |
|
|
|
zoom = d3.behavior.zoom().scaleExtent([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(" + (-width / 2) + "," + (-height / 2) + ")" |
|
}); |
|
|
|
d3.json('http://tour-pedia.org/api/getOpinions?location=Paris&language=es', function(data) { |
|
var NEUTRAL, best, color, enter_labels, fake_tree, labels, nodes_data, words, words_frequency, worst; |
|
|
|
words = data.target; |
|
words_frequency = []; |
|
best = 0; |
|
worst = 0; |
|
Object.keys(words).forEach(function(word_lemma) { |
|
var o; |
|
|
|
o = words[word_lemma]; |
|
o.lemma = word_lemma.trim(); |
|
if (o.lemma.length <= 1) { |
|
return; |
|
} |
|
words_frequency.push(o); |
|
best = Math.max(best, o.polarity); |
|
return worst = Math.min(worst, o.polarity); |
|
}); |
|
fake_tree = { |
|
children: words_frequency |
|
}; |
|
NEUTRAL = 80; |
|
color = d3.scale.linear().domain([worst, 0, best]).range([d3.hcl(NEUTRAL - 80, 85, 50), d3.hcl(NEUTRAL, 85, 70), d3.hcl(NEUTRAL + 80, 85, 50)]).interpolate(d3.interpolateHcl); |
|
nodes_data = treemap.nodes(fake_tree); |
|
labels = vis.selectAll('.label').data(nodes_data.filter(function(node) { |
|
return node.depth === 1; |
|
})); |
|
enter_labels = labels.enter().append('svg').attr({ |
|
"class": 'label' |
|
}); |
|
enter_labels.append('text').text(function(node) { |
|
return node.lemma.toUpperCase(); |
|
}).attr({ |
|
dy: '0.35em', |
|
fill: function(node) { |
|
return color(node.polarity); |
|
} |
|
}).each(function(node) { |
|
var bbox, bbox_aspect, node_bbox, node_bbox_aspect, rotate; |
|
|
|
bbox = this.getBBox(); |
|
bbox_aspect = 2; |
|
node_bbox = { |
|
width: node.dx, |
|
height: node.dy |
|
}; |
|
node_bbox_aspect = node_bbox.width / node_bbox.height; |
|
rotate = bbox_aspect >= 1 && node_bbox_aspect < 1 || bbox_aspect < 1 && 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 |
|
}; |
|
return d3.select(this).attr('transform', 'rotate(-90)'); |
|
} |
|
}); |
|
return enter_labels.attr({ |
|
x: function(node) { |
|
return node.x; |
|
}, |
|
y: function(node) { |
|
return node.y; |
|
}, |
|
width: function(node) { |
|
return node.dx; |
|
}, |
|
height: function(node) { |
|
return node.dy; |
|
}, |
|
viewBox: function(node) { |
|
return "" + node.label_bbox.x + " " + node.label_bbox.y + " " + node.label_bbox.width + " " + node.label_bbox.height; |
|
}, |
|
preserveAspectRatio: 'none' |
|
}); |
|
}); |
|
|
|
}).call(this); |
The color scale has some issues if the user is interested in comparing positive with negative polarity values. The most green word has not in general the same absolute value of the most red word, since positive and negative values are normalized separately.