BezierData.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. let Bezier = require("Bezier")
  2. let EventListener = require("EventListener")
  3. let BezierData = (function () {
  4. let _this = {};
  5. // ------------------------【私有属性】---------------------------
  6. // point预制体
  7. let pointPrefab = null;
  8. let controlPrefab = null;
  9. // 贝塞尔曲线列表
  10. let bezierCurveLists = [];
  11. // 曲线点列表
  12. let bezierCurveData = {
  13. time: 5,//运行总时长
  14. length: 0,//曲线总长
  15. points: [],//曲线点列表
  16. pointsData: [],//所有历史点,可以重新导入
  17. }
  18. // // 点 - 曲线 字典
  19. let pointCurveDict = new Map();
  20. // // 点 数据 字典 用于历史数据导入
  21. let pointCurveData = {};
  22. // 需要删除的目标节点
  23. let deleteTarget = null;
  24. // 点计数
  25. let PointNum = 0;
  26. // 父节点
  27. let pointParent = null;
  28. // 曲线类型
  29. let currentBezierType = 2;
  30. // 每段曲线的切割份数
  31. let pointCount = 10;
  32. // 画板分辨率
  33. let resolution = {
  34. width: 1280,
  35. height: 800
  36. }
  37. _this.canAddPos = false
  38. // ------------------------【公有方法】---------------------------
  39. // 初始化
  40. _this.init = function (point, control, parent) {
  41. this.clearAllBezier()
  42. pointPrefab = point;
  43. controlPrefab = control;
  44. pointParent = parent;
  45. initRandCurve();
  46. }
  47. // 获取分辨率
  48. _this.getResolution = function (params) {
  49. return resolution;
  50. }
  51. // 设置分辨率
  52. _this.setResolution = function (width, height) {
  53. resolution = {width, height};
  54. return resolution;
  55. }
  56. // 设置曲线切割份数
  57. _this.setPointCount = function (num) {
  58. pointCount = num;
  59. }
  60. // 设置曲线类型
  61. _this.setBezierCurveType = function (type) {
  62. currentBezierType = type;
  63. }
  64. // 设置删除的目标节点
  65. _this.setDeleteTarget = function (node) {
  66. deleteTarget = node;
  67. }
  68. // 添加贝塞尔曲线到列表
  69. _this.addBezierCurve = function (curve) {
  70. bezierCurveLists.push(curve);
  71. console.log("bezierCurveLists", bezierCurveLists);
  72. }
  73. // 获取曲线类型
  74. _this.getBezierCurveType = function () {
  75. return currentBezierType;
  76. }
  77. // 获取贝塞尔曲线列表
  78. _this.getBezierCurveLists = function () {
  79. return bezierCurveLists;
  80. }
  81. // 获取贝塞尔曲线数据
  82. _this.getBezierCurveData = function () {
  83. return bezierCurveData;
  84. }
  85. // 设置贝塞尔曲线运行时长
  86. _this.setBezierCurveRunTime = function (time) {
  87. bezierCurveData.time = time;
  88. }
  89. // 是否是最后一个曲线
  90. _this.isLastCurve = function () {
  91. return bezierCurveLists.length <= 1;
  92. }
  93. // 创建二阶贝塞尔曲线
  94. _this.createCurve = function (pos) {
  95. let end = createPoint(lcl.Ident.point, pos);
  96. let control = createPoint(lcl.Ident.control, pos);
  97. // 把曲线列表最后一个点作为新曲线起点
  98. let start = bezierCurveLists[bezierCurveLists.length - 1].end;
  99. let curve = {start, control, end}
  100. bezierCurveLists.push(curve);
  101. this.saveToPointCurveDict(curve);
  102. console.log("bezierLists->", bezierCurveLists)
  103. }
  104. // 创建三阶贝塞尔曲线
  105. _this.createThirdOrderCurve = function (pos) {
  106. // 把曲线列表最后一个点作为新曲线起点
  107. let start = bezierCurveLists[bezierCurveLists.length - 1].end;
  108. let end = createPoint(lcl.Ident.point, pos);
  109. let control2 = createPoint(lcl.Ident.control, pos);
  110. //计算偏移点
  111. let c1pos = cc.v2(200, 200).add(start.position);
  112. c1pos.x = Math.min(resolution.width / 2, c1pos.x);
  113. c1pos.y = Math.min(resolution.height / 2, c1pos.y);
  114. let control1 = createPoint(lcl.Ident.control, c1pos, false);
  115. let curve = {start, control1, control2, end}
  116. bezierCurveLists.push(curve);
  117. this.saveToPointCurveDict(curve);
  118. console.log("bezierLists->", bezierCurveLists)
  119. }
  120. // 存储到曲线字典
  121. // key - 点, value - 该点所关联的曲线对象Obj,
  122. // 曲线对象Obj: start字段 为 该点作为起点所在的曲线, control end类似
  123. _this.saveToPointCurveDict = function (curve) {
  124. let obj;
  125. let objData;
  126. for (const key in curve) {
  127. const point = curve[key];
  128. if (pointCurveDict.has(point)) {
  129. obj = pointCurveDict.get(point);
  130. } else {
  131. obj = {};
  132. }
  133. obj[key + "Curve"] = curve;
  134. pointCurveDict.set(point, obj);
  135. }
  136. console.log("pointCurveDict", pointCurveDict);
  137. }
  138. // 删除节点
  139. _this.deletePoint = function () {
  140. if (pointCurveDict.has(deleteTarget)) {
  141. let location = getPointLocation(deleteTarget)
  142. if (location == "center") {
  143. deleteCenterPoint(deleteTarget);
  144. } else if (location == "start") {
  145. deleteStartPoint(deleteTarget);
  146. } else if (location == "end") {
  147. deleteEndPoint(deleteTarget);
  148. }
  149. }
  150. }
  151. // 保存路径
  152. _this.saveBezierPath = function () {
  153. bezierCurveData.length = 0;
  154. bezierCurveData.points = [];
  155. bezierCurveData.pointsData = [];
  156. console.log("保存路径bezierLists", bezierCurveLists);
  157. for (var i = 0, len = bezierCurveLists.length; i < len; i++) {
  158. const bezier = bezierCurveLists[i];
  159. // 创建一个贝塞尔曲线
  160. // let bezierCurve = new Bezier(bezier.start, bezier.control, bezier.end, 100);
  161. // console.log("consscscds", Object.values(bezier));
  162. let posNameArr = ['start', 'control', 'control1', 'control2', 'end']
  163. let bezierArr = []
  164. for (let i = 0; i < posNameArr.length; i++) {
  165. if (bezier[posNameArr[i]]) {
  166. bezierArr.push(bezier[posNameArr[i]])
  167. }
  168. }
  169. let bezierCurve = new Bezier(bezierArr, 2);
  170. // 获取曲线点
  171. let points = bezierCurve.getPoints(pointCount);
  172. points.forEach(pos => {
  173. pos.x = parseFloat(pos.x.toFixed(5))
  174. pos.y = parseFloat(pos.y.toFixed(5))
  175. pos.length = parseFloat(pos.length.toFixed(2))
  176. })
  177. console.log("consscscds", pointCount);
  178. // 获取曲线长度
  179. let curveLength = bezierCurve.getCurveLength();
  180. // 计算路程长度
  181. bezierCurveData.length += curveLength;
  182. // 存储曲线点
  183. bezierCurveData.points.push(...points);
  184. // console.log("points", points);
  185. let obj = {}
  186. let convertNode2Data = (node, key) => {
  187. let tmp = {}
  188. tmp.position = cc.v2(parseFloat(node.x.toFixed(3)),parseFloat(node.y.toFixed(3)))
  189. tmp.Ident = key.includes('control') ? lcl.Ident.control : lcl.Ident.point
  190. return tmp
  191. }
  192. if (i == 0) {
  193. obj.start = convertNode2Data(bezier.start, 'start')
  194. }
  195. posNameArr.shift()
  196. for (let posName of posNameArr) {
  197. if (bezier[posName]) {
  198. obj[posName] = convertNode2Data(bezier[posName], posName)
  199. }
  200. }
  201. bezierCurveData.pointsData.push(obj)
  202. }
  203. console.log("保存路径bezierCurveData", bezierCurveData);
  204. console.log("保存路径pointCurveDict->", pointCurveDict)
  205. }
  206. // 情况所有曲线
  207. _this.clearAllBezier = function () {
  208. console.log("clearAllBezier");
  209. bezierCurveLists = [];
  210. pointCurveDict.forEach((curve, point) => {
  211. if (point)
  212. point.destroy();
  213. })
  214. pointCurveDict.clear()
  215. }
  216. // 导入历史轨迹
  217. _this.importCurveData = function (data) {
  218. PointNum = 0
  219. _this.clearAllBezier()
  220. lcl.NodeEvents.setMoveTargetNode(null);
  221. for (let i = 0; i < data.pointsData.length; i++) {
  222. let bezierData = data.pointsData[i]
  223. let bezier = {}
  224. let posNameArr = ['start', 'control', 'control1', 'control2', 'end']
  225. for (let posName of posNameArr) {
  226. if (bezierData[posName]) {
  227. bezier[posName] = createPoint(bezierData[posName].Ident, bezierData[posName].position)
  228. }
  229. }
  230. if (i > 0) {
  231. bezier.start = bezierCurveLists[bezierCurveLists.length - 1].end;
  232. }
  233. BezierData.addBezierCurve(bezier);
  234. this.saveToPointCurveDict(bezier);
  235. }
  236. //this.saveBezierPath();
  237. }
  238. // ------------------------【私有方法】---------------------------
  239. // 创建新节点
  240. let createPoint = function (ident, pos, isSelect = true) {
  241. let node;
  242. let name;
  243. if (ident == lcl.Ident.point) {
  244. node = cc.instantiate(pointPrefab);
  245. node.ident = lcl.Ident.point;
  246. name = "point";
  247. } else if (ident == lcl.Ident.control) {
  248. node = cc.instantiate(controlPrefab);
  249. node.ident = lcl.Ident.control;
  250. name = "control";
  251. if (isSelect) lcl.NodeEvents.setMoveTargetNode(node);
  252. }
  253. let count = PointNum++;
  254. node.name = name + "_" + count;
  255. node.parent = pointParent;
  256. node.setPosition(pos);
  257. lcl.NodeEvents.addPointDeleteEvents(node);
  258. lcl.NodeEvents.addDragEvents(node);
  259. // 创建编号
  260. let num = new cc.Node();
  261. num.parent = node;
  262. num.y = 20;
  263. let label = num.addComponent(cc.Label)
  264. label.string = count
  265. label.fontSize = 12
  266. return node
  267. }
  268. let getRandPos = function () {
  269. let randX = Math.random() * resolution.width - resolution.width * 0.5;
  270. let randY = Math.random() * resolution.height - resolution.height * 0.5;
  271. return cc.v2(randX, randY)
  272. }
  273. // 初始化一个随机曲线
  274. let initRandCurve = function () {
  275. let start = createPoint(lcl.Ident.point, getRandPos());
  276. let control = createPoint(lcl.Ident.control, getRandPos());
  277. let end = createPoint(lcl.Ident.point, getRandPos());
  278. lcl.NodeEvents.setMoveTargetNode(null);
  279. let bezier = {start, control, end}
  280. BezierData.addBezierCurve(bezier);
  281. BezierData.saveToPointCurveDict(bezier);
  282. }
  283. // 判断该点是起点,终点或者中间点
  284. let getPointLocation = function (node) {
  285. let curveObj = pointCurveDict.get(node);
  286. if (curveObj) {
  287. if (curveObj["startCurve"] && curveObj["endCurve"]) {
  288. return "center";
  289. }
  290. if (curveObj["startCurve"]) {
  291. return "start";
  292. }
  293. if (curveObj["endCurve"]) {
  294. return "end";
  295. }
  296. }
  297. return 0;
  298. }
  299. // 删除的是中间点
  300. let deleteCenterPoint = function (point) {
  301. console.warn("删除的是中间点");
  302. if (pointCurveDict.has(point)) {
  303. //中间点有前后两个曲线,删除该点就需要合并两个曲线(这里的方案是保留前面的曲线,删除后面的曲线)
  304. let CurveObj = pointCurveDict.get(point);
  305. let prevCurve = CurveObj.endCurve;
  306. let nextCurve = CurveObj.startCurve;
  307. // 把前一个曲线的终点移动到后一个曲线的终点上
  308. prevCurve.end = nextCurve.end;
  309. // 重新赋值该节点下的曲线对象的end曲线
  310. let prevEndCurveObj = pointCurveDict.get(prevCurve.end);
  311. prevEndCurveObj.endCurve = prevCurve;
  312. pointCurveDict.delete(point);
  313. // 删除后曲线相关的信息
  314. for (const key in nextCurve) {
  315. if (key == "end") continue;
  316. const _point = nextCurve[key];
  317. pointCurveDict.delete(_point)
  318. _point.destroy();
  319. }
  320. // pointCurveDict.delete(nextCurve.start)
  321. // pointCurveDict.delete(nextCurve.control)
  322. // nextCurve.start.destroy();
  323. // nextCurve.control.destroy();
  324. deleteCurveFromBezierLists(nextCurve);
  325. }
  326. }
  327. // 删除的是起点
  328. let deleteStartPoint = function (point) {
  329. console.warn("删除的是起点");
  330. if (pointCurveDict.has(point)) {
  331. //找到该点关联的曲线
  332. let CurveObj = pointCurveDict.get(point);
  333. let startCurve = CurveObj.startCurve;
  334. CurveObj.endCurve = null;
  335. // 删除曲线及其相关的点
  336. let endCurveObj = pointCurveDict.get(startCurve.end);
  337. endCurveObj.endCurve = null;
  338. for (const key in startCurve) {
  339. if (key == "end") continue;
  340. const _point = startCurve[key];
  341. pointCurveDict.delete(_point)
  342. _point.destroy();
  343. }
  344. deleteCurveFromBezierLists(startCurve);
  345. }
  346. }
  347. // 删除的是终点
  348. let deleteEndPoint = function (point) {
  349. console.warn("删除的是终点");
  350. if (pointCurveDict.has(point)) {
  351. let CurveObj = pointCurveDict.get(point);
  352. let endCurve = CurveObj.endCurve;
  353. CurveObj.startCurve = null;
  354. // 删除曲线及其相关的点
  355. let startCurveObj = pointCurveDict.get(endCurve.start);
  356. startCurveObj.startCurve = null;
  357. for (const key in endCurve) {
  358. if (key == "start") continue;
  359. const _point = endCurve[key];
  360. pointCurveDict.delete(_point)
  361. _point.destroy();
  362. }
  363. // pointCurveDict.delete(endCurve.control)
  364. // endCurve.control.destroy();
  365. deleteCurveFromBezierLists(endCurve);
  366. }
  367. }
  368. //从曲线列表删除曲线
  369. let deleteCurveFromBezierLists = function (curve) {
  370. for (var i = 0, len = bezierCurveLists.length; i < len; i++) {
  371. const _curve = bezierCurveLists[i];
  372. if (_curve === curve) {
  373. bezierCurveLists.splice(i, 1);
  374. return
  375. }
  376. }
  377. }
  378. return _this;
  379. }());
  380. module.exports = BezierData;