• 自定义 Gizmo 进阶

    自定义 Gizmo 进阶

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

    1. class CustomGizmo extends Editor.Gizmo {
    2. init () {
    3. // 初始化一些参数
    4. }
    5. createGizmoCallBacks () {
    6. // 创建 gizmo 操作回调
    7. // 申明一些局部变量
    8. let startRadius; // 按下鼠标时记录的圆半径
    9. let pressx, pressy; // 按下鼠标时记录的鼠标位置
    10. let updated; // 记录 gizmo 是否被操作过
    11. return {
    12. /**
    13. * 在 gizmo 上按下鼠标时触发
    14. * @property x 按下点的 x 坐标
    15. * @property y 按下点的 y 坐标
    16. * @property event mousedown dom event
    17. */
    18. start: (x, y, event) => {
    19. startRadius = this.target.radius;
    20. pressx = x;
    21. pressy = y;
    22. updated = false;
    23. },
    24. /**
    25. * 在 gizmo 上按下鼠标移动时触发
    26. * @property dx 鼠标移动的 x 位移
    27. * @property dy 鼠标移动的 y 位移
    28. * @property event mousedown dom event
    29. */
    30. update: (dx, dy, event) => {
    31. if (dx === 0 && dy === 0) {
    32. return;
    33. }
    34. updated = true;
    35. // 获取 gizmo 依附的节点
    36. let node = this.node;
    37. // 记录节点信息的 undo 信息,注意参数为节点的 uuid
    38. _Scene.Undo.recordNode( node.uuid );
    39. // 获取 svg view 坐标系下点
    40. let x = pressx + dx, y = pressy + dy;
    41. // 获取节点世界坐标系下点
    42. let pos = this._view.pixelToWorld( cc.v2(x, y) );
    43. // 转换坐标点到节点下
    44. pos = node.convertToNodeSpaceAR(pos);
    45. // 计算 radius
    46. let radius = pos.mag();
    47. // js 在做一些计算后会出现小数位过长的情况, Editor.Math.toPrecision 会帮助做一些小数位的截取
    48. let minDifference = Editor.Math.numOfDecimalsF(1.0/this._view.scale);
    49. this.target.radius = Editor.Math.toPrecision(radius, minDifference);
    50. // 更新 gizmo view
    51. this._view.repaintHost();
    52. },
    53. /**
    54. * 在 gizmo 抬起鼠标时触发
    55. * @property event mousedown dom event
    56. */
    57. end: (event) => {
    58. // 判断是否有操作过 gizmo, 没有则跳过处理
    59. if (updated) {
    60. // 如果 gizmo 有修改需要进入 animation 编辑的属性,需要调用此接口来更新数据
    61. // _Scene.AnimUtils.recordNodeChanged(this.node);
    62. // 推送修改到 undo 下,结束 undo
    63. _Scene.Undo.commit();
    64. }
    65. }
    66. };
    67. }
    68. onCreateRoot () {
    69. // 创建 svg 根节点的回调,可以在这里创建你的 svg 工具
    70. // this._root 可以获取到 Editor.Gizmo 创建的 svg 根节点
    71. // 实例:
    72. // 创建一个 svg 工具
    73. // group 函数文档 : http://documentup.com/wout/svg.js#groups
    74. this._tool = this._root.group();
    75. let circle = this._tool.circle()
    76. // 设置 circle fill 样式
    77. .fill( { color: 'rgba(0,128,255,0.2)' } )
    78. // 设置 circle stroke 样式
    79. .stroke( { color: 'rgba(0,128,255,0.4)', width: 1 } )
    80. // 设置 circle 的点击区域,这里设置的是根据 fill 模式点击
    81. .style( 'pointer-events', 'fill' )
    82. // 设置 circle 鼠标样式
    83. .style( 'cursor', 'pointer' )
    84. ;
    85. // 为 tool 定义一个绘画函数,可以为其他名字
    86. this._tool.plot = (radius, position) => {
    87. this._tool.move(position.x, position.y);
    88. circle.radius(radius);
    89. };
    90. // 创建 gizmo 操作回调函数
    91. let callbacks = this.createGizmoCallBacks();
    92. // 为 tool 添加一个操作回调
    93. // 当在 tool 上按下鼠标时,会创建一个 drag mask
    94. // 如果不需要此辅助函数,可以自行对 tool 注册 mousedown, mousemove, mouseup 来进行操作
    95. Editor.GizmosUtils.addMoveHandles( this._tool, {cursor: 'pointer'}, callbacks );
    96. }
    97. onUpdate () {
    98. // 更新 svg 工具
    99. // 获取 gizmo 依附的组件
    100. let target = this.target;
    101. // 获取 gizmo 依附的节点
    102. let node = this.node;
    103. // 获取组件半径
    104. let radius = target.radius;
    105. // 获取节点世界坐标
    106. let worldPosition = node.convertToWorldSpaceAR(cc.p(0, 0));
    107. // 转换世界坐标到 svg view 上
    108. // svg view 的坐标体系和节点坐标体系不太一样,这里使用内置函数来转换坐标
    109. let viewPosition = this._view.worldToPixel(worldPosition);
    110. // 对齐坐标,防止 svg 因为精度问题产生抖动
    111. let p = Editor.GizmosUtils.snapPixelWihVec2( viewPosition );
    112. // 获取世界坐标下圆半径
    113. let worldPosition2 = node.convertToWorldSpaceAR(cc.p(radius, 0));
    114. let worldRadius = worldPosition.sub(worldPosition2).mag();
    115. worldRadius = Editor.GizmosUtils.snapPixel(worldRadius);
    116. // 移动 svg 工具到坐标
    117. this._tool.plot(worldRadius, p);
    118. }
    119. }
    120. module.exports = CustomGizmo;