You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

continuous.js 3.3 KiB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import {bisect} from "d3-array";
  2. import {interpolate as interpolateValue, interpolateRound} from "d3-interpolate";
  3. import {map, slice} from "./array";
  4. import constant from "./constant";
  5. import number from "./number";
  6. var unit = [0, 1];
  7. export function deinterpolateLinear(a, b) {
  8. return (b -= (a = +a))
  9. ? function(x) { return (x - a) / b; }
  10. : constant(b);
  11. }
  12. function deinterpolateClamp(deinterpolate) {
  13. return function(a, b) {
  14. var d = deinterpolate(a = +a, b = +b);
  15. return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
  16. };
  17. }
  18. function reinterpolateClamp(reinterpolate) {
  19. return function(a, b) {
  20. var r = reinterpolate(a = +a, b = +b);
  21. return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
  22. };
  23. }
  24. function bimap(domain, range, deinterpolate, reinterpolate) {
  25. var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1];
  26. if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0);
  27. else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1);
  28. return function(x) { return r0(d0(x)); };
  29. }
  30. function polymap(domain, range, deinterpolate, reinterpolate) {
  31. var j = Math.min(domain.length, range.length) - 1,
  32. d = new Array(j),
  33. r = new Array(j),
  34. i = -1;
  35. // Reverse descending domains.
  36. if (domain[j] < domain[0]) {
  37. domain = domain.slice().reverse();
  38. range = range.slice().reverse();
  39. }
  40. while (++i < j) {
  41. d[i] = deinterpolate(domain[i], domain[i + 1]);
  42. r[i] = reinterpolate(range[i], range[i + 1]);
  43. }
  44. return function(x) {
  45. var i = bisect(domain, x, 1, j) - 1;
  46. return r[i](d[i](x));
  47. };
  48. }
  49. export function copy(source, target) {
  50. return target
  51. .domain(source.domain())
  52. .range(source.range())
  53. .interpolate(source.interpolate())
  54. .clamp(source.clamp());
  55. }
  56. // deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
  57. // reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
  58. export default function continuous(deinterpolate, reinterpolate) {
  59. var domain = unit,
  60. range = unit,
  61. interpolate = interpolateValue,
  62. clamp = false,
  63. piecewise,
  64. output,
  65. input;
  66. function rescale() {
  67. piecewise = Math.min(domain.length, range.length) > 2 ? polymap : bimap;
  68. output = input = null;
  69. return scale;
  70. }
  71. function scale(x) {
  72. return (output || (output = piecewise(domain, range, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate)))(+x);
  73. }
  74. scale.invert = function(y) {
  75. return (input || (input = piecewise(range, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y);
  76. };
  77. scale.domain = function(_) {
  78. return arguments.length ? (domain = map.call(_, number), rescale()) : domain.slice();
  79. };
  80. scale.range = function(_) {
  81. return arguments.length ? (range = slice.call(_), rescale()) : range.slice();
  82. };
  83. scale.rangeRound = function(_) {
  84. return range = slice.call(_), interpolate = interpolateRound, rescale();
  85. };
  86. scale.clamp = function(_) {
  87. return arguments.length ? (clamp = !!_, rescale()) : clamp;
  88. };
  89. scale.interpolate = function(_) {
  90. return arguments.length ? (interpolate = _, rescale()) : interpolate;
  91. };
  92. return rescale();
  93. }