From 7d66e03c0bc692e363d5de96bc583a3a2b6375ba Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 25 Apr 2013 13:37:18 -0700 Subject: [PATCH] Redraw hovered vertices more efficiently (#1377) --- js/id/renderer/map.js | 14 +++--- js/id/svg/vertices.js | 99 +++++++++++++++++++++++-------------------- 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index bd3f405c0..6e8205f88 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -26,10 +26,6 @@ iD.Map = function(context) { tail = iD.ui.Tail(), surface, layergroup; - function visibleEntities() { - return context.intersects(map.extent()); - } - function map(selection) { context.history() .on('change.map', redraw); @@ -59,16 +55,16 @@ iD.Map = function(context) { .call(iD.svg.Surface(context)); surface.on('mouseover.vertices', function() { - vertices.hover(d3.event.target.__data__); if (map.editable() && !isTransformed()) { - surface.call(vertices, context.graph(), visibleEntities(), map.zoom()); + var hover = d3.event.target.__data__; + surface.call(vertices.drawHover, context.graph(), hover, map.zoom()); } }); surface.on('mouseout.vertices', function() { - vertices.hover(d3.event.relatedTarget && d3.event.relatedTarget.__data__); if (map.editable() && !isTransformed()) { - surface.call(vertices, context.graph(), visibleEntities(), map.zoom()); + var hover = d3.event.relatedTarget && d3.event.relatedTarget.__data__; + surface.call(vertices.drawHover, context.graph(), hover, map.zoom()); } }); @@ -126,7 +122,7 @@ iD.Map = function(context) { } else { surface .call(points, graph, all, filter) - .call(vertices, graph, visibleEntities(), map.zoom()) + .call(vertices, graph, all, map.zoom()) .call(lines, graph, all, filter, dimensions) .call(areas, graph, all, filter) .call(midpoints, graph, all, filter, extent) diff --git a/js/id/svg/vertices.js b/js/id/svg/vertices.js index 1640bd42a..b270d3f77 100644 --- a/js/id/svg/vertices.js +++ b/js/id/svg/vertices.js @@ -8,48 +8,44 @@ iD.svg.Vertices = function(projection, context) { var hover; - function visibleVertices() { - var visible = {}; + function siblingAndChildVertices(ids, graph) { + var vertices = {}; - function addChildVertices(entity, klass) { + function addChildVertices(entity) { var i; if (entity.type === 'way') { for (i = 0; i < entity.nodes.length; i++) { - visible[entity.nodes[i]] = klass; + vertices[entity.nodes[i]] = graph.entity(entity.nodes[i]); } } else if (entity.type === 'relation') { for (i = 0; i < entity.members.length; i++) { var member = context.hasEntity(entity.members[i].id); if (member) { - addChildVertices(member, klass); + addChildVertices(member); } } } else { - visible[entity.id] = klass; + vertices[entity.id] = entity; } } - function addSiblingAndChildVertices(id, klass) { + function addSiblingAndChildVertices(id) { var entity = context.hasEntity(id); if (entity && entity.type === 'node') { - visible[entity.id] = klass; + vertices[entity.id] = entity; context.graph().parentWays(entity).forEach(function(entity) { - addChildVertices(entity, klass); + addChildVertices(entity); }); } else if (entity) { - addChildVertices(entity, klass); + addChildVertices(entity); } } - if (hover) { - addSiblingAndChildVertices(hover.id, 'vertex-hover'); - } - - context.selection().forEach(function(id) { + ids.forEach(function(id) { addSiblingAndChildVertices(id, 'vertex-selected'); }); - return visible; + return vertices; } function isIntersection(entity, graph) { @@ -58,31 +54,7 @@ iD.svg.Vertices = function(projection, context) { }).length > 1; } - function drawVertices(surface, graph, entities, zoom) { - var visible = visibleVertices(), - vertices = []; - - for (var i = 0; i < entities.length; i++) { - var entity = entities[i]; - - if (entity.geometry(graph) !== 'vertex') - continue; - - // Vertices that have interesting tags or are intersections are - // always visible. We don't want them to get classed vertex-hover. - if (entity.hasInterestingTags()) - visible[entity.id] = 'tagged'; - if (isIntersection(entity, graph)) - visible[entity.id] = 'intersection'; - - if (entity.id in visible) { - vertices.push(entity) - } - } - - var groups = surface.select('.layer-hit').selectAll('g.vertex') - .data(vertices, iD.Entity.key); - + function draw(groups, graph, zoom) { var group = groups.enter() .insert('g', ':first-child') .attr('class', 'node vertex'); @@ -104,8 +76,6 @@ iD.svg.Vertices = function(projection, context) { groups.attr('transform', iD.svg.PointTransform(projection)) .call(iD.svg.TagClasses()) .call(iD.svg.MemberClasses(graph)) - .classed('vertex-hover', function(entity) { return visible[entity.id] === 'vertex-hover'; }) - .classed('vertex-selected', function(entity) { return visible[entity.id] === 'vertex-selected'; }) .classed('tagged', function(entity) { return entity.hasInterestingTags(); }) .classed('shared', function(entity) { return graph.isShared(entity); }); @@ -175,10 +145,45 @@ iD.svg.Vertices = function(projection, context) { .remove(); } - drawVertices.hover = function(_) { - if (!arguments.length) return hover; - hover = _; - return drawVertices; + function drawVertices(surface, graph, entities, zoom) { + var selected = siblingAndChildVertices(context.selection(), graph), + vertices = []; + + for (var i = 0; i < entities.length; i++) { + var entity = entities[i]; + + if (entity.geometry(graph) !== 'vertex') + continue; + + if (entity.id in selected || + entity.hasInterestingTags() || + isIntersection(entity, graph)) { + vertices.push(entity) + } + } + + surface.select('.layer-hit').selectAll('g.vertex.vertex-persistent') + .data(vertices, iD.Entity.key) + .call(draw, graph, zoom) + .classed('vertex-persistent', true); + + drawHover(surface, graph, zoom); + } + + function drawHover(surface, graph, zoom) { + var hovered = hover ? siblingAndChildVertices([hover.id], graph) : {}; + + surface.select('.layer-hit').selectAll('g.vertex.vertex-hover') + .data(d3.values(hovered), iD.Entity.key) + .call(draw, graph, zoom) + .classed('vertex-hover', true); + } + + drawVertices.drawHover = function(surface, graph, _, zoom) { + if (hover !== _) { + hover = _; + drawHover(surface, graph, zoom); + } }; return drawVertices;