janvas实现xmind可编辑思维导图效果代码
代码语言:html
所属分类:图表
代码描述: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