Coder Social home page Coder Social logo

d3-interpolate's Introduction

d3-interpolate

This module provides a variety of interpolation methods for blending between two values. Values may be numbers, colors, strings, arrays, or even deeply-nested objects.

Resources

d3-interpolate's People

Contributors

dependabot[bot] avatar devgru avatar fil avatar gerardofurtado avatar jetzhliu avatar joallard avatar krukon avatar mbostock avatar stefanullinger avatar stof avatar waldyrious avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

d3-interpolate's Issues

support for Vec3

THREE.js and AFrame interchange between strings and Vec3 objects e.g
3 3 3 and {x:3, y:3, z:3}

I've been handling this using my own home-rolled interpolator functions with attrTween, but this seems like a straighforward feature to consider adding to stock d3.

Performance issue: parseCss

The parseCss method transforms a statement like translate(23px, 24px) into a transformation matrix. It constantly modifies the DOM. This is a huge performance issue, when an animation is initiated.

https://github.com/d3/d3-interpolate/blob/master/src/transform/parse.js

What do you think about parsing this with regex instead and mathematically generating the transformation matrices? Should be significantly faster. We can look for inspiration in places like https://github.com/jlmakes/rematrix for matrix generation. An simple example where performance is already a huge drain:

<html>
<head>
    <title>Learn D3 in 5 minutes</title>
</head>
<body>


<svg id="canvas"></svg>
<script src="https://d3js.org/d3.v5.js"></script>
<script>
    const circles = d3.select('svg')
        .selectAll('path')
        .data(Array(2).fill())
        .enter()
        .append('circle')
        .attr('r', 20)
    
    let xOffset = 0;
    const animate = () => {
        xOffset+=0.1
        circles.transition()
        .duration(100)
        .style('transform', (_, index) => `translate(${(index + xOffset) * 30}px, 30px)`)
        .on('end', animate);
    }
    animate();
</script>
</body>
</html>

On my brand new Macbook Pro I can see the framedrops easily with my eyes. As seen in Chrome, this triggers forced reflows. For a lot of simultaneous transitions starting at the same time, the problem is, of course, even bigger.

pastedgraphic-3

Is this a known issue? I would be interested in helping out with a pull request

Exclude keys from interpolation?

In some situations interpolateObject does more work than is desired. For instance, if I have an object like {x: 1, y: 2, label: 'red'} that interpolates to {x: 3, y: 4, label: 'red'}. I want it to come out of interpolate as exactly {x: 3, y: 4, label: 'red'}, however, because interpolateObject tries to interpolate all of the values in the object the output of this interpolation tends to be {x: 3, y: 4, label: 'rgb(255, 0, 0)'}.

Is there a way to exclude specific keys from the interpolation? Or do I need to do some sort of recombination after the interpolation? Given the design goal of this function to be the fast inner part of a loop for animation, needing to modify the data after interpolation is less than ideal.

Images in readme not loading?

Might be a temporary github issue, but I'm not seeing any of the images here. Dev console shows something like this over and over:

Refused to load the image 'https://raw.githubusercontent.com/d3/d3-interpolate/master/img/hsl.png' because it violates the following Content Security Policy directive: "img-src 'self' data: assets-cdn.github.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com collector.githubapp.com avatars0.githubusercontent.com avatars1.githubusercontent.com avatars2.githubusercontent.com avatars3.githubusercontent.com github-cloud.s3.amazonaws.com".

d3.interpolateFunction?

I have a need to linearly deform one (unary, real domain) function onto another.

As a new d3 user I'm still learning what's in the kitchen, so to speak. Before discovering d3-interpolate I was cobbling this feature together with d3.scaleLinear. However this was falling down due to needing to construct such a scale on each interpolator call.

Doing the interpolation explicitly fixed the issue and is easy enough, but it felt a little counter to the intended style. After noticing d3-interpolate I hoped I would find such a function interpolator (homotopy) constructor, but no dice.

Could it be added?

Recommended way to use D3+plugins with ES6-style imports?

I have a specific case in mind I'm wondering about, related to this plugin, but I'm also wondering how this should be done in general.

It seems like most plugins attach functions to the d3 object itself, so for this plugin my first approach was something like this:

import * as d3 from 'd3';
import 'd3-interpolate';
window.d3 = d3;

The specific issue I'm running into here is that later I have code like

const someFunction = (arr, numSamples) => {
        const interpolator = d3.interpolateRgb(arr[0], arr[1]);
        return d3.quantize(interpolator, numSamples);
    };

which throws the error "d3.quantize is not a function". Placing a debugger to examine the d3 object, it looks like d3.interpolateRgb exists, along with many of the other d3.interpolate functions, but d3.quantize doesn't.

One quick fix was to do something like

import * as interpolate from 'd3-interpolate';
d3.quantize = interpolate.quantize

but I'm just wondering what the proper approach might be for importing/attaching plugin functions (or if this is just an isolated instance!)

d3.piecewise?

A very lightweight piecewise linear scale. Implementation:

d3.piecewise = function(interpolate, values) {
  var n = values.length - 1, I = d3.pairs(values, interpolate);
  return function(t) {
    var i = Math.max(0, Math.min(n - 1, Math.floor(t *= n)));
    return I[i](t - i);
  };
};

Example usage:

d3.piecewise(d3.interpolateRgb, ["red", "green", "blue"])

Update readme for interpolateTransformSvg

In d3 version 3.5.17 there is no interpolateTransformSvg but there is interpolateTransform. The readme for this repository has it as interpolateTransformSvg. It might be the up and coming api, so it might not really be an issue, but thought that I would let you know anyway.

Thank you for such an awesome library!

Gamma correct RGB interpolation

Are you considering adding it in the future?

Interpolating RGB values without gamma correct produces darker "dirtier" colors than they should be.

screen shot 2016-01-07 at 11 14 52

The solution would be to move values to linear space, interpolate and bring it back to gamma space.

//pseudocode for R channel
var color_hex = '#FF0000';
var color = hex2bytes(color_hex);
var byte_r = color[0];
var float_r = byte_r/255;
var linear_r = Math.pow(float_r, 2.2);
var inter_r = interpolate(linear_r, linear_r_2, t);
var gamma_r = Math.pow(inter_r, 1/2.2);
var out_r = Math.floor(gamma_r * 255);

Add option to modify ρ value in d3.interpolateZoom

It would be great if the ρ value responsible for the curvature of the 'flight' path in d3.interpolateZoom function could be modified by users, e.g.:

interpolate.rho(ρ)

var i=d3.interpolateZoom.rho(.25)([ux0, uy0, w0],[ux1, uy1, w1]);

I would imagine the default ρ value would be the current √2.

It would also be good to have a value that produces linear path (e.g. ρ=0), making it a standard non-zoom interpolator.

What I'm not sure about is if the value should only be a constant or also a function, if there should be allowed min & max values, could it accept negative values and if it should be a set function or a get too?

Why b-splines t value need ((t - i / n) * n?

export function basis(t1, v0, v1, v2, v3) {
  var t2 = t1 * t1, t3 = t2 * t1;
  return ((1 - 3 * t1 + 3 * t2 - t3) * v0
      + (4 - 6 * t2 + 3 * t3) * v1
      + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
      + t3 * v3) / 6; 
}

export default function(values) {
  var n = values.length - 1;
  return function(t) {
    var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),
        v1 = values[i],
        v2 = values[i + 1],
        v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,
        v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
    return basis((t - i / n) * n, v0, v1, v2, v3);// Why multipy n ???
    // how about use the next line ?
    return basis(t , v0, v1, v2, v3);
  };
}

Feature request: changing the default color interpolation method

Scenario: I want to create an interpolator between two objects a = {color: "red"} and b = {color:"lightblue"}.

d3.interpolate(a,b) sees that these properties are colors, and defaults to the hard-coded rgb (https://github.com/d3/d3-interpolate/blob/master/src/value.js#L15) method. Is there a way to override that default and use a gamma-corrected interpolateRgb (#14) or interpolateLab instead of rgb?

Unless I'm missing something, I don't see how to override this. (It doesn't even look possible to monkey-patch with d3.interpolateRgb = d3.interpolateLab, which I would not recommend anyway :))

A possible syntax might be d3.interpolate.color(d3.interpolateLab)(…), or maybe more generically d3.interpolate.delegate("color", d3.interpolateLab)(…), which could also work for numbers, strings, whatever…

https://observablehq.com/d/7f6b33e509e0e698

Should functions have the prefix “interpolate”?

In d3-shape, I felt it was too verbose to use the prefixes “curve” for curves and “symbol” for symbol types: d3.shape.cardinal and d3.shape.circle seem sufficiently specific. If the functions in this repository are similarly scoped by the module name, then isn’t d3.interpolate.rgb sufficiently specific, too? Saying d3.interpolate.interpolateRgb seems redundant.

Of course, this assumes that the symbols aren’t flattened on to the d3 namespace, as in d3.interpolateRgb as they were in 3.x, but I think it will be nice to scope each module’s symbols so that the way we refer to them is the same whether you are using Rollup for a custom bundles or simply concatenating the pre-built bundles.

The probably means d3.interpolate would need to be renamed d3.interpolate.auto, unless we decide to have that function be the default export of the module… which I think probably wouldn’t work well? Which then raises a related issue of what to name d3.ease in d3/d3-ease#8.

d3.interpolateTransformSvg returning an empty string

Context: I'm using a transition for changing the "translate" transform function of some elements. Sometimes the position doesn't change, so the transition goes from foo to the same foo.

However, I've notice that when transitioning from "translate(0,0)" to "translate(0,0)" the interpolator returns an empty string. The interpolator in question is d3.interpolateTransformSvg.

For instance:

d3.interpolateTransformSvg("translate(1,1)","translate(0,0)")(1);
//returns "translate(0,0)", as expected

But:

d3.interpolateTransformSvg("translate(0,0)","translate(0,0)")(1);
//returns an empty string ""

Here is a basic demo: https://jsfiddle.net/bvudenyq/

I'm not sure if the issue is in d3.interpolateTransformSvg itself or in the parse.js file. The solution is quite simple, in my case I'm just using attrTween with d3.interpolateString as the interpolator, ditching d3.interpolateTransformSvg, but I thought I should mention this bug.

Thanks,

Interpolation of objects without prototype results in error

Calling interpolate with objects without prototype:

var a = Object.create(null);
a.value = 0;
var b = Object.create(null);
b.value = 10;
var interpolator = interpolate(a, b)

results in error:

TypeError: Cannot convert object to primitive value
    at isNaN (native)

I've created pull request to fix this: #34

d3.interpolate should special-case number-like objects?

Related d3/d3#2878. The old behavior of d3.interpolate was:

  1. If b is a color, interpolateRgb is used.
  2. If b is a string, interpolateString is used.
  3. If b is an array, interpolateArray is used.
  4. If b is an object and not coercible to a number, interpolateObject is used.
  5. Otherwise, interpolateNumber is used.

Note the “and not coercible to a number” rule in step 4. The new algorithm does not treat objects that are coercible to numbers specially:

  1. If b is null, undefined or a boolean, use the constant b.
  2. If b is a number, use interpolateNumber.
  3. If b is a color or a string coercible to a color, use interpolateRgb.
  4. If b is a string, use interpolateString.
  5. If b is an array, use interpolateArray.
  6. Use interpolateObject.

A ramification of this is that d3.interpolate no longer supports interpolating dates: dates are treated as generic objects, and since they do not have any enumerable properties, the resulting interpolator returns the empty object.

I see two non-exclusive options:

  1. After step 5, check if b is a date using instanceof Date, and if so, use a new d3.interpolateDate instead of d3.interpolateObject.
  2. After step 5, check if b is coercible to a number using !isNaN(b), and if so, use d3.interpolateNumber instead of d3.interpolateObject.

Note that if we only do the second option, then the resulting interpolator will return numbers rather than Date instances. In practice, this is typically fine because all methods in D3 that accept dates should create a Date instance from a number if they are given a number. However, it might be cleaner to handle dates specially, since the Date is a first-class type in JavaScript.

Interpolating arcs can lead to error messages

A path element's "d" attribute for an arc (such as those created with d3.arc) contain "A" commands ("elliptical arc curve commands"). They have five parameters, two of which are flags which can only be 0 or 1.

Unfortunately, some transitions can lead to these flags being linearly interpolated, leading to values such as 0.12345. At least in Chrome, this causes error messages. Here is an example:

http://codepen.io/anon/pen/qRrgLe
(You will need to open the console to see the error messages.)

Is there a chance to have these flags only assume the values 0 or 1 during a transition?

array(undefined, [42]) throws TypeError

As with #10, the starting value should be treated as an empty array if it’s not an array, rather than potentially throwing an error:

> d3_interpolate.value(undefined, [42])(0.5)
TypeError: Cannot read property 'length' of undefined

Circular dependencies between array.js <-> value.js and object.js <-> value.js

Detected this circular dependency issue in my team's CI, we use rc-slider which has d3-interpolate as dependency.

The circular dependency was reported by CI as follows:

Circular dependency: node_modules/d3-interpolate/src/value.js -> node_modules/d3-interpolate/src/array.js -> node_modules/d3-interpolate/src/value.js
Circular dependency: node_modules/d3-interpolate/src/value.js -> node_modules/d3-interpolate/src/object.js -> node_modules/d3-interpolate/src/value.js

interpolateHcl and achromatic colors

Interpolating red and white in Lab and HCL:

screen shot 2018-04-04 at 15 29 10

Due to the particular HCL hue of achromatic colors (~ 158.2° in the current implementation of d3-color), when interpolating a chromatic and achromatic color, the non-zero Chroma of the interpolated color will pick up various hues.

In comparison, chroma.js will not interpolate the hue in this case, with a more predictable (and analogous to Lab) outcome:

screen shot 2018-04-04 at 15 35 12

Should interpolateHcl behave the same?

interpolateRgb("invalid", "red")(1) returns black

When interpolating from an invalid RGB color, we should assume the (potentially) valid channel values from the target color, rather than always returning black. This should apply to other color spaces, too.

  • rgb.r
  • rgb.g
  • rgb.b
  • hsl.h
  • hsl.s
  • hsl.l
  • hcl.h
  • hcl.c
  • hcl.l
  • lab.l
  • lab.a
  • lab.b
  • cubehelix.h
  • cubehelix.c
  • cubehelix.l

Interpolation questions

Are all the interpolations linear?
Is it possible to do easing or even physics-based (e.g. spring based using stiffness and damping)?

interpolateNumberArrayRound ?

I just realized that in #77, for integer arrays, the implicit rounding is floor when we would want round, for symmetry.
I'm not sure where to put that change: in array type detection, and/or in an explicit interpolateNumberArrayRound function.

(Sorry for l'esprit d'escalier)

Interpolating opacity.

Now that it’s supported by d3-color, it would be nice to do here.

One tricky thing: CSS says that transparent is rgba(0, 0, 0, 0). A more natural representation in d3-color is rgba(NaN, NaN, NaN, 0), so the RGB channels can be inherited. Probably we should fix d3-color to set these channels to NaN if the opacity is zero, so that the existing interpolators will just work automatically.

Remove d3.interpolators.

Seems insufficiently useful. Just make the behavior of d3.interpolator fixed. People can create custom interpolators easily enough.

d3.interpolateTransform that takes a matrix.

I’d like a version of d3.interpolateTransform that, instead of taking a transform string as d3.interpolateTransformCss and d3.interpolateTransformSvg do, takes an array of six numbers [a, b, c, d, tx, ty] in the same manner as the matrix transform function.

This would potentially eliminate the need for separate CSS- and SVG-specific transform methods, in conjunction with changing how the transform style and attribute is handling in d3-transition (d3/d3-transition#72).

parseSvg function crashes in IE

I've been noticing this error in Internet Explorer with an application that depends on d3;
Unable to get property 'matrix' of undefined or null reference

I tracked it down to this line. It seems like the problem is almost identical to d3/d3#376. I'm not completely sure what the conditions are that cause consolidate() to return null in my case. My understanding of the internals of d3 and the SVG API are too limited, and my toolset for debugging issues in IE is too cumbersome for me to quickly find out. However, it seems like the solution is the same as the previous d3 issue. Changing line 21 to the following seems to fix the issue for me;
var m = svgNode.transform.baseVal.consolidate() ? svgNode.transform.baseVal.consolidate().matrix : {a: 1, b: 0, c: 0, d: 1, e: 0, f: 0};

I'm not sure if that's the right fix, but I'll open a PR with that fix for now and await feedback.

Expose `/transform` helpers/methods

Can you extract out or expose the transformation decomposition, manipulation, and recompose logic?

Specifically, parseSvg has been very useful to build the object from the attribute, and it'd be nice if the "build the CSS string from the transform JSON" logic was also exposed (instead of closed over in the interpolation logic).

https://github.com/d3/d3-interpolate/tree/master/src/transform

https://github.com/d3/d3-interpolate/blob/master/src/transform/index.js

Is there a good reason to not make this functionality a dedicated micro library?

d3-transform-matrix? d3-css-transform?

In charge of:

  • Parse the style string into a JSON representation
  • Write a style string from JSON
  • Apply multiple JSON transformations down into 1 representation

Support BigInt?

  • d3.interpolate(BigInt(5), BigInt(15))(0.5) throws a TypeError: Cannot convert a BigInt value to a number

  • BigInt64Array and BigUint64Array (typed arrays) could be supported too (see #74 (comment)).

object(NaN, {foo: 42})(0.5) throws TypeError

The starting value should be treated as an empty object if it is not an object. So, instead of:

> d3_interpolate.value(NaN, {foo: 42})(0.5)
TypeError: Cannot use 'in' operator to search for 'foo' in NaN
    at object (/Users/mbostock/Development/d3-interpolate/build/d3-interpolate.js:44:18)

The input NaN should be treated as {}:

> d3_interpolate.value({}, {foo: 42})(0.5)
{foo: 42}

Related d3/d3#2688.

Interpolate typed arrays?

It’d be nice if there were an interpolator for typed arrays, like Float32Array. The existing d3.interpolateArray is almost what we want—the only change you’d need to make is to say c = new b.constructor(nb) rather than c = new Array(nb).

However, there are two considerations with this approach:

  • Should d3.interpolate delegate to d3.interpolateArray if b is a typed array? If so, we will need to use a different test than Array.isArray that also returns true for typed arrays.

  • How should d3.interpolateArray behave if b is not an array and not a typed array? The current implementation is guaranteed to return an Array even if b is not an array (but may be an array-like). If c is constructed using b.constructor, the change to d3.interpolateArray might be considered backwards-incompatible.

It might make more sense to introduce a new d3.interpolateTypedArray, and keep the current behavior of d3.interpolateArray. And we could optionally extend d3.interpolate to delegate to d3.interpolateTypedArray for typed array input. Seems like the following test would work:

function isTypedArray(x) {
  return ArrayBuffer.isView(x) && !(x instanceof DataView);
}

interpolateMonotone

I've experimented with monotone cubic interpolation (as per the Steffen method you reference in d3-shape) and with the array values being evenly spaced, the formula is quite simplified, as long as I read the paper correctly:

const monotone = (t1, h, v0, v1, v2, v3) => {

	let h2 = h * h;
	let t2 = t1 * t1;
	let t3 = t2 * t1;

	let s20 = (v2 - v0) / (2 * h);
	let s31 = (v3 - v1) / (2 * h);
	let s21 = (v2 - v1) / h;

	return (
		(s20 + s31 - 2 * s21) / h2 * t3 +
		(3 * s21 - 2 * s20 - s31) / h * t2 + 
		s20 * t +
		v1
	);
}

where h = 1 / n, t1 = t - i / n and i, n, and v0...v3 being computed the same as with the basis spline.

I tried it for the purpose of color interpolation, although it turned out to be of questionable usefulness, at least in RGB:

screen shot 2018-04-10 at 13 11 08

Nevertheless, if you think it would be a good addition to d3-interpolate, I'm happy to make a PR. (Could be useful for animations, since it smoothly interpolates the data points?)

Circular dependencies when bundling D3 interpolate 1.3.2:

Using [email protected] when bundling with rollup:

(!) Circular dependency: node_modules\d3-interpolate\src\value.js -> node_modules\d3-interpolate\src\array.js -> node_modules\d3-interpolate\src\value.js
(!) Circular dependency: node_modules\d3-interpolate\src\value.js -> node_modules\d3-interpolate\src\object.js -> node_modules\d3-interpolate\src\value.js

Cubic spline

I dislike asking this question without having the proper vocabulary for it, but I was experimenting with reproducing Photoshop's Curves interface using D3 modules.

After reading up on some of the math, experimenting with polynomial interpolation (and experiencing Runge's phenomenon with it), I came back to a cubic spline interpolation — using a package that implements this algorithm — that gave me the correct result.

Pictured below, in combination with a clamped linear scale, and in comparison with some curves available in d3-shape:

screen shot 2018-03-03 at 19 31 09

  • Would such a spline interpolator be a good addition to d3-interpolate?
  • Is it called something specific? (I'm a bit lost among the various types of splines...)

Also, reading through the original implementation of this spline, it also mentions it being a natural spline, and I have found that in some situations, D3's curveNatural matches this implementation, but in others they diverge, further clouding my understanding of terms :D

cubehelixDefault and rainbow?

Perhaps these could be simple interpolators (taking an argument t in [0,1]) that returns the corresponding color, as is currently implemented in d3-scale.

Add each interpolate as their own file in build

I think it would be great to not have to get all the interpolation methods when we just want one (it's linked to d3/d3-color#15)
Lodash does it very well:

// load the modern build
var _ = require('lodash');
// or a method category
var array = require('lodash/array');
// or a method (great for smaller builds with browserify/webpack)
var chunk = require('lodash/array/chunk');

So it would mean that instead of:

var interpolateRound = require('d3-interpolate').interpolateRound

We could do:

var interpolateRound = require('d3-interpolate/interpolateRound')

Which, in this case, is 630 less loc to add to the final build.
I think it might be a problem with all the new d3 repos, I'm happy to add PRs this week if you're keen with the change.

Why is skewY missing?

I was wondering if I can learn something from your interpolation methods and I found skewY to be missing. I ask because I want to sharpen my scripting; I want to develop a unified methods to do HTML & SVG animation (if SVG do the transform attribute with the below codes, else do the HTML).

You know regular HTML elements do use skewY and I don't understand why you decided not to use it for D3 functions as well. D3 is above and beyond me and any other scripting there is for SVG, so I'm here to learn, I hope I can find some help here or in SO website.

As of now, we have in the decompose.js:

if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;

As for skewX we have

skewX: Math.atan(skewX) * degrees,

similar for skewY

skewY: Math.tan(a) * degrees, // is this correct? it could according to https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewY

In the index.js we have skewX

function skewX(a, b, s, q) {
  if (a !== b) {
    q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number(a, b)});
  } else if (b) {
    s.push(pop(s) + "skewX(" + b + degParen);
  }
}

Could this mean that skewY would look like this?

function skewY(a, b, s, q) {
  if (a !== b) {
    q.push({i: s.push(pop(s) + "skewY(", null, degParen) - 2, x: number(a, b)});
  } else if (b) {
    s.push(pop(s) + "skewY(" + b + degParen);
  }
}

Please, are the decomposition and interpolation functions correct for 'skewY' in the above?

Interpolate transform function lists, not just matrices.

Consider this animation which interpolates using interpolateTransformSvg:

var p1 = d3.select('svg')
  .append('polygon')
  .attr('points', '100 90 100 110 10 100')
  .attr('transform', 'rotate(20, 100, 100)');

p1.transition()
  .duration(2000)
  .attr('transform', 'rotate(160, 100, 100)')
  .on('start end', function () {
    console.log(p1.node().transform.baseVal.consolidate().matrix);
  });

Codepen

It should rotate the polygon about a constant center. Instead, the rotation center moves during the transition. If you look at the logged consolidated transform matrices, this is not that suprising:

{ a: 0.9396926164627075, b: 0.3420201539993286, c: -0.3420201539993286, d: 0.9396926164627075, e: 40.23275375366211, f: -28.171276092529297 }
{ a: -0.9396926164627075, b: 0.3420201539993286, c: -0.3420201539993286, d: -0.9396926164627075, e: 228.17127990722656, f: 159.76724243164062 }

The method of blindly taking the matrix supplied by SVGTransformList.consolidate() as a basis for interpolation is clearly not appropriate in this case.

Rotating without supplying a rotation center works is as expected.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.