自定义锚点

2024-10-24 09:14:14 阅读:3 编辑

https://codesandbox.io/embed/logicflow026-edgeanimation-forked-fdg3v0?fontsize=14&hidenavigation=1&theme=dark

import { HtmlNode, HtmlNodeModel } from "@logicflow/core";
import "./style.css";

class HtmlCard extends HtmlNode {
  // 重写HtmlNode的setHtml,来控制html节点内容。
  setHtml(rootEl) {
    const cardEl = this.getCardEl();
    rootEl.innerHtml = "";
    rootEl.appendChild(cardEl);
  }
  getCardEl() {
    const { properties } = this.props.model;
    const el = document.createElement("div");
    el.className = "html-card";

    const header = document.createElement("div");
    header.className = "html-card-header";
    header.innerText = properties.title;

    const body = document.createElement("div");
    body.className = "html-card-body";
    body.innerText = properties.content;

    const footer = document.createElement("div");
    footer.className = "html-card-footer";

    if (properties.answers) {
      properties.answers.forEach((answer) => {
        const label = document.createElement("div");
        label.innerText = answer.text;
        label.className = "html-card-label";
        footer.appendChild(label);
      });
    }

    el.appendChild(header);
    el.appendChild(body);
    el.appendChild(footer);

    return el;
  }
}
class HtmlCardModel extends HtmlNodeModel {
  initNodeData(data) {
    super.initNodeData(data);
    // 禁止节点文本可以编辑
    this.text.editable = false;
    this.width = 240;
    // 定义连接规则,只允许出口节点连接入口节点
    const rule = {
      message: "只允许出口节点连接入口节点",
      validate: (sourceNode, targetNode, sourceAnchor, targetAnchor) => {
        return (
          sourceAnchor.type === "sourceAnchor" &&
          targetAnchor.type === "targetAnchor"
        );
      }
    };
    this.sourceRules.push(rule);
  }
  setAttributes() {
    const {
      properties: { content }
    } = this;
    // 动态计算节点的高度
    const rowSize = Math.ceil(content.length / 20);
    this.height = 60 + rowSize * 18;
  }
  /**
   * 计算每个锚点的位置
   */
  getDefaultAnchor() {
    const { height, x, y, id, properties } = this;
    const anchorPositon = [];
    anchorPositon.push({
      x,
      y: y - height / 2,
      type: "targetAnchor",
      id: `${id}_targetAnchor`
    });
    if (properties.answers) {
      let preOffset = 5;
      properties.answers.forEach((answer) => {
        const text = answer.text;
        // 计算每个锚点的位置,锚点的位置一般相对节点中心点进行偏移
        const offsetX =
          preOffset + (this.getBytesLength(text) * 6 + 4) / 2 - this.width / 2;
        preOffset += this.getBytesLength(text) * 6 + 4 + 10;
        const offsetY = height / 2;
        anchorPositon.push({
          x: x + offsetX,
          y: y + offsetY,
          type: "sourceAnchor",
          id: answer.id
        });
      });
    }
    return anchorPositon;
  }
  getBytesLength(word) {
    if (!word) {
      return 0;
    }
    let totalLength = 0;
    for (let i = 0; i < word.length; i++) {
      const c = word.charCodeAt(i);
      if (word.match(/[A-Z]/)) {
        totalLength += 1.5;
      } else if ((c >= 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) {
        totalLength += 1.2;
      } else {
        totalLength += 2;
      }
    }
    return totalLength;
  }
}

export default {
  type: "html-card",
  view: HtmlCard,
  model: HtmlCardModel
};