自定义 Gizmo 进阶

上一篇 讲了如何自定义一个跟随节点移动并缩放的 Gizmo,这篇我们将实现一个可以编辑的 Gizmo

  1. letToolType={
  2. None:0,
  3. Side:1,
  4. Center:2
  5. };
  6. classCustomGizmoextendsEditor.Gizmo{
  7. init (){
  8. // 初始化一些参数
  9. }
  10. onCreateMoveCallbacks (){
  11. // 创建 gizmo 操作回调
  12. // 申明一些局部变量
  13. let startOffset;// 按下鼠标时记录的园偏移量
  14. let startRadius;// 按下鼠标时记录的圆半径
  15. let pressx, pressy;// 按下鼠标时记录的鼠标位置
  16. return{
  17. /**
  18. * 在 gizmo 上按下鼠标时触发
  19. * @param x 按下点的 x 坐标
  20. * @param y 按下点的 y 坐标
  21. * @param event mousedown dom event
  22. */
  23. start:(x, y,event)=>{
  24. startRadius =this.target.radius;
  25. startOffset =this.target.offset;
  26. pressx = x;
  27. pressy = y;
  28. },
  29. /**
  30. * 在 gizmo 上按下鼠标移动时触发
  31. * @param dx 鼠标移动的 x 位移
  32. * @param dy 鼠标移动的 y 位移
  33. * @param event mousedown dom event
  34. */
  35. update:(dx, dy,event, type)=>{
  36. // 获取 gizmo 依附的节点
  37. let node =this.node;
  38. // 获取 gizmo 依附的组件
  39. let target =this.target;
  40. if(type ===ToolType.Center){
  41. // 计算新的偏移量
  42. let t = cc.affineTransformClone( node.getWorldToNodeTransform());
  43. t.tx = t.ty =0;
  44. let d = cc.v2(cc.pointApplyAffineTransform(dx, dy, t)).add(startOffset);
  45. target.offset = d;
  46. this.adjustValue(target,'offset');
  47. }
  48. else{
  49. // 转换坐标点到节点下
  50. let position = node.convertToNodeSpaceAR(cc.v2(pressx + dx, pressy + dy));
  51. // 计算 radius
  52. target.radius = position.sub(startOffset).mag();
  53. // 防止 radius 小数点位数过多
  54. this.adjustValue(target,'radius');
  55. }
  56. },
  57. /**
  58. * 在 gizmo 抬起鼠标时触发
  59. * @param event mousedown dom event
  60. */
  61. end:(updated,event)=>{
  62. }
  63. };
  64. }
  65. onCreateRoot (){
  66. // 创建 svg 根节点的回调,可以在这里创建你的 svg 工具
  67. // this._root 可以获取到 Editor.Gizmo 创建的 svg 根节点
  68. // 实例:
  69. // 创建一个 svg 工具
  70. // group 函数文档 : http://documentup.com/wout/svg.js#groups
  71. this._tool =this._root.group();
  72. // 创建中心拖拽区域,用于操作 offset 属性
  73. let dragArea =this._tool.circle()
  74. // 设置 fill 样式
  75. .fill({ color:'rgba(0,128,255,0.2)'})
  76. // 设置点击区域,这里设置的是根据 fill 模式点击
  77. .style('pointer-events','fill')
  78. // 设置鼠标样式
  79. .style('cursor','move')
  80. ;
  81. // 注册监听鼠标移动事件的 svg 元素
  82. // ToolType.Center 是自定义的参数,会在移动回调中按照参数的形式传递到移动回调中,方便区别当前回调是哪一个 svg 元素产生的回调。
  83. // {cursor: 'move'} 指定移动时的鼠标类型
  84. this.registerMoveSvg( dragArea,ToolType.Center,{cursor:'move'});
  85. // 创建边缘拖拽区域,用于操作 radius 属性
  86. let circle =this._tool.circle()
  87. // 设置stroke 样式
  88. .stroke({ color:'#7fc97a', width:2})
  89. // 设置点击区域,这里设置的是根据 stroke 模式点击
  90. .style('pointer-events','stroke')
  91. // 设置鼠标样式
  92. .style('cursor','pointer')
  93. this.registerMoveSvg( circle,ToolType.Side,{cursor:'pointer'});
  94. // 为 tool 定义一个绘画函数,方便在 onUpdate 中更新 svg 的绘制。
  95. this._tool.plot =(radius, position)=>{
  96. this._tool.move(position.x, position.y);
  97. dragArea.radius(radius);
  98. circle.radius(radius);
  99. };
  100. }
  101. onUpdate (){
  102. // 更新 svg 工具
  103. // 获取 gizmo 依附的组件
  104. let target =this.target;
  105. // 获取 gizmo 依附的节点
  106. let node =this.node;
  107. // 获取节点世界坐标
  108. let position = node.convertToWorldSpaceAR(target.offset);
  109. // 转换世界坐标到 svg view 上
  110. // svg view 的坐标体系和节点坐标体系不太一样,这里使用内置函数来转换坐标
  111. position =this.worldToPixel(position);
  112. // 对齐坐标,防止 svg 因为精度问题产生抖动
  113. position =Editor.GizmosUtils.snapPixelWihVec2( position );
  114. // 获取世界坐标下圆半径
  115. let p1 = node.convertToWorldSpaceAR(cc.p(target.radius,0));
  116. let p2 = node.convertToWorldSpaceAR(cc.p(0,0));
  117. let radius = p1.sub(p2).mag();
  118. // 对齐坐标,防止 svg 因为精度问题产生抖动
  119. radius =Editor.GizmosUtils.snapPixel(radius);
  120. // 移动 svg 工具到坐标
  121. this._tool.plot(radius, position);
  122. }
  123. }
  124. module.exports =CustomGizmo;

更多 Gizmo Api 请参考 Gizmo Api更多 Gizmo 实例请参考 Gizmo 实例