diff --git a/css/map.css b/css/map.css index 4a537591f..3c786a6fb 100644 --- a/css/map.css +++ b/css/map.css @@ -43,11 +43,6 @@ path.shadow { pointer-events: stroke; } -.shadow { - -webkit-transition: 200ms; - -moz-transition: 200ms; - transition: 200ms; -} /* points */ @@ -133,11 +128,11 @@ g.vertex.vertex-hover { g.vertex.hover:not(.selected) .shadow, g.midpoint.hover:not(.selected) .shadow { - fill-opacity: 0.3; + fill-opacity: 0.5; } g.vertex.selected .shadow { - fill-opacity: 0.5; + fill-opacity: 0.7; } .mode-draw-area g.midpoint, @@ -172,7 +167,7 @@ path.shadow { } path.shadow.hover:not(.selected) { - stroke-opacity: 0.3; + stroke-opacity: 0.4; } path.shadow.selected { @@ -1566,10 +1561,10 @@ text.gpx { } .fill-wireframe path.shadow.hover:not(.selected) { - stroke-opacity: 0.2; + stroke-opacity: 0.4; } .fill-wireframe path.shadow.selected { - stroke-opacity: 0.4; + stroke-opacity: 0.6; } .fill-wireframe .point, diff --git a/index.html b/index.html index 42522a2bf..e51b6ef9b 100644 --- a/index.html +++ b/index.html @@ -178,6 +178,7 @@ + diff --git a/js/id/behavior/breathe.js b/js/id/behavior/breathe.js new file mode 100644 index 000000000..379c49adf --- /dev/null +++ b/js/id/behavior/breathe.js @@ -0,0 +1,105 @@ +iD.behavior.Breathe = function() { + var duration = 800, + selector = '.selected.shadow, .selected .shadow', + selected = d3.select(null), + classed = [], + params = {}, + done; + + function reset(selection) { + selection + .style('stroke-opacity', null) + .style('stroke-width', null) + .style('fill-opacity', null) + .style('r', null); + } + + function setAnimationParams(transition, fromTo) { + transition + .style('stroke-opacity', function(d) { return params[d.id][fromTo].opacity; }) + .style('stroke-width', function(d) { return params[d.id][fromTo].width; }) + .style('fill-opacity', function(d) { return params[d.id][fromTo].opacity; }) + .style('r', function(d) { return params[d.id][fromTo].width; }); + } + + function calcAnimationParams(selection) { + selection + .call(reset) + .each(function(d) { + var s = d3.select(this), + tag = s.node().tagName, + p = {'from': {}, 'to': {}}, + opacity, width; + + // determine base opacity and width + if (tag === 'circle') { + opacity = parseFloat(s.style('fill-opacity') || 0.5); + width = parseFloat(s.style('r') || 15.5); + } else { + opacity = parseFloat(s.style('stroke-opacity') || 0.7); + width = parseFloat(s.style('stroke-width') || 10); + } + + // calculate from/to interpolation params.. + p.tag = tag; + p.from.opacity = opacity * 0.6; + p.to.opacity = opacity * 1.25; + p.from.width = width * 0.9; + p.to.width = width * (tag === 'circle' ? 1.5 : 1.25); + params[d.id] = p; + }); + } + + function run(surface, fromTo) { + var toFrom = (fromTo === 'from' ? 'to': 'from'), + currSelected = surface.selectAll(selector), + currClassed = Array.prototype.slice.call(surface.node().classList), + n = 0; + + if (done || currSelected.empty()) { + selected.call(reset); + return; + } + + if (!_.isEqual(currSelected, selected) || !_.isEqual(currClassed, classed)) { + selected.call(reset); + classed = _.clone(currClassed); + selected = currSelected.call(calcAnimationParams); + } + + selected + .transition() + .call(setAnimationParams, fromTo) + .duration(duration) + .each(function() { ++n; }) + .each('end', function() { + if (!--n) { // call once + surface.call(run, toFrom); + } + }); + } + + var breathe = function(surface) { + done = false; + d3.timer(function() { + if (done) return true; + + var currSelected = surface.selectAll(selector); + if (currSelected.empty()) return false; + + surface.call(run, 'from'); + return true; + }, 200); + }; + + breathe.off = function(surface) { + done = true; + d3.timer.flush(); + selected + .transition() + .call(reset) + .duration(0); + }; + + return breathe; +}; diff --git a/js/id/modes/select.js b/js/id/modes/select.js index db821f137..f016f5b92 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -9,6 +9,7 @@ iD.modes.Select = function(context, selectedIDs) { behaviors = [ iD.behavior.Copy(context), iD.behavior.Paste(context), + iD.behavior.Breathe(context), iD.behavior.Hover(context), iD.behavior.Select(context), iD.behavior.Lasso(context), diff --git a/test/index.html b/test/index.html index d551f6667..1fa6301c8 100644 --- a/test/index.html +++ b/test/index.html @@ -157,6 +157,7 @@ +