smooth.js 2.5 KB

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