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 = width;
              width = 0;
            } else {
              w = janvas.Utils.measureTextWidth(c, style.font);
              if ((width += w) > style.maxWidth) {
                values.push(value.substring(cursor, i));
                cursor = i;
                maxWidth = style.maxWidth;
                width = w;
              }
            }
          }
          values.push(value.substring(cursor));
          length = values.length;
          while (texts.length < length) {
            var text = new janvas.Text(this.$ctx, 0, 0);
            text.getStyle().setFillStyle(style.color)
              .setFont(style.font).setTextBaseline("top");
            texts.push(text);
          }
          this.background
            .setWidth(this.width = style.paddingLeft + style.paddingRight +
              (width > maxWidth ? width : maxWidth))
            .setHeight(this.height = style.paddingTop + style.paddingBottom +
              style.fontSize + (length - 1) * style.lineHeight);
          this.border
            .setWidth(this.width + style.borderOffset * 2)
            .setHeight(this.height + style.borderOffset * 2);
          for (i = 0; i < length; i++) {
            texts[i].setText(values[i]);
          }
          this.halfWidth = this.width / 2;
          this.halfHeight = this.height / 2;
          this.layoutX += 0;
          this.layoutY += 0;
        },
        eventmove: function (x, y) {
          return this.isMousein = this.background.isPointInPath(x, y);
        },
        select: function () {
          this.isSelected = true;
          this.border.getStyle().setStrokeStyle(this.style.borderColor);
        },
        unselect: function () {
          this.isSelected = this.isMousein = false;
          this.border.getStyle().setStrokeStyle(this.style.borderAlpha);
        },
        hide: function () {
          this.draw = janvas.Utils.noop;
        },
        show: function () {
          this.draw = Node.prototype.draw;
        },
        onValueOperation: function (_value) {
          this.onOperation(this, null, Node.OPERATION.SETVALUE, this.value,
            Node.OPERATION.SETVALUE, _value);
        },
        beforeOffset: function () {
          this._x = this.x;
          this._y = this.y;
        },
        offset: function (offsetX, offsetY) {
          this.layoutX = this._x + offsetX;
          this.layoutY = this._y + offsetY;
        },
        get layoutX() {
          return this.x;
        },
        set layoutX(x) {
          this.x = x;
          this.right = x + this.width;
          this.cx = x + this.halfWidth;
        },
        get layoutY() {
          return this.y;
        },
        set layoutY(y) {
          this.y = y;
          this.bottom = y + this.height;
          this.cy = y + this.halfHeight;
        },
        get collapse() {
          return this._collapse;
        },
        set collapse(collapse) {
          var _collapse = this._collapse;
          this._collapseOperation(collapse); // 须不等判断,否则会造成回收机制 collapse 赋同值
          if (_collapse !== void (0) && _collapse !== collapse) this.onOperation(this, null,
            Node.OPERATION.COLLAPSE, collapse, Node.OPERATION.COLLAPSE, _collapse);
        },
        _collapseOperation: function (collapse) {
          this.link._collapse(this._collapse = collapse);
        },
        get count() {
          return this._count;
        },
        set count(count) {
          this.link._count(this._count = count);
        },
        get length() {
          return this._length;
        },
        set length(length) {
          this.link._length(this._length = length);
        },
        get first() {
          return this.children[0];
        },
        get last() {
          return this.children[this.length - 1];
        },
        get previous() {
          return this.parent.children[this.index - 1];
        },
        get next() {
          return this.parent.children[this.index + 1];
        },
        onOperation: janvas.Utils.noop
      };

      Node.Style = function (target) {
        this.target = target;
      }

      Node.Style.prototype = {
        apply: function (style) {
          this.backgroundColor = style.backgroundColor || "#e2e9f1";
          this.color = style.color || "#35455b";
          this.fontSize = style.fontSize || 14;
          this.fontFamily = "Open Sans";
          this.font = this.fontSize + "px " + this.fontFamily;
          this.lineHeight = Math.floor(this.fontSize * 4 / 3);
          this.maxWidth = 280;
          this.paddingLeft = style.paddingLeft || this.fontSize * 0.625;
          this.paddingRight = style.paddingRight || this.paddingLeft;
          this.paddingTop = style.paddingTop || this.fontSize * 0.5;
          this.paddingBottom = style.paddingBottom || this.paddingTop;
          this.borderRadius = this.fontSize * 0.3;
          this.borderPadding = 2;
          this.borderWidth = 2;
          this._borderOffset = this.borderWidth / 2;
          this.borderOffset = this.borderPadding + this._borderOffset;
          this.borderColor = "#2ebdff";
          this.borderAlpha = this.borderColor + "80";
          this._apply();
        },
        _apply: function () {
          var target = this.target, background = target.background,
            border = target.border, texts = target.texts;
          background.setRadius(this.borderRadius).getStyle()
            .setFillStyle(this.backgroundColor).setLineWidth(this.borderWidth);
          border.setRadius(this.borderRadius).getStyle()
            .setStrokeStyle(target.isSelected ? this.borderColor : this.borderAlpha)
            .setLineWidth(this.borderWidth);
          for (var i = 0, length = texts.length; i < length; i++) {
            texts[i].getStyle().setFillStyle(this.color).setFont(this.font);
          }
          target._apply();
        }
      };

      Node.Link = function (target) {
        this.target = target;
        this._link = new _Link(target.$ctx, 0, 0, target.children, 0, 0);
        this.arc = new janvas.Arc(target.$ctx, 0, 0, 0);
        this.text = new janvas.Text(target.$ctx, 0, 0, "");
        this.line = new janvas.Line(target.$ctx, 0, 0, 0, 0);
        this.style = new Node.Link.Style(this);
        this.isMousein = false;
      }

      Node.Link.prototype = {
        apply: function () {
          var target = this.target, style = this.style, arc = this.arc;
          this._link.initXY(target.right, target.cy);
          arc.initXY(target.right + style.spacing, target.cy);
          this.text.initXY(arc.getStartX(), target.cy);
          this.line.initXY(arc.getStartX() - style.arcLineLength / 2, target.cy)
            .setEndX(arc.getStartX() + style.arcLineLength / 2).setEndY(target.cy);
          if (target.length) {
            this._left = target.right;
            if (target.collapse) {
              this._top = target.cy - arc.getRadius();
              this._right = arc.getStartX() + arc.getRadius();
              this._bottom = target.cy + arc.getRadius();
            } else {
              this._top = target.first.y;
              this._right = target.first.x;
              this._bottom = target.last.bottom;
            }
            this.collidesWith = this._collidesWith;
          } else {
            this.collidesWith = this._noCollision;
          }
        },
        draw: function () {
          this._link.stroke();
          if (this.target.collapse) {
            this.arc.fillStroke();
            this.text.fill();
          } else if (this.target.isMousein || this.isMousein) {
            this.arc.fillStroke();
            this.line.stroke();
          }
        },
        eventdown: function () {
          this.target.collapse = !this.target.collapse;
        },
        eventmove: function (x, y) {
          if (this.target.length === 0) return false;
          if (this.isMousein !== (this.target.collapse ? this.arc.isPointInPath(x, y) :
            x >= this._left && x <= this._right && y >= this.target.y && y <= this.target.bottom)) {
            this.arc.getStyle().setFillStyle((this.isMousein = !this.isMousein) ?
              this.style.backgroundMousein : this.style.backgroundColor);
          }
          return this.isMousein;
        },
        _collidesWith: function (rect) {
          return janvas.Collision.rect(this._left, this._top, this._right, this._bottom,
            rect._left, rect._top, rect._right, rect._bottom);
        },
        _noCollision: function () {
          return false;
        },
        _count: function (count) {
          this.text.setText(count > 99 ? "..." : count + "");
        },
        _collapse: function (collapse) {
          this._link._collapse = collapse;
          this.arc.setRadius(collapse ?
            this.style.arcRadiusCollapse : this.style.arcRadius);
        },
        _length: function (length) {
          this._link._length = length;
        }
      };

      Node.Link.Style = function (target) {
        this.target = target;
      }

      Node.Link.Style.prototype = {
        apply: function (style) {
          this.backgroundColor = style.backgroundColor || "#ecf4f9";
          this.backgroundMousein = style.backgroundMousein || "#d2dbe2";
          this.color = style.color || "#35455b";
          this.lineWidth = style.lineWidth || 2;
          this.spacing = style.spacing || 13;
          this.arcToRadius = style.arcToRadius || 8;
          this.arcRadius = style.arcRadius || 6;
          this.arcRadiusCollapse = style.arcRadiusCollapse || 8;
          this.arcLineLength = style.arcLineLength || this.arcRadius * 4 / 3;
          this.arcLineWidth = style.arcLineWidth || 1;
          this.font = style.font || "10px Open Sans";
          this._apply();
        },
        _apply: function () {
          var target = this.target, _link = target._link;
          _link.setSpacing(this.spacing);
          _link.setArcToRadius(this.arcToRadius);
          _link.getStyle().setStrokeStyle(this.color).setLineWidth(this.lineWidth);
          target.arc.setRadius(_link._collapse ? this.arcRadiusCollapse : this.arcRadius)
            .getStyle().setLineWidth(this.arcLineWidth).setStrokeStyle(this.color)
            .setFillStyle(target.isMousein ? this.backgroundMousein : this.backgroundColor);
          target.text.getStyle().setFont(this.font).setFillStyle(this.color)
            .setTextAlign("center").setTextBaseline("middle");
          target.line.getStyle().setLineWidth(this.arcLineWidth)
            .setStrokeStyle(this.color);
        }
      };

      function _Link(ctx, sx, sy, children, cx, cy) {
        janvas.Shape.call(this, ctx, sx, sy, cx, cy);
        this.children = children;
      }

      janvas.Utils.inheritPrototype(_Link, janvas.Shape);

      Object.defineProperties(_Link.prototype, {
        process: {
          value: function () {
            var ctx = this.ctx, tx = this._sx + this.spacing, ty = this._sy,
              children = this.children, i, child, ex, ey;
            ctx.beginPath();
            ctx.moveTo(this._sx, ty);
            ctx.lineTo(tx, ty);
            if (this._collapse) return;
            for (i = 0; i < this._length; i++) {
              child = children[i];
              ex = child.x - this.cx;
              ey = child.cy - this.cy;
              if (Math.abs(ey - ty) < this.arcToRadius) {
                ctx.moveTo(tx, ey);
                ctx.lineTo(ex, ey);
              } else {
                ctx.moveTo(tx, ty); // 可以 if (i),因为第一次已经 lineTo(tx, ty) 了
                ctx.arcTo(tx, ey, ex, ey, this.arcToRadius);
                ctx.lineTo(ex, ey); // 因为 (ex - tx) > this.arcToRadius === true
              }
            }
          }
        },
        setSpacing: {
          value: function (spacing) {
            this.spacing = spacing;
          }
        },
        setArcToRadius: {
          value: function (arcToRadius) {
            this.arcToRadius = arcToRadius;
          }
        }
      });

      return Node;
    }()),
    Selector: (function () {
      function Selector() {
        this.selected = [];
        this._selected = [];
        this._shift = [];
        this.ctrl = null;
      }

      Selector.prototype = {
        select: function (node, ctrlKey, shiftKey) {
          if (node) {
            if (node.isSelected) { // node 已选中的情况
              if (ctrlKey) { // ctrl+选中node->取消选中
                this._unselect(node);
              } else if (shiftKey) { // shift+选中node->范围选中
                this._selectRange(this.ctrl, node);
              } else { // 选中node->仅选中
                this._clear(node);
              }
            } else { // node 未选中的情况
              if (ctrlKey) { // ctrl+未选node->增添选中
                this._select(node);
              } else {
                if (shiftKey) { // shift+未选node
                  if (this.ctrl) { // +已有ctrl->范围选中
                    this._selectRange(this.ctrl, node);
                  } else { // 没有ctrl->仅选中
                    this._select(node);
                  }
                } else { // 选中node->仅选中
                  this._clear(node);
                }
              }
            }
          } else if (!ctrlKey && !shiftKey) {
            this._clear(); // 点击屏幕->清除选中
          }
        },
        isMultiple: function () {
          return this.selected.length > 1;
        },
        sideBySide: function () {
          for (var i = this.selected.length; i > 0;) {
            if (this.selected[--i].parent !== this.ctrl.parent) return false;
          }
          return true;
        },
        forEachSelected: function (callback, context) {
          for (var i = 0, length = this.selected.length;
               i < length; i++) this._selected[i] = this.selected[i];
          for (i = 0; i < length; i++) callback.call(context, this._selected[i]);
        },
        onCtrlSelected: janvas.Utils.noop,
        onNodeSelected: janvas.Utils.noop,
        onClear: janvas.Utils.noop,
        _select: function (node) {
          node.select();
          this.selected.push(node);
          if (this.ctrl === null) this.onCtrlSelected(this.ctrl = node);
          else this.onNodeSelected(node);
        },
        _unselect: function (node) {
          node.unselect();
          this.selected.splice(this.selected.indexOf(node), 1);
        },
        _clear: function (except) {
          while (this.selected.length) this.selected.pop().unselect();
          this._shift.length = 0;
          this.ctrl = null;
          if (except) this._select(except);
          else this.onClear();
        },
        _selectRange: function (ctrl, node) {
          if (node.depth === ctrl.depth && node !== ctrl) {
            while (this._shift.length) {
              var pop = this._shift.pop();
              if (pop.isSelected) this._unselect(pop);
            }
            ctrl.parent.forEachChild(function (child) {
              if (!child.isSelected) this._select(child);
              this._shift.push(child);
            }, this, node.index, ctrl.index);
            if (!ctrl.isSelected) this._select(ctrl);
          }
        },
        get last() {
          return this.selected[this.selected.length - 1];
        },
        get length() {
          return this.selected.length;
        }
      };

      return Selector;
    }()),
    Hacker: (function () {
      Hacker.unit = "px";

      function Hacker() {
        this._init();
        this._initStyles();
        this._initCallbacks();
      }

      Hacker.prototype = {
        _init: function () {
          this.border = document.createElement("div");
          this.border.appendChild(this.textarea = document.createElement("textarea"));
          this.deactivate();
        },
        _initStyles: function () {
          var border = this.border.style, textarea = this.textarea.style;
          border.position = "absolute"; // border.display = "block";
          border.borderStyle = "solid";
          border.margin = "0";
          textarea.display = "block";
          textarea.overflow = "hidden";
          textarea.outline = textarea.border = textarea.resize = "none";
          textarea.wordWrap = textarea.whiteSpace = "break-spaces";
          textarea.wordBreak = "break-all";
          textarea.boxSizing = "border-box";
          textarea.margin = "0";
          textarea.tabSize = "1";
        },
        _initCallbacks: function () {
          var border = this.border;
          border.onmousedown = border.onmousemove = border.onmouseup =
            border.ontouchstart = border.ontouchmove = border.ontouchend =
              border.onmouseout = border.ontouchcancel = border.ondblclick = function (ev) {
                ev.stopPropagation();
              };
          border.oncontextmenu = function (ev) {
            ev.stopPropagation();
            ev.preventDefault(); // TODO: 使用 oncontextmenu(x, y) 回调出去,调用 Menu 菜单
          };
          border.onkeydown = function (ev) {
            var key = ev.key;
            if (this.isActivated()) {
              ev.stopPropagation();
              switch (key) {
                case "s":
                case "o":
                  if (ev.ctrlKey) ev.preventDefault();
                  break;
                case "Tab":
                  ev.preventDefault();
                  break;
                case "Escape":
                  this._bind.setValue(this._value);
                  this.deactivate();
                  break;
                case "Enter":
                  if (ev.ctrlKey) {
                    var value = this.getValue(), start = this.selectionStart,
                      end = this.selectionEnd;
                    this.setValue(value.substr(0, start) + "\n" + value.substr(end));
                    this.selectionEnd = start + 1;
                    this._oninput();
                  } else if (!ev.shiftKey) {
                    ev.preventDefault();
                    this.deactivate();
                  }
                  break;
              }
            } else if (!ev.ctrlKey && key.length === 1 || ev.isComposing || key === "Process") {
              if (key === " ") ev.preventDefault();
              ev.stopPropagation();
              this.activate();
            }
          }.bind(this);
          border.oninput = this._oninput.bind(this);
        },
        appendTo: function (wrapper) {
          wrapper.appendChild(this.border);
        },
        bind: function (node) {
          if (this.isActivated()) this.deactivate();
          this._bind = node;
          this.textarea.focus();
        },
        activate: function () {
          this.beforeActivate(this._bind);
          this._isActivated = true;
          this.border.style.opacity = "1";
          this.border.style.pointerEvents = "auto";
          this._bindParams();
          this._bindStyles();
          this._bind.hide();
          this.callDraw();
        },
        deactivate: function () {
          this._isActivated = false;
          this.border.style.opacity = "0";
          this.border.style.pointerEvents = "none";
          if (this._bind) {
            this._bind.show();
            if (this._bind.getValue() === this._value) this.callDraw();
            else this._bind.onValueOperation(this._value);
          }
        },
        isActivated: function () {
          return this._isActivated;
        },
        _bindParams: function () {
          this.follow();
          this.setWidth(this._bind.width);
          this.setHeight(this._bind.height);
          this.setValue(this._value = this._bind.getValue());
          this.textarea.select();
        },
        _bindStyles: function () {
          var border = this.border.style, textarea = this.textarea.style, bind = this._bind.style;
          border.borderRadius = bind.borderRadius + bind._borderOffset + Hacker.unit;
          border.padding = bind.borderPadding + Hacker.unit;
          border.borderWidth = bind.borderWidth + Hacker.unit;
          border.borderColor = bind.borderColor;
          textarea.backgroundColor = bind.backgroundColor;
          textarea.color = bind.color;
          textarea.font = bind.font; // textarea.fontFamily = bind.fontFamily; textarea.fontSize = bind.fontSize + Hacker.unit;
          textarea.lineHeight = bind.lineHeight + Hacker.unit;
          textarea.pad.........完整代码请登录后点击上方下载按钮下载查看

网友评论0