pack.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import { deepMix } from '@antv/util';
  2. import { calcBBox } from '../utils/vector';
  3. function modifier(P, count, layout) {
  4. const pcount = P.length;
  5. if (pcount === 0)
  6. return [];
  7. // col * row >= count
  8. // row is close to col * aspect, so
  9. // col * (col * aspect) >= count
  10. const { innerWidth, innerHeight } = layout;
  11. const aspect = innerHeight / innerWidth;
  12. let col = Math.ceil(Math.sqrt(count / aspect));
  13. // Increase col to avoid total height of packed shape
  14. // being large than height of bbox.
  15. let size = innerWidth / col;
  16. let row = Math.ceil(count / col);
  17. let h0 = row * size;
  18. while (h0 > innerHeight) {
  19. col = col + 1;
  20. size = innerWidth / col;
  21. row = Math.ceil(count / col);
  22. h0 = row * size;
  23. }
  24. // Some offset to increase the space usage.
  25. const space = innerHeight - row * size;
  26. const intervalY = row <= 1 ? 0 : space / (row - 1);
  27. const [offsetX, offsetY] = row <= 1
  28. ? [(innerWidth - pcount * size) / (pcount - 1), (innerHeight - size) / 2]
  29. : [0, 0];
  30. return P.map((points, m) => {
  31. const [x, y, width, height] = calcBBox(points);
  32. const i = m % col;
  33. const j = Math.floor(m / col);
  34. const newX = i * size;
  35. const newY = (row - j - 1) * size + space;
  36. const sx = size / width;
  37. const sy = size / height;
  38. // Translate the shape and mark to make sure the center of
  39. // shape is overlap before and after scale transformation.
  40. const tx = newX - x + offsetX * i;
  41. const ty = newY - y - intervalY * j - offsetY;
  42. return `translate(${tx}, ${ty}) scale(${sx}, ${sy})`;
  43. });
  44. }
  45. /**
  46. * Uniform pack to avid overlap.
  47. * @todo Improve or change algorithm to increase space usage.
  48. * @todo Take some special case into account.
  49. */
  50. export const Pack = () => {
  51. return (I, mark) => {
  52. return [I, deepMix({}, mark, { modifier, axis: false })];
  53. };
  54. };
  55. Pack.props = {};
  56. //# sourceMappingURL=pack.js.map