smooth.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /**
  2. * @fileOverview convert the line to curve
  3. * @author dxq613@gmail.com
  4. */
  5. import Vector2 from './vector2';
  6. function getPoint(v) {
  7. return [v.x, v.y];
  8. }
  9. function smoothBezier(points, smooth, isLoop, constraint) {
  10. var cps = [];
  11. var prevPoint;
  12. var nextPoint;
  13. var hasConstraint = !!constraint;
  14. var min;
  15. var max;
  16. var point;
  17. var len;
  18. var l;
  19. var i;
  20. if (hasConstraint) {
  21. min = [Infinity, Infinity];
  22. max = [-Infinity, -Infinity];
  23. for (i = 0, l = points.length; i < l; i++) {
  24. point = getPoint(points[i]);
  25. Vector2.min(min, min, point);
  26. Vector2.max(max, max, point);
  27. }
  28. Vector2.min(min, min, constraint[0]);
  29. Vector2.max(max, max, constraint[1]);
  30. }
  31. for (i = 0, len = points.length; i < len; i++) {
  32. point = getPoint(points[i]);
  33. if (isLoop) {
  34. prevPoint = getPoint(points[i ? i - 1 : len - 1]);
  35. nextPoint = getPoint(points[(i + 1) % len]);
  36. } else {
  37. if (i === 0 || i === len - 1) {
  38. cps.push([point[0], point[1]]);
  39. continue;
  40. } else {
  41. prevPoint = getPoint(points[i - 1]);
  42. nextPoint = getPoint(points[i + 1]);
  43. }
  44. }
  45. var v = Vector2.sub([], nextPoint, prevPoint);
  46. Vector2.scale(v, v, smooth);
  47. var d0 = Vector2.distance(point, prevPoint);
  48. var d1 = Vector2.distance(point, nextPoint);
  49. var sum = d0 + d1;
  50. if (sum !== 0) {
  51. d0 /= sum;
  52. d1 /= sum;
  53. }
  54. var v1 = Vector2.scale([], v, -d0);
  55. var v2 = Vector2.scale([], v, d1);
  56. var cp0 = Vector2.add([], point, v1);
  57. var cp1 = Vector2.add([], point, v2);
  58. if (hasConstraint) {
  59. Vector2.max(cp0, cp0, min);
  60. Vector2.min(cp0, cp0, max);
  61. Vector2.max(cp1, cp1, min);
  62. Vector2.min(cp1, cp1, max);
  63. }
  64. cps.push([cp0[0], cp0[1]]);
  65. cps.push([cp1[0], cp1[1]]);
  66. }
  67. if (isLoop) {
  68. cps.push(cps.shift());
  69. }
  70. return cps;
  71. }
  72. function catmullRom2bezier(pointList, z, constraint) {
  73. var isLoop = !!z;
  74. var controlPointList = smoothBezier(pointList, 0.4, isLoop, constraint);
  75. var len = pointList.length;
  76. var d1 = [];
  77. var cp1;
  78. var cp2;
  79. var p;
  80. for (var i = 0; i < len - 1; i++) {
  81. cp1 = controlPointList[i * 2];
  82. cp2 = controlPointList[i * 2 + 1];
  83. p = pointList[i + 1];
  84. d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p.x, p.y]);
  85. }
  86. if (isLoop) {
  87. cp1 = controlPointList[len];
  88. cp2 = controlPointList[len + 1];
  89. p = pointList[0];
  90. d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p.x, p.y]);
  91. }
  92. return d1;
  93. }
  94. export { catmullRom2bezier as smooth };