demo.controller.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. * PS 钢笔工具 控制逻辑
  3. */
  4. define( function ( require, exports, module ) {
  5. // 资源引入
  6. var Bezier = require( "graphic/bezier" ),
  7. Color = require( "graphic/color" ),
  8. Pen = require( "graphic/pen" ),
  9. Utils = require( "core/utils" ),
  10. Vector = require( "graphic/vector" ),
  11. // 引入可绘制的点集合
  12. PointGroup = require( "../ps-pen/demo.pointgroup" ),
  13. BezierPoint = require( "graphic/bezierpoint" );
  14. function Controller ( paper ) {
  15. this.paper = paper || null;
  16. this.bezier = null;
  17. this.bezierPoints = null;
  18. this.pointGroup = null;
  19. this.drawState = false;
  20. // 记录当前是否处于更新状态
  21. this.modifyState = false;
  22. // 记录更新状态的持久信息
  23. this._modifyStatus = null;
  24. // 允许重新拖动编辑的
  25. this.editable = false;
  26. }
  27. Utils.extend( Controller.prototype, {
  28. takeover: function ( paper ) {
  29. paper && ( this.paper = paper );
  30. initListener( this );
  31. },
  32. enableDraw: function () {
  33. this.drawState = true;
  34. },
  35. disableDraw: function () {
  36. this.drawState = false;
  37. },
  38. enableModify: function () {
  39. this.modifyState = true;
  40. },
  41. disableModify: function () {
  42. this.modifyState = false;
  43. },
  44. // 设置更新状态
  45. setModifyStatus: function ( status ) {
  46. this._modifyStatus = status;
  47. },
  48. clearModifySatus: function () {
  49. this._modifyStatus = null;
  50. },
  51. getModifyStatus: function () {
  52. return this._modifyStatus;
  53. },
  54. enableEdit: function () {
  55. this.editable = true;
  56. },
  57. disableEdit: function () {
  58. this.editable = false;
  59. },
  60. setBezier: function ( bezier ) {
  61. this.bezier = bezier;
  62. this.bezierPoints = [];
  63. return this;
  64. },
  65. getBezier: function () {
  66. return this.bezier;
  67. },
  68. setPointGroup: function ( pointGroup ) {
  69. this.pointGroup = pointGroup;
  70. return this;
  71. },
  72. getPointGroup: function () {
  73. return this.pointGroup;
  74. },
  75. addPoint: function ( point ) {
  76. this.bezierPoints && this.bezierPoints.push( point );
  77. return this;
  78. },
  79. getPoints: function () {
  80. return this.bezierPoints;
  81. }
  82. } );
  83. return Controller;
  84. // 私有方法实现
  85. // 初始化交互事件监听器
  86. function initListener ( controller ) {
  87. // 记录是否允许所有事件的监听
  88. var isBegin = false,
  89. // 记录是否需要更新曲线
  90. isUpdateable = false,
  91. paper = controller.paper,
  92. currentBezier = null,
  93. currentPointGroup = null;
  94. paper.on( "mousedown", function ( e ) {
  95. var point = null;
  96. e.preventDefault();
  97. if ( !controller.drawState ) {
  98. return;
  99. }
  100. // 切换监听状态
  101. if ( !isBegin ) {
  102. isBegin = true;
  103. currentBezier = createBezier( paper );
  104. currentPointGroup = createPointGroup( paper );
  105. listenPointGroup( currentPointGroup, controller );
  106. //设置当前controller处理的贝塞尔曲线
  107. controller.setBezier( currentBezier );
  108. controller.setPointGroup( currentPointGroup );
  109. }
  110. isUpdateable = false;
  111. // 获取当前鼠标点击在用户坐标系上的映射点
  112. point = e.getPosition();
  113. updateBezier( controller, point );
  114. } );
  115. // 绘制时 更新控制点
  116. paper.on( "mousemove", function ( e ) {
  117. var point = null,
  118. bezierPoint = null;
  119. e.preventDefault();
  120. if ( !controller.drawState ) {
  121. return;
  122. }
  123. if ( !isBegin || isUpdateable ) {
  124. return;
  125. }
  126. point = e.getPosition();
  127. currentBezier.getLastPoint().setForward( point.x, point.y );
  128. currentPointGroup.getLastPoint().setForward( point.x, point.y );
  129. } );
  130. // 编辑时拖动更新
  131. paper.on( "mousemove", function ( e ) {
  132. var mousePoint = null,
  133. currentPoint = null,
  134. pointIndex = -1;
  135. e.preventDefault();
  136. // 不可编辑
  137. if ( !controller.editable ) {
  138. return;
  139. }
  140. mousePoint = e.getPosition();
  141. pointIndex = controller._modifyStatus.pointIndex;
  142. currentPoint = currentPointGroup.getPointByIndex( pointIndex );
  143. switch ( controller._modifyStatus.pointType ) {
  144. case PointGroup.TYPE_FORWARD:
  145. currentPoint.setForward( mousePoint.x, mousePoint.y );
  146. currentBezier.getPoint( pointIndex ).setForward( mousePoint.x, mousePoint.y );
  147. break;
  148. case PointGroup.TYPE_BACKWARD:
  149. currentPoint.setBackward( mousePoint.x, mousePoint.y );
  150. currentBezier.getPoint( pointIndex ).setBackward( mousePoint.x, mousePoint.y );
  151. break;
  152. case PointGroup.TYPE_VERTEX:
  153. currentPoint.moveTo( mousePoint.x, mousePoint.y );
  154. currentBezier.getPoint( pointIndex ).moveTo( mousePoint.x, mousePoint.y );
  155. break;
  156. }
  157. } );
  158. paper.on( "mouseup", function () {
  159. if ( controller.drawState ) {
  160. isUpdateable = isBegin;
  161. } else if ( controller.modifyState ) {
  162. controller.disableEdit();
  163. // 清空状态
  164. controller.clearModifySatus();
  165. }
  166. } );
  167. }
  168. // 画贝塞尔曲线
  169. function updateBezier ( controller, point ) {
  170. var bezierPoint = new BezierPoint( point.x, point.y, true );
  171. //添加可绘制控制点
  172. controller.getPointGroup().addPoint( bezierPoint.clone() );
  173. //记录贝塞尔的控制点
  174. controller.addPoint( bezierPoint );
  175. //更新贝塞尔曲线的点
  176. controller.getBezier().setPoints( controller.getPoints() );
  177. }
  178. // 创建一个新的贝塞尔
  179. function createBezier ( paper ) {
  180. var bezier = new Bezier();
  181. bezier.stroke( new Pen( new Color( "black" ) ).setWidth( 100 ) );
  182. paper.addShape( bezier );
  183. return bezier;
  184. }
  185. function createPointGroup ( paper ) {
  186. var pointGroup = new PointGroup();
  187. paper.addShape( pointGroup );
  188. return pointGroup;
  189. }
  190. // 监听点上的事件
  191. function listenPointGroup ( pointGroup, controller ) {
  192. pointGroup.on( "pointmousedown", function ( e ) {
  193. var currentPoint = null,
  194. currentType = null,
  195. index = -1,
  196. vertexWidth = 0;
  197. // 非modify状态, 不处理
  198. if ( !controller.modifyState ) {
  199. return;
  200. }
  201. index = e.targetPointIndex;
  202. currentType = e.targetPointType;
  203. currentPoint = pointGroup.getPointByIndex( index );
  204. // 获取到当前顶点的宽度
  205. vertexWidth = pointGroup.getVertexWidth();
  206. // 检查当前点击的点的控制点是否和顶点重叠
  207. // 如果重叠了, 则认为点击是发生在forward的控制点上的
  208. if ( currentType === PointGroup.TYPE_VERTEX ) {
  209. //更新点类型
  210. switch ( checkOverlapping( currentPoint, vertexWidth ) ) {
  211. case 1:
  212. currentType = PointGroup.TYPE_FORWARD;
  213. break;
  214. case 2:
  215. currentType = PointGroup.TYPE_BACKWARD
  216. break;
  217. }
  218. }
  219. // 运行更新
  220. controller.enableEdit();
  221. controller.setModifyStatus( {
  222. pointType: currentType,
  223. pointIndex: index
  224. } );
  225. //更新当前的点
  226. this.selectPoint( index );
  227. } );
  228. }
  229. // 工具方法, 检测贝塞尔曲线上的点的控制点和顶点是否重叠在一起
  230. // 参数distance控制了点之间的最小距离, 如果不大于该距离, 则认为是重叠的
  231. // 返回值有: 0: 无重叠, 1: forward重叠, 2: backward重叠
  232. function checkOverlapping ( bezierPoint, distance ) {
  233. var forward = bezierPoint.getForward(),
  234. backward = bezierPoint.getBackward(),
  235. vertex = bezierPoint.getVertex();
  236. if ( Vector.fromPoints( forward, vertex ).length() <= distance ) {
  237. // forward重叠
  238. return 1;
  239. } else if ( Vector.fromPoints( backward, vertex ).length() <= distance ) {
  240. // backward重叠
  241. return 2;
  242. }
  243. // 无重叠
  244. return 0;
  245. }
  246. } );