janvas实现xmind可编辑思维导图效果代码

代码语言:html

所属分类:图表

代码描述:janvas实现xmind可编辑思维导图效果代码影效果代码图饼状图图表效果代码

代码标签: janvas xmind 编辑 思维 导图

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">

  
  
  
<style>
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
</style>



</head>

<body >
  <div id="app" style="width: 100%;height: 100%;"></div>



      <script type="module">
/**
 * XMind software
 * Created by jarenchow based on janvas
 * https://github.com/jarenchow/jmind
 * https://github.com/jarenchow/janvas
 * https://github.com/jarenchow/janvasexamples
 */
import janvas from "https://cdn.skypack.dev/janvas@2.7.4";

var xmind = new janvas.Canvas({
  container: "#app",
  props: {
    data: { // TODO: node 添加 inverse 属性,使得可以向左布局
      value: "Central Topic",
      children: [
        {
          value: "Main Topic 1",
          children: [
            {value: "Subtopic 1", children: []},
            {value: "Subtopic 2", children: []}
          ]
        },
        {
          value: "Main Topic 2",
          children: [
            {value: "Subtopic 1", children: []}
          ]
        },
        {
          value: "Main Topic 3",
          collapse: true,
          children: [
            {value: "Subtopic 1", children: []},
            {
              value: "Subtopic 2", children: [
                {value: "Subtopic", children: []},
                {value: "Subtopic", children: []}
              ]
            },
            {value: "Subtopic 3", children: []}
          ]
        }
      ]
    },
    style: {
      backgroundColor: "#ecf4f9",
      boxBackgroundColor: "#35bffe19",
      boxBorderColor: "#28beff3d",
      centralSpacing: 50,
      spacing: 26,
      centralVerticalSpacing: 35,
      verticalSpacing: 8,
      centralTopic: {
        backgroundColor: "#35455b", color: "#ffffff", fontSize: 24,
        paddingLeft: 30, paddingTop: 22, paddingBottom: 18
      },
      mainTopic: {
        backgroundColor: "#84a1c9", color: "#ffffff", fontSize: 18,
        paddingLeft: 18, paddingTop: 14, paddingBottom: 12
      },
      subTopic: {
        backgroundColor: "#e2e9f1", color: "#35455b", fontSize: 14,
        paddingLeft: 7, paddingTop: 9, paddingBottom: 6
      },
      centralLink: {
        backgroundColor: "#ecf4f9", backgroundMousein: "#d2dbe2", color: "#35455b",
        lineWidth: 3, spacing: 13, arcToRadius: 8,
        arcRadius: 6, arcRadiusCollapse: 8, arcLineLength: 8, arcLineWidth: 1,
        font: "10px Open Sans"
      },
      mainLink: {
        lineWidth: 2
      }
    },
    point: {
      _locate: new janvas.Point(0, 0),
      _offset: new janvas.Point(0, 0),
      _before: new janvas.Point(0, 0),
      _delta: new janvas.Point(0, 0),
      _conflict: new janvas.Point(0, 0),
      locate: function (x, y) {
        this._locate.init(x, y);
      },
      set: function (x, y) {
        this._offset.init(x, y);
        this._onOffsetChanged();
      },
      add: function (x, y) {
        this._offset.translate(x, y);
        this._onOffsetChanged();
      },
      delta: function (x, y) {
        this._delta.init(x, y);
      },
      isDelta: function () {
        return this._delta.x || this._delta.y;
      },
      beforeUpdate: function () {
        this._before.copy(this._offset);
      },
      update: function (ratio) {
        this.set(this._before.x + this._delta.x * this._ease(ratio),
          this._before.y + this._delta.y * this._ease(ratio));
      },
      afterUpdate: function () {
        this.beforeUpdate();
      },
      _ease: janvas.Utils.ease.out.quad,
      eventdown: function () {
        this._conflict.init(0, 0);
        if (!this.$isRunning) this.beforeUpdate();
      },
      eventmove: function (moveX, moveY) {
        if (this.$isRunning) this._conflict.init(moveX, moveY);
        else this.set(this._before.x + moveX - this._conflict.x,
          this._before.y + moveY - this._conflict.y);
      },
      _onOffsetChanged: function () {
        this.onOffsetChanged(this._locate.x + this._offset.x,
          this._locate.y + this._offset.y);
      },
      onOffsetChanged: janvas.Utils.noop
    },
    mouse: {
      type: 0,
      none: 0,
      left: 1,
      right: 2,
      center: 4,
      back: 8,
      front: 16
    },
    format: {
      markdown: {
        prefix: "- ",
        suffix: "\n",
        indent: 2,
        separate: " ",
        regex: /\r\n(?= )/
      },
      xmind: {
        prefix: "",
        suffix: "\n",
        indent: 1,
        separate: "\t",
        regex: /\r\n(?=\t)/
      }
    },
    topic: function (depth) {
      return depth ? "Subtopic" + " " : "Main Topic" + " ";
    }
  },
  components: {
    Node: (function () {
      Node._serialId = 0;

      Node.OPERATION = {
        APPENDCHILD: "_appendOperation",
        REMOVECHILD: "_removeOperation",
        SETVALUE: "_setValueOperation",
        COLLAPSE: "_collapseOperation"
      };

      Node.setOnOperation = function (onOperation) {
        this.prototype.onOperation = onOperation;
      };

      function Node($ctx) {
        this._serialId = Node._serialId++;
        this.$ctx = $ctx;
        this.x = this.y = this.width = this.height = this.borderX = this.borderY = 0;
        this.parent = null;
        this.children = [];
        this.index = 0; // 所处 children 中的 index
        this.depth = 0; // 所处树的深度
        this.value = "";
        this.values = [];
        this.background = new janvas.RoundRect(this.$ctx, 0, 0, 0, 0, 0);
        this.border = new janvas.RoundRect(this.$ctx, 0, 0, 0, 0, 0);
        this.texts = [];
        this.isMousein = false;
        this.isSelected = false;
        this.style = new Node.Style(this);
        this.link = new Node.Link(this); // this.collapse = false;
        this.count = 0;
        this.length = 0; // 全等于 this.children.length
      }

      Node.prototype = {
        reset: function () {
          this.parent = null;
          this.children.length = 0;
          this.length = 0;
          this.index = 0;
          this.depth = 0;
          this.count = 0;
          this.isMousein = false;
          this.isSelected = false; // this.collapse = false;
        },
        apply: function () { // TODO: 整体 x, y, width, height 属性取整
          var style = this.style, x = this.x, y = this.y,
            borderX = x - style.borderOffset, borderY = y - style.borderOffset;
          this.background.initXY(x, y);
          this.border.initXY(borderX, borderY);
          this.borderX = borderX - style._borderOffset;
          this.borderY = borderY - style._borderOffset;
          for (var i = 0, length = this.values.length; i < length; i++) {
            this.texts[i].initXY(x + style.paddingLeft,
              y + style.paddingTop + i * style.lineHeight);
          }
        },
        collidesWith: function (rect) {
          return janvas.Collision.rect(this.x, this.y, this.right, this.bottom,
            rect._left, rect._top, rect._right, rect._bottom);
        },
        draw: function () {
          this.background.fill();
          if (this.isMousein || this.isSelected) this.border.stroke();
          for (var i = 0, length = this.values.length; i < length; i++) this.texts[i].fill();
        },
        appendChild: function (child) {
          this.insertChild(child, this.length);
        },
        insertChild: function (child, index) {
          this._appendOperation(child, index);
          this.onOperation(this, child, Node.OPERATION.APPENDCHILD, index,
            Node.OPERATION.REMOVECHILD, null);
        },
        _appendOperation: function (child, index) {
          child.parent = this;
          child.index = index;
          index ? index < this.length ? this.children.splice(index, 0, child) :
            this.children.push(child) : this.children.unshift(child);
          for (var i = this.length++; i > index;) this.children[i--].index++;
          this._appendDepth(child, this.depth + 1);
          this._appendCount(child, child.count + 1);
        },
        _appendDepth: function (node, depth) {
          node.depth = depth;
          node.forEachChild(function (child) {
            this._appendDepth(child, depth + 1);
          }, this);
        },
        _appendCount: function (node, count) {
          while ((node = node.parent)) node.count += count;
        },
        removeChild: function (child) {
          this._removeOperation(child);
          this.onOperation(this, child, Node.OPERATION.REMOVECHILD, null,
            Node.OPERATION.APPENDCHILD, child.index);
        },
        _removeOperation: function (child) {
          for (var i = --this.length; i > child.index;) this.children[i--].index--;
          child.index ? child.index < this.length ? this.children.splice(child.index, 1) :
            this.children.pop() : this.children.shift();
          this._appendCount(child, -(child.count + 1));
        },
        forEachChild: function (callback, context, start, end) {
          if (start === void (0)) start = 0;
          if (end === void (0)) end = this.length;
          var step = end > start ? 1 : -1;
          while (start !== end) {
            callback.call(context, this.children[start]);
            start += step;
          }
        },
        getValue: function () {
          return this.value;
        },
        setValue: function (value) {
          this._setValueOperation(value);
        },
        _setValueOperation: function (value) {
          this.value = value;
          this._apply();
        },
        _apply: function () {
          var value = this.value, values = this.values, length, texts = this.texts,
            style = this.style, width = 0, maxWidth = 0, cursor = 0, i, c, w;
          values.length = 0;
          for (i = 0, length = value.length; i < length; i++) {
            c = value[i];
            if (c === "\n") {
              values.push(value.substring(cursor, i));
              cursor = i + 1;
              if (width > maxWidth) maxWidth.........完整代码请登录后点击上方下载按钮下载查看

网友评论0