draggable-text-node.js 4.44 KB
/*
 * @Date: 2025-03-17 15:40:00
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-03-18 17:17:47
 * @FilePath: /logic-flow2/src/views/api/draggable-text-node.js
 * @Description: 可拖动文本的矩形节点
 */
import { RectNode, RectNodeModel } from "@logicflow/core";
import { v4 as uuidv4 } from "uuid";

const useNodeBehavior = () => {
  const isTextDraggable = ref(true);
  const isTextEditable = ref(false);

  const behavior = {
    nodeStyle: ref({
      stroke: '#1E90FF',
      fill: '#F0F8FF',
      strokeWidth: 1
    }),
    selectedStyle: ref({
      stroke: '#ff7f0e',
      strokeWidth: 2
    }),
    textStyle: ref({
      cursor: 'move'
    })
  };

  return {
    isTextDraggable,
    isTextEditable,
    behavior
  };
};

class DraggableTextNodeModel extends RectNodeModel {
  initNodeData(data) {
    // 确保 data.x 和 data.y 有默认值
    const nodeX = data.x || 0;
    const nodeY = data.y || 0;

    // 处理文本数据
    if (!data.text || typeof data.text === "string") {
      data.text = {
        value: data.text || "",
        x: nodeX,
        y: nodeY + 80,
      };
    }

    super.initNodeData(data);

    const { behavior } = useNodeBehavior();
    this.behavior = behavior;

    this.text.draggable = true;
    this.text.editable = false;
  }

  getNodeStyle() {
    /**
     * - 合并基础样式
     * - 根据选中状态添加额外样式
     */
    return {
      ...this.behavior.nodeStyle.value,
      ...(this.isSelected ? this.behavior.selectedStyle.value : {})
    };
  }

  getTextStyle() {
    /**
     * - 扩展原有文本样式
     * - 添加自定义样式(如移动光标)
     */
    const style = super.getTextStyle();
    return {
      ...style,
      ...this.behavior.textStyle.value
    };
  }

  getAnchorStyle() {
    const style = super.getAnchorStyle();
    style.stroke = "rgb(24, 125, 255)";
    style.r = 3;
    style.hover.r = 8;
    style.hover.fill = "rgb(24, 125, 255)";
    style.hover.stroke = "rgb(24, 125, 255)";
    return style;
  }

  getAnchorLineStyle() {
    const style = super.getAnchorLineStyle();
    style.stroke = "rgb(24, 125, 255)";
    return style;
  }

  getOutlineStyle() {
    const style = super.getOutlineStyle();
    style.stroke = "red";
    style.hover.stroke = "yellow";
    return style;
  }

  createId() {
    return `custom-rect-${uuidv4()}`;
  }

  // 定义节点只有左右两个锚点. 锚点位置通过中心点和宽度算出来。
  getDefaultAnchor() {
    const { width, height, x, y, id } = this;
    return [
      {
        x: x - width / 2,
        y,
        name: 'left',
        id: `${id}_0`
      },
      {
        x: x + width / 2,
        y,
        name: 'right',
        id: `${id}_1`,
        // edgeAddable: false
      },
    ]
  }

  // getConnectedSourceRules(){
  //   const rules = super.getConnectedSourceRules();
  //   const getWayOnlyAsTarget = {
  //     message: "结束节点只能连入,不能连出!",
  //     validate: ( source, target, sourceAnchor, targetAnchor ) => {
  //       let isValid = true;
  //       if (source) {
  //         isValid = false;
  //       }
  //       return isValid;
  //     },
  //   };

  //   rules.push(getWayOnlyAsTarget);
  //   return rules;
  // }

  // getConnectedTargetRules() {
  //   const rules = super.getConnectedTargetRules();
  //   const notAsTarget = {
  //     message: "起始节点不能作为边的终点",
  //     validate: () => false,
  //   };

  //   rules.push(notAsTarget);
  //   return rules;
  // }

  isAllowMoveNode(deltaX, deltaY) {
    let newX = this.x + deltaX
    let newY = this.y + deltaY
    let isAllowMoveX = true
    let isAllowMoveY = true
    // 处理
    return {
      x: isAllowMoveX,
      y: isAllowMoveY,
    }
  }

  // isAllowConnectedAsSource(target, sourceAnchor, targetAnchor) {
  //   // 根据节点类型判断是否允许连线
  //   if (this.properties.nodeType === 'source') {
  //     if (target.properties.nodeType === 'target') {
  //       return false
  //     }
  //     return true
  //   }
  // }

  // isAllowConnectedAsTarget(source, sourceAnchor, targetAnchor) {
  //   // 根据节点类型判断是否允许连线
  //   if (this.properties.nodeType ==='target') {
  //     if (source.properties.nodeType === 'source') {
  //       return false
  //     }
  //     return true
  //   }
  // }
}

class DraggableTextNode extends RectNode {}

export default {
  type: "custom-rect",
  view: DraggableTextNode,
  model: DraggableTextNodeModel,
};