From b90c5459abda2071761b2407f81d0db44a30bf96 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Sat, 24 Sep 2016 23:22:00 -0400 Subject: [PATCH] Add RatchetyInterpolator for breathe behavior The interpolator now just runs a few discrete steps, avoiding most of the repainting that was causing high CPU and noisy laptop fans. And it still looks pretty good. (closes #2911) --- modules/behavior/breathe.js | 52 +++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/modules/behavior/breathe.js b/modules/behavior/breathe.js index 9ba1eaacf..cc4433fe8 100644 --- a/modules/behavior/breathe.js +++ b/modules/behavior/breathe.js @@ -4,6 +4,7 @@ import _ from 'lodash'; export function Breathe() { var duration = 800, + steps = 4, selector = '.selected.shadow, .selected .shadow', selected = d3.select(null), classed = '', @@ -12,6 +13,19 @@ export function Breathe() { timer; + function ratchetyInterpolator(a, b, steps, units) { + a = parseFloat(a); + b = parseFloat(b); + var sample = d3.scaleQuantize() + .domain([0, 1]) + .range(d3.quantize(d3.interpolateNumber(a, b), steps)); + + return function(t) { + return String(sample(t)) + (units || ''); + }; + } + + function reset(selection) { selection .style('stroke-opacity', null) @@ -22,11 +36,39 @@ export function Breathe() { function setAnimationParams(transition, fromTo) { + var toFrom = (fromTo === 'from' ? 'to' : 'from'); + 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; }); + .styleTween('stroke-opacity', function(d) { + return ratchetyInterpolator( + params[d.id][toFrom].opacity, + params[d.id][fromTo].opacity, + steps + ); + }) + .styleTween('stroke-width', function(d) { + return ratchetyInterpolator( + params[d.id][toFrom].width, + params[d.id][fromTo].width, + steps, + 'px' + ); + }) + .styleTween('fill-opacity', function(d) { + return ratchetyInterpolator( + params[d.id][toFrom].opacity, + params[d.id][fromTo].opacity, + steps + ); + }) + .styleTween('r', function(d) { + return ratchetyInterpolator( + params[d.id][toFrom].width, + params[d.id][fromTo].width, + steps, + 'px' + ); + }); } @@ -60,7 +102,7 @@ export function Breathe() { function run(surface, fromTo) { - var toFrom = (fromTo === 'from' ? 'to': 'from'), + var toFrom = (fromTo === 'from' ? 'to' : 'from'), currSelected = surface.selectAll(selector), currClassed = surface.attr('class');