demo.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. var paper;
  2. var rawLines = [];
  3. var rawLinesData = [];
  4. var fittedCurves = [];
  5. var fittedCurvesData = [];
  6. var error = 50;
  7. var showBezierDots = false;
  8. var showBezierControlPoints = false;
  9. var bezierDots = [];
  10. var bezierControlPoints = [];
  11. var bezierControlPointLines = [];
  12. window.onload = function () {
  13. paper = Raphael('container', 800, 400);
  14. function lineDataToPathString(lineData) {
  15. var str = "";
  16. lineData.map(function (xy, i) {
  17. if (i == 0) {
  18. str += "M ";
  19. } else {
  20. str += "L ";
  21. }
  22. str += xy[0] + " " + xy[1] + " ";
  23. });
  24. return str;
  25. }
  26. function fittedCurveDataToPathString(fittedLineData) {
  27. var str = "";
  28. fittedLineData.map(function (bezier, i) {
  29. if (i == 0) {
  30. str += "M " + bezier[0][0] + " " + bezier[0][1];
  31. }
  32. str += "C " + bezier[1][0] + " " + bezier[1][1] + ", " +
  33. bezier[2][0] + " " + bezier[2][1] + ", " +
  34. bezier[3][0] + " " + bezier[3][1] + " ";
  35. });
  36. return str;
  37. }
  38. function cleanBezierHelpGraphics(){
  39. bezierDots
  40. .concat(bezierControlPoints)
  41. .concat(bezierControlPointLines)
  42. .forEach(function(el){
  43. el.remove();
  44. });
  45. bezierDots = [];
  46. bezierControlPoints = [];
  47. bezierControlPointLines = [];
  48. }
  49. function updateLines(updateAllCurves) {
  50. rawLinesData.forEach(function (lineData, i) {
  51. if (rawLines.length <= i) {
  52. var path = paper.path('');
  53. path.attr({
  54. stroke: 'lightgray'
  55. });
  56. rawLines.push(path);
  57. }
  58. rawLines[i].attr("path", lineDataToPathString(lineData));
  59. var isLastItem = i === rawLinesData.length - 1;
  60. if (updateAllCurves || isLastItem) {
  61. if (fittedCurves.length <= i) {
  62. path = paper.path('');
  63. path.attr({
  64. stroke: 'red'
  65. });
  66. fittedCurves.push(path);
  67. }
  68. if (lineData.length > 1) {
  69. fittedCurvesData[i] = fitCurve(lineData, error);
  70. //console.log(lineData.length, lineData.map(function(arr){return "["+arr.join(",")+"]";}).join(","));
  71. fittedCurves[i].attr("path", fittedCurveDataToPathString(fittedCurvesData[i]));
  72. }
  73. }
  74. });
  75. cleanBezierHelpGraphics();
  76. fittedCurvesData.forEach(function (beziers) {
  77. beziers.forEach(function (bezier, i) {
  78. var p1 = bezier[0];
  79. var cp1 = bezier[1];
  80. var cp2 = bezier[2];
  81. var p2 = bezier[3];
  82. var getDotCircle = function (p) {
  83. var circle = paper.circle(p[0], p[1], 5);
  84. circle.attr({
  85. fill: 'rgb(200, 50, 0)',
  86. 'fill-opacity': 0.5,
  87. stroke: null
  88. });
  89. return circle;
  90. };
  91. var getControlPoint = function (p) {
  92. var circle = paper.circle(p[0], p[1], 2);
  93. circle.attr({
  94. fill: 'rgb(100, 200, 0)',
  95. 'fill-opacity': 0.5,
  96. stroke: null
  97. });
  98. return circle;
  99. };
  100. var getControlLine = function (p1, p2) {
  101. var pathString = "M " + p1[0] + " " + p1[1] + " ";
  102. pathString += "L " + p2[0] + " " + p2[1];
  103. var line = paper.path(pathString);
  104. line.attr({
  105. stroke: 'rgb(100, 200, 0)',
  106. 'stroke-opacity': 0.5
  107. });
  108. return line;
  109. };
  110. if (showBezierDots) {
  111. if (i == 0) {
  112. bezierDots.push(getDotCircle(p1));
  113. }
  114. bezierDots.push(getDotCircle(p2));
  115. }
  116. if (showBezierControlPoints) {
  117. bezierControlPointLines.push(getControlLine(p1, cp1));
  118. bezierControlPointLines.push(getControlLine(cp2, p2));
  119. bezierControlPoints.push(getControlPoint(cp1));
  120. bezierControlPoints.push(getControlPoint(cp2));
  121. }
  122. });
  123. });
  124. }
  125. var container = document.getElementsByTagName('svg').item(0);
  126. var clearButton = document.getElementById('clear-button');
  127. var errorInput = document.getElementById('errorInput');
  128. var errorValue = document.getElementById('errorValue');
  129. var showBezierDotsCheckbox = document.getElementById('showBezierDotsCheckbox');
  130. var showBezierControlPointsCheckbox = document.getElementById('showBezierControlPointsCheckbox');
  131. error = parseInt(errorInput.value);
  132. var isMouseDown = false;
  133. container.addEventListener('mousedown', function () {
  134. rawLinesData.push([]);
  135. isMouseDown = true;
  136. });
  137. container.addEventListener('mouseup', function () {
  138. isMouseDown = false;
  139. });
  140. container.addEventListener('mousemove', function (event) {
  141. if (isMouseDown) {
  142. var containerArea = container.getBoundingClientRect(),
  143. x = event.clientX - containerArea.left,
  144. y = event.clientY - containerArea.top;
  145. rawLinesData[rawLinesData.length - 1].push([x, y]);
  146. updateLines();
  147. }
  148. });
  149. errorInput.addEventListener('input', function () {
  150. error = parseInt(this.value);
  151. errorValue.innerText = error;
  152. updateLines(true);
  153. });
  154. clearButton.addEventListener('click', function () {
  155. rawLinesData = [];
  156. rawLines.concat(fittedCurves).forEach(function (rawLine) {
  157. rawLine.remove();
  158. });
  159. rawLines = [];
  160. fittedCurvesData = [];
  161. fittedCurves = [];
  162. cleanBezierHelpGraphics();
  163. });
  164. showBezierDotsCheckbox.addEventListener('click', function () {
  165. showBezierDots = this.checked;
  166. updateLines();
  167. });
  168. showBezierControlPointsCheckbox.addEventListener('click', function () {
  169. showBezierControlPoints = this.checked;
  170. updateLines();
  171. });
  172. };