• 自定义 Gizmo 进阶

    自定义 Gizmo 进阶

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

    1、在 资源管理器CustomComponent 脚本中定义 offset:

    1. properties: {
    2. //...
    3. offset: cc.Vec2
    4. },

    2、将 custom-gizmo.js 改为以下内容并保存:

    1. let ToolType = {
    2. None: 0,
    3. Side: 1,
    4. Center: 2
    5. };
    6. class CustomGizmo extends Editor.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 mat4 = cc.vmath.mat4.create();
    43. node.getWorldMatrix(mat4);
    44. let t = cc.vmath.mat4.invert(mat4, mat4);
    45. t.m12 = t.m13 = 0;
    46. let d = cc.v2(dx, dy);
    47. cc.vmath.vec2.transformMat4(d, d, t);
    48. d.addSelf(startOffset);
    49. target.offset = d;
    50. this.adjustValue(target, 'offset');
    51. }
    52. else {
    53. // 转换坐标点到节点下
    54. let position = node.convertToNodeSpaceAR(cc.v2(pressx + dx, pressy + dy));
    55. // 计算 radius
    56. target.radius = position.sub(startOffset).mag();
    57. // 防止 radius 小数点位数过多
    58. this.adjustValue(target, 'radius');
    59. }
    60. },
    61. /**
    62. * 在 gizmo 抬起鼠标时触发
    63. * @param event mousedown dom event
    64. */
    65. end: (updated, event) => {
    66. }
    67. };
    68. }
    69. onCreateRoot () {
    70. // 创建 svg 根节点的回调,可以在这里创建你的 svg 工具
    71. // this._root 可以获取到 Editor.Gizmo 创建的 svg 根节点
    72. // 实例:
    73. // 创建一个 svg 工具
    74. // group 函数文档 : http://documentup.com/wout/svg.js#groups
    75. this._tool = this._root.group();
    76. // 创建中心拖拽区域,用于操作 offset 属性
    77. let dragArea = this._tool.circle()
    78. // 设置 fill 样式
    79. .fill( { color: 'rgba(0,128,255,0.2)' } )
    80. // 设置点击区域,这里设置的是根据 fill 模式点击
    81. .style( 'pointer-events', 'fill' )
    82. // 设置鼠标样式
    83. .style( 'cursor', 'move' )
    84. ;
    85. // 注册监听鼠标移动事件的 svg 元素
    86. // ToolType.Center 是自定义的参数,会在移动回调中按照参数的形式传递到移动回调中,方便区别当前回调是哪一个 svg 元素产生的回调。
    87. // {cursor: 'move'} 指定移动时的鼠标类型
    88. this.registerMoveSvg( dragArea, ToolType.Center, {cursor: 'move'} );
    89. // 创建边缘拖拽区域,用于操作 radius 属性
    90. let circle = this._tool.circle()
    91. // 设置stroke 样式
    92. .stroke( { color: '#7fc97a', width: 2 } )
    93. // 设置点击区域,这里设置的是根据 stroke 模式点击
    94. .style( 'pointer-events', 'stroke' )
    95. // 设置鼠标样式
    96. .style( 'cursor', 'pointer' )
    97. this.registerMoveSvg( circle, ToolType.Side, {cursor: 'pointer'} );
    98. // 为 tool 定义一个绘画函数,方便在 onUpdate 中更新 svg 的绘制。
    99. this._tool.plot = (radius, position) => {
    100. this._tool.move(position.x, position.y);
    101. dragArea.radius(radius);
    102. circle.radius(radius);
    103. };
    104. }
    105. onUpdate () {
    106. // 更新 svg 工具
    107. // 获取 gizmo 依附的组件
    108. let target = this.target;
    109. // 获取 gizmo 依附的节点
    110. let node = this.node;
    111. // 获取节点世界坐标
    112. let position = node.convertToWorldSpaceAR(target.offset);
    113. // 转换世界坐标到 svg view 上
    114. // svg view 的坐标体系和节点坐标体系不太一样,这里使用内置函数来转换坐标
    115. position = this.worldToPixel(position);
    116. // 对齐坐标,防止 svg 因为精度问题产生抖动
    117. position = Editor.GizmosUtils.snapPixelWihVec2( position );
    118. // 获取世界坐标下圆半径
    119. let p1 = node.convertToWorldSpaceAR(cc.v2(target.radius, 0));
    120. let p2 = node.convertToWorldSpaceAR(cc.v2(0, 0));
    121. let radius = p1.sub(p2).mag();
    122. // 对齐坐标,防止 svg 因为精度问题产生抖动
    123. radius = Editor.GizmosUtils.snapPixel(radius);
    124. // 移动 svg 工具到坐标
    125. this._tool.plot(radius, position);
    126. }
    127. }
    128. module.exports = CustomGizmo;

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