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