catmull-rom-2-bezier.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { vec2 } from 'gl-matrix';
  2. function smoothBezier(points, smooth, isLoop, constraint) {
  3. var cps = [];
  4. var hasConstraint = !!constraint;
  5. var prevPoint;
  6. var nextPoint;
  7. var min;
  8. var max;
  9. var nextCp0;
  10. var cp1;
  11. var cp0;
  12. if (hasConstraint) {
  13. min = constraint[0], max = constraint[1];
  14. for (var i = 0, l = points.length; i < l; i += 1) {
  15. var point = points[i];
  16. min = vec2.min([0, 0], min, point);
  17. max = vec2.max([0, 0], max, point);
  18. }
  19. }
  20. for (var i = 0, len = points.length; i < len; i += 1) {
  21. var point = points[i];
  22. if (i === 0 && !isLoop) {
  23. cp0 = point;
  24. }
  25. else if (i === len - 1 && !isLoop) {
  26. cp1 = point;
  27. cps.push(cp0);
  28. cps.push(cp1);
  29. }
  30. else {
  31. var prevIdx = [i ? i - 1 : len - 1, i - 1][isLoop ? 0 : 1];
  32. prevPoint = points[prevIdx];
  33. nextPoint = points[isLoop ? (i + 1) % len : i + 1];
  34. var v = [0, 0];
  35. v = vec2.sub(v, nextPoint, prevPoint);
  36. v = vec2.scale(v, v, smooth);
  37. var d0 = vec2.distance(point, prevPoint);
  38. var d1 = vec2.distance(point, nextPoint);
  39. var sum = d0 + d1;
  40. if (sum !== 0) {
  41. d0 /= sum;
  42. d1 /= sum;
  43. }
  44. var v1 = vec2.scale([0, 0], v, -d0);
  45. var v2 = vec2.scale([0, 0], v, d1);
  46. cp1 = vec2.add([0, 0], point, v1);
  47. nextCp0 = vec2.add([0, 0], point, v2);
  48. // 下一个控制点必须在这个点和下一个点之间
  49. nextCp0 = vec2.min([0, 0], nextCp0, vec2.max([0, 0], nextPoint, point));
  50. nextCp0 = vec2.max([0, 0], nextCp0, vec2.min([0, 0], nextPoint, point));
  51. // 重新计算 cp1 的值
  52. v1 = vec2.sub([0, 0], nextCp0, point);
  53. v1 = vec2.scale([0, 0], v1, -d0 / d1);
  54. cp1 = vec2.add([0, 0], point, v1);
  55. // 上一个控制点必须要在上一个点和这一个点之间
  56. cp1 = vec2.min([0, 0], cp1, vec2.max([0, 0], prevPoint, point));
  57. cp1 = vec2.max([0, 0], cp1, vec2.min([0, 0], prevPoint, point));
  58. // 重新计算 nextCp0 的值
  59. v2 = vec2.sub([0, 0], point, cp1);
  60. v2 = vec2.scale([0, 0], v2, d1 / d0);
  61. nextCp0 = vec2.add([0, 0], point, v2);
  62. if (hasConstraint) {
  63. cp1 = vec2.max([0, 0], cp1, min);
  64. cp1 = vec2.min([0, 0], cp1, max);
  65. nextCp0 = vec2.max([0, 0], nextCp0, min);
  66. nextCp0 = vec2.min([0, 0], nextCp0, max);
  67. }
  68. cps.push(cp0);
  69. cps.push(cp1);
  70. cp0 = nextCp0;
  71. }
  72. }
  73. if (isLoop) {
  74. cps.push(cps.shift());
  75. }
  76. return cps;
  77. }
  78. /**
  79. * create bezier spline from catmull rom spline
  80. * @param {Array} crp Catmull Rom Points
  81. * @param {boolean} z Spline is loop
  82. * @param {Array} constraint Constraint
  83. */
  84. function catmullRom2Bezier(crp, z, constraint) {
  85. if (z === void 0) { z = false; }
  86. if (constraint === void 0) { constraint = [
  87. [0, 0],
  88. [1, 1],
  89. ]; }
  90. var isLoop = !!z;
  91. var pointList = [];
  92. for (var i = 0, l = crp.length; i < l; i += 2) {
  93. pointList.push([crp[i], crp[i + 1]]);
  94. }
  95. var controlPointList = smoothBezier(pointList, 0.4, isLoop, constraint);
  96. var len = pointList.length;
  97. var d1 = [];
  98. var cp1;
  99. var cp2;
  100. var p;
  101. for (var i = 0; i < len - 1; i += 1) {
  102. cp1 = controlPointList[i * 2];
  103. cp2 = controlPointList[i * 2 + 1];
  104. p = pointList[i + 1];
  105. d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]]);
  106. }
  107. if (isLoop) {
  108. cp1 = controlPointList[len];
  109. cp2 = controlPointList[len + 1];
  110. p = pointList[0];
  111. d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]]);
  112. }
  113. return d1;
  114. }
  115. export default catmullRom2Bezier;
  116. //# sourceMappingURL=catmull-rom-2-bezier.js.map