parse-transform.mjs 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. const radToDeg = (rad) => (rad * 180) / Math.PI;
  2. const rotate = (v) => {
  3. const angle = radToDeg(Math.atan2(v[1], v[0]));
  4. return rebaseAngle(angle);
  5. };
  6. const matrix2dParsers = {
  7. x: 4,
  8. y: 5,
  9. translateX: 4,
  10. translateY: 5,
  11. scaleX: 0,
  12. scaleY: 3,
  13. scale: (v) => (Math.abs(v[0]) + Math.abs(v[3])) / 2,
  14. rotate,
  15. rotateZ: rotate,
  16. skewX: (v) => radToDeg(Math.atan(v[1])),
  17. skewY: (v) => radToDeg(Math.atan(v[2])),
  18. skew: (v) => (Math.abs(v[1]) + Math.abs(v[2])) / 2,
  19. };
  20. const rebaseAngle = (angle) => {
  21. angle = angle % 360;
  22. if (angle < 0)
  23. angle += 360;
  24. return angle;
  25. };
  26. const rotateZ = rotate;
  27. const scaleX = (v) => Math.sqrt(v[0] * v[0] + v[1] * v[1]);
  28. const scaleY = (v) => Math.sqrt(v[4] * v[4] + v[5] * v[5]);
  29. const matrix3dParsers = {
  30. x: 12,
  31. y: 13,
  32. z: 14,
  33. translateX: 12,
  34. translateY: 13,
  35. translateZ: 14,
  36. scaleX,
  37. scaleY,
  38. scale: (v) => (scaleX(v) + scaleY(v)) / 2,
  39. rotateX: (v) => rebaseAngle(radToDeg(Math.atan2(v[6], v[5]))),
  40. rotateY: (v) => rebaseAngle(radToDeg(Math.atan2(-v[2], v[0]))),
  41. rotateZ,
  42. rotate: rotateZ,
  43. skewX: (v) => radToDeg(Math.atan(v[4])),
  44. skewY: (v) => radToDeg(Math.atan(v[1])),
  45. skew: (v) => (Math.abs(v[1]) + Math.abs(v[4])) / 2,
  46. };
  47. function defaultTransformValue(name) {
  48. return name.includes("scale") ? 1 : 0;
  49. }
  50. function parseValueFromTransform(transform, name) {
  51. if (!transform || transform === "none") {
  52. return defaultTransformValue(name);
  53. }
  54. const matrix3dMatch = transform.match(/^matrix3d\(([-\d.e\s,]+)\)$/u);
  55. let parsers;
  56. let match;
  57. if (matrix3dMatch) {
  58. parsers = matrix3dParsers;
  59. match = matrix3dMatch;
  60. }
  61. else {
  62. const matrix2dMatch = transform.match(/^matrix\(([-\d.e\s,]+)\)$/u);
  63. parsers = matrix2dParsers;
  64. match = matrix2dMatch;
  65. }
  66. if (!match) {
  67. return defaultTransformValue(name);
  68. }
  69. const valueParser = parsers[name];
  70. const values = match[1].split(",").map(convertTransformToNumber);
  71. return typeof valueParser === "function"
  72. ? valueParser(values)
  73. : values[valueParser];
  74. }
  75. const readTransformValue = (instance, name) => {
  76. const { transform = "none" } = getComputedStyle(instance);
  77. return parseValueFromTransform(transform, name);
  78. };
  79. function convertTransformToNumber(value) {
  80. return parseFloat(value.trim());
  81. }
  82. export { parseValueFromTransform, readTransformValue };