# 节点缩放

# 使用

LogicFlow在extension包中提供了RectResizeEllipseResizeDiamonResizeHtmlResize这4种支持缩放的基础节点, 每个节点都有viewmodel这两个属性。节点的缩放也是利用LogicFlow的自定义节点机制,使开发者可以继承这4种可以缩放的节点,来实现节点的缩放。

以我们需要一个可以缩放的矩形为例,在以前我们不支持节点缩放时,我们自定义节点方式为:

// 不可以缩放的节点
import { RectNode, RectNodeModel } from '@logicflow/core'
class CustomNode extends RectNode {}
class CustomNodeModel extends RectNodeModel {}
export default {
  type: 'custom-node',
  model: CustomNodeModel,
  view: CustomNode
}

如果我们期望自定义的节点可以缩放,那么则改成:

// 支持缩放的节点
import { RectResize } from '@logicflow/extension'
class CustomNode extends RectResize.view {}
class CustomNodeModel extends RectResize.model {}
export default {
  type: 'custom-node',
  model: CustomNodeModel,
  view: CustomNode
}

# 设置节点的形状属性

LogicFlow把节点的宽高、半径等属性称之为形状属性,我们可以重写model中的initNodeData或者setAttributes方法来设置节点的形状属性。但是当节点可以缩放后,我们不能在setAttributes中设置宽高,只能在initNodeData中设置。

class ResizableRectModel extends RectResize.model {
  initNodeData(data) {
    super.initNodeData(data)
    this.width = 100;
    this.height = 40;
  }
}

# 自定义节点的view

在自定义节点中提到过,对于样式属性比较复杂的节点,我们可以重写view中的getShape方法来实现自定义节点真实渲染的外观。但是由于自定义节点需要在节点外观上填加用于缩放的调整点,所以对于自定义可缩放节点的view,我们需要重写getResizeShape, 而不是getShape

import { RectResize } from '@logicflow/extension';

class ResizableRectModel extends RectResize.model {
  initNodeData(data) {
    super.initNodeData(data)
    this.width = 100;
    this.height = 40;
    this.text.draggable = true;
  }
}
class ResizableRectView extends RectResize.view {
  /**
   * 此方法替代自定义节点的getShape方法。
   */
  getResizeShape() {
    const { model } = this.props;
    const { x, y, width, height, radius, properties } = model;
    const style = model.getNodeStyle();
    return h("g", {}, [
      h("rect", {
        ...style,
        x: x - width / 2,
        y: y - height / 2,
        rx: radius,
        ry: radius,
        width,
        height
      }),
    ]);
  }
}

export default {
  type: "resizable-rect",
  view: ResizableRectView,
  model: ResizableRectModel
};

# 事件

节点缩放后抛出事件node:resize,抛出数据包括节点缩放前后的节点位置、节点大小信息, 数据为{oldNodeSize, newNodeSize}, 详细字段如下。

名称 类型 描述
id String 节点 id
type String 节点类型
modelType String 节点图形类型,已内部定义
x Number 节点中心x轴坐标
y Number 节点中心y轴坐标
rx Number x轴半径(椭圆、菱形)
ry Number y轴半径(椭圆、菱形)
width Number 节点宽度(矩形)
height Number 节点高度(矩形)
lf.on('node:resize', ({oldNodeSize, newNodeSize}) => {
  console.log(oldNodeSize, newNodeSize)
})

# 设置放大缩小的最大最小值

v1.1.8后,节点的放大缩小支持设置最大值和最小值。

class ResizableRectModel extends RectResize.model {
  initNodeData(data) {
    super.initNodeData(data)
    this.width = 100;
    this.height = 40;
    this.maxWidth = 400;
    this.maxHeight = 400;
  }
}

# 设置放大缩小的调整默认距离

v1.1.8后,支持设置节点的girdSize属性,用来控制鼠标移动多少距离后开始缩放节点。

class ResizableRectModel extends RectResize.model {
  initNodeData(data) {
    super.initNodeData(data)
    this.gridSize = 400;
  }
}

关于节点缩放的gridSize

大多数情况下,为了保证节点的整齐,便于节点之间的上下左右对齐。logicflow默认在放大缩小时,只有鼠标移动的距离达到初始化画布传入的gridSize两倍时才改变节点的大小。但是这样会有一个缺点,那就是调整的时候有卡顿的感觉。可以再不改变初始化gridSize的情况下,单独设置每个节点的gridSize来让放大缩小节点更流畅。

# 设置调整边框样式

可放大缩小节点在被选中时,会贴着节点显示一个虚线框(矩形没有)。可以通过重写getResizeOutlineStyle方法实现自定义其样式。

class ResizableRectModel extends RectResize.model {
  getResizeOutlineStyle() {
    return {
      stroke: '#000000',
      strokeWidth: 1,
      strokeDasharray: '3,3',
    };
  }
}

# 设置调整点样式

可放大缩小节点在被选中时,会在虚线框的四个角生成调整节点大小的操作点,可以通过重写getControlPointStyle方法实现自定义其样式。

class ResizableRectModel extends RectResize.model {
  getControlPointStyle() {
    return {
      width: 7,
      height: 7,
      fill: '#FFFFFF',
      stroke: '#000000',
    };
  }
}

地址: https://codesandbox.io/s/prod-resonance-ztpvtv (opens new window)