Skip to content

Commit

Permalink
Fix #37 - synchronous evaluation.
Browse files Browse the repository at this point in the history
We can’t wait until the tweens are initialized in transition.{attr,style,text};
we must compute the target value synchronously. The resulting value is stored in
a map on the transition schedule so that tweens can still be efficiently copied
on write and shared across instances.
  • Loading branch information
mbostock committed Feb 23, 2016
1 parent 56655da commit b2230df
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 24 deletions.
22 changes: 11 additions & 11 deletions src/transition/attr.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {interpolate, interpolateTransform} from "d3-interpolate";
import {namespace, namespaces} from "d3-selection";
import {tweenValue} from "./tween";

// TODO Assumes either ALL selected nodes are SVG, or none are.
function attrInterpolate(node, name) {
Expand All @@ -23,7 +24,7 @@ function attrRemoveNS(fullname) {
function attrConstant(name, value1) {
var value00,
interpolate0;
return value1 += "", function() {
return function() {
var value0 = this.getAttribute(name);
return value0 === value1 ? null
: value0 === value00 ? interpolate0
Expand All @@ -34,7 +35,7 @@ function attrConstant(name, value1) {
function attrConstantNS(fullname, value1) {
var value00,
interpolate0;
return value1 += "", function() {
return function() {
var value0 = this.getAttributeNS(fullname.space, fullname.local);
return value0 === value1 ? null
: value0 === value00 ? interpolate0
Expand All @@ -47,10 +48,9 @@ function attrFunction(name, value) {
value10,
interpolate0;
return function() {
var value0,
value1 = value.apply(this, arguments);
var value0, value1 = value(this);
if (value1 == null) return void this.removeAttribute(name);
value0 = this.getAttribute(name), value1 += "";
value0 = this.getAttribute(name);
return value0 === value1 ? null
: value0 === value00 && value1 === value10 ? interpolate0
: interpolate0 = attrInterpolate(this, name)(value00 = value0, value10 = value1);
Expand All @@ -62,9 +62,9 @@ function attrFunctionNS(fullname, value) {
value10,
interpolate0;
return function() {
var value0, value1 = value.apply(this, arguments);
var value0, value1 = value(this);
if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
value0 = this.getAttributeNS(fullname.space, fullname.local), value1 += "";
value0 = this.getAttributeNS(fullname.space, fullname.local);
return value0 === value1 ? null
: value0 === value00 && value1 === value10 ? interpolate0
: interpolate0 = interpolate(value00 = value0, value10 = value1);
Expand All @@ -73,8 +73,8 @@ function attrFunctionNS(fullname, value) {

export default function(name, value) {
var fullname = namespace(name);
return this.attrTween(name, (value == null
? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
? (fullname.local ? attrFunctionNS : attrFunction)
: (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
return this.attrTween(name, typeof value === "function"
? (fullname.local ? attrFunctionNS : attrFunction)(fullname, tweenValue(this, "attr." + name, value))
: value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname)
: (fullname.local ? attrConstantNS : attrConstant)(fullname, value + ""));
}
12 changes: 6 additions & 6 deletions src/transition/style.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {interpolate} from "d3-interpolate";
import {window} from "d3-selection";
import {tweenValue} from "./tween";

function styleRemove(name) {
var value00,
Expand All @@ -24,7 +25,7 @@ function styleRemoveEnd(name) {
function styleConstant(name, value1) {
var value00,
interpolate0;
return value1 += "", function() {
return function() {
var value0 = window(this).getComputedStyle(this, null).getPropertyValue(name);
return value0 === value1 ? null
: value0 === value00 ? interpolate0
Expand All @@ -39,9 +40,8 @@ function styleFunction(name, value) {
return function() {
var style = window(this).getComputedStyle(this, null),
value0 = style.getPropertyValue(name),
value1 = value.apply(this, arguments);
value1 = value(this);
if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
else value1 += "";
return value0 === value1 ? null
: value0 === value00 && value1 === value10 ? interpolate0
: interpolate0 = interpolate(value00 = value0, value10 = value1);
Expand All @@ -52,7 +52,7 @@ export default function(name, value, priority) {
return value == null ? this
.styleTween(name, styleRemove(name))
.on("end.style." + name, styleRemoveEnd(name))
: this.styleTween(name, (typeof value === "function"
? styleFunction
: styleConstant)(name, value), priority);
: this.styleTween(name, typeof value === "function"
? styleFunction(name, tweenValue(this, "style." + name, value))
: styleConstant(name, value + ""), priority);
}
15 changes: 8 additions & 7 deletions src/transition/text.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import {tweenValue} from "./tween";

function textConstant(value) {
return value = value == null ? "" : value + "", function() {
return function() {
this.textContent = value;
};
}

function textFunction(value) {
return function() {
var v = value.apply(this, arguments);
if (v == null) v = "";
this.textContent = v;
var value1 = value(this);
this.textContent = value1 == null ? "" : value1;
};
}

export default function(value) {
return this.tween("text", (typeof value === "function"
? textFunction
: textConstant)(value));
return this.tween("text", typeof value === "function"
? textFunction(tweenValue(this, "text", value))
: textConstant(value == null ? "" : value + ""));
}
14 changes: 14 additions & 0 deletions src/transition/tween.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,17 @@ export default function(name, value) {
if (typeof value !== "function") throw new Error;
return this.each(tweenFunction(key, id, name, value));
}

export function tweenValue(transition, name, value) {
var key = transition._key,
id = transition._id;

transition.each(function() {
var schedule = set(this, key, id), v = value.apply(this, arguments);
(schedule.values || (schedule.values = {}))[name] = v == null ? null : v + "";
});

return function(node) {
return get(node, key, id).values[name];
};
}

0 comments on commit b2230df

Please sign in to comment.