From a53d5cbb44e8461441332f635c04ec7773818ece Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Sat, 11 May 2013 13:12:07 -0700 Subject: [PATCH] Optimize label hover Add entity IDs to the element class list, so that specific elements can be selected by ID rather than needing `filter`. --- css/map.css | 4 ++++ js/id/svg/labels.js | 37 ++++++++++++------------------------- test/spec/behavior/hover.js | 6 ++++-- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/css/map.css b/css/map.css index 46df73da6..56a1e7240 100644 --- a/css/map.css +++ b/css/map.css @@ -885,6 +885,10 @@ text.pointlabel { stroke-miterlimit: 1; } +text.proximate { + opacity: 0; +} + text.point { font-size: 10px; } diff --git a/js/id/svg/labels.js b/js/id/svg/labels.js index 475a8412a..abb0a9251 100644 --- a/js/id/svg/labels.js +++ b/js/id/svg/labels.js @@ -92,7 +92,7 @@ iD.svg.Labels = function(projection, context) { var tp = texts.enter() .append('text') - .attr('class', function(d, i) { return classes + ' ' + labels[i].classes;}) + .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; }) .append('textPath') .attr('class', 'textpath'); @@ -135,7 +135,7 @@ iD.svg.Labels = function(projection, context) { texts.enter() .append('text') - .attr('class', function(d, i) { return classes + ' ' + labels[i].classes; }); + .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; }); texts.attr('x', get(labels, 'x')) .attr('y', get(labels, 'y')) @@ -224,34 +224,21 @@ iD.svg.Labels = function(projection, context) { } - function hideOnMouseover() { + var layers = d3.select(this) + .selectAll('.layer-label, .layer-halo'); + + layers.selectAll('.proximate') + .classed('proximate', false); + var mouse = context.mouse(), pad = 50, rect = new RTree.Rectangle(mouse[0] - pad, mouse[1] - pad, 2*pad, 2*pad), - labels = _.pluck(rtree.search(rect, this), 'leaf'), - containsLabel = d3.set(labels), - selection = d3.select(this); + ids = _.pluck(rtree.search(rect, this), 'leaf'); - // ensures that simply resetting opacity - // does not force style recalculation - function resetOpacity() { - if (this._opacity !== '') { - this.style.opacity = ''; - this._opacity = ''; - } - } - - selection.selectAll('.layer-label text, .layer-halo path, .layer-halo text') - .each(resetOpacity); - - if (!labels.length) return; - selection.selectAll('.layer-label text, .layer-halo path, .layer-halo text') - .filter(function(d) { - return containsLabel.has(d.id); - }) - .style('opacity', 0) - .property('_opacity', 0); + if (!ids.length) return; + layers.selectAll('.' + ids.join(', .')) + .classed('proximate', true); } function name(d) { diff --git a/test/spec/behavior/hover.js b/test/spec/behavior/hover.js index 0d6d94aaf..cdb2cc01d 100644 --- a/test/spec/behavior/hover.js +++ b/test/spec/behavior/hover.js @@ -32,14 +32,16 @@ describe("iD.behavior.Hover", function() { describe("mouseover", function () { it("adds the .hover class to all elements to which the same datum is bound", function () { + var a = {id: 'a', type: 'node'}, + b = {id: 'b', type: 'node'}; + container.selectAll('span') - .data([{id: 'a'}, {id: 'b'}, {id: 'a'}, {id: 'b'}]) + .data([a, b, a, b]) .enter().append('span').attr('class', function(d) { return d.id; }); container.call(iD.behavior.Hover()); container.selectAll('.a').trigger('mouseover'); - expect(container.selectAll('.a.hover')[0]).to.have.length(2); expect(container.selectAll('.b.hover')[0]).to.have.length(0); });