scale.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import { bisectLeft, sort } from 'd3-array';
  2. function constrain(x, lo, hi) {
  3. return Math.min(hi, Math.max(lo, x));
  4. }
  5. export function isOrdinalScale(scale) {
  6. return scale.getBandWidth;
  7. }
  8. export function invert(scale, x, start) {
  9. if (!isOrdinalScale(scale))
  10. return scale.invert(x);
  11. const { adjustedRange } = scale;
  12. const { domain } = scale.getOptions();
  13. const offset = start ? -1 : 0;
  14. const step = scale.getStep();
  15. const range = start ? adjustedRange : adjustedRange.map((d) => d + step);
  16. // R[i0 - 1] < x <= R[i0]
  17. const i0 = bisectLeft(range, x);
  18. const i1 = constrain(i0 + offset, 0, domain.length - 1);
  19. return domain[i1];
  20. }
  21. export function domainOf(scale, values, ratioX) {
  22. if (!values)
  23. return scale.getOptions().domain;
  24. if (!isOrdinalScale(scale)) {
  25. const sortedDomain = sort(values);
  26. if (!ratioX)
  27. return sortedDomain;
  28. const [d] = sortedDomain;
  29. const { range } = scale.getOptions();
  30. const [r0, r1] = range;
  31. const v = r0 > r1 ? -1 : 1;
  32. const d1 = scale.invert(scale.map(d) + v * ratioX);
  33. return [d, d1];
  34. }
  35. const { domain } = scale.getOptions();
  36. const v1 = values[0];
  37. const start = domain.indexOf(v1);
  38. if (ratioX) {
  39. const end = start + Math.round(domain.length * ratioX);
  40. return domain.slice(start, end);
  41. }
  42. const v2 = values[values.length - 1];
  43. const end = domain.indexOf(v2);
  44. return domain.slice(start, end + 1);
  45. }
  46. export function selectionOf(x, y, x1, y1, scale, coordinate) {
  47. const { x: scaleX, y: scaleY } = scale;
  48. const abstractDomain = (point, start) => {
  49. const [x, y] = coordinate.invert(point);
  50. return [invert(scaleX, x, start), invert(scaleY, y, start)];
  51. };
  52. const p0 = abstractDomain([x, y], true);
  53. const p1 = abstractDomain([x1, y1], false);
  54. const domainX = domainOf(scaleX, [p0[0], p1[0]]);
  55. const domainY = domainOf(scaleY, [p0[1], p1[1]]);
  56. return [domainX, domainY];
  57. }
  58. export function abstractOf(domain, scale) {
  59. const [d0, d1] = domain;
  60. const maybeStep = (scale) => (scale.getStep ? scale.getStep() : 0);
  61. return [scale.map(d0), scale.map(d1) + maybeStep(scale)];
  62. }
  63. export function pixelsOf(selection, scale, coordinate) {
  64. const { x: scaleX, y: scaleY } = scale;
  65. const [X, Y] = selection;
  66. const AX = abstractOf(X, scaleX);
  67. const AY = abstractOf(Y, scaleY);
  68. const p0 = [AX[0], AY[0]];
  69. const p1 = [AX[1], AY[1]];
  70. const [x, y] = coordinate.map(p0);
  71. const [x1, y1] = coordinate.map(p1);
  72. return [x, y, x1, y1];
  73. }
  74. //# sourceMappingURL=scale.js.map