chartx
Version:
Data Visualization Chart Library
1,187 lines (1,141 loc) • 44.8 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _canvax = _interopRequireDefault(require("canvax"));
var _base = _interopRequireDefault(require("./base"));
var _tools = require("../../../utils/tools");
var _trigger2 = _interopRequireDefault(require("../../trigger"));
var _tree2 = _interopRequireDefault(require("../../../layout/tree/tree"));
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
var _ = _canvax.default._,
event = _canvax.default.event;
var Circle = _canvax.default.Shapes.Circle;
var Rect = _canvax.default.Shapes.Rect;
//内部交互需要同步回源数据的属性, 树状图要实现文本的编辑,所以content也要加入进来
var syncToOriginKeys = ['collapsed', 'style', 'content'];
var iconWidth = 20;
/**
* 关系图中 包括了 配置,数据,和布局数据,
* 默认用配置和数据可以完成绘图, 但是如果有布局数据,就绘图玩额外调用一次绘图,把布局数据传入修正布局效果
*/
var compactTree = /*#__PURE__*/function (_GraphsBase) {
function compactTree(opt, app, preComp) {
var _this;
(0, _classCallCheck2.default)(this, compactTree);
_this = _callSuper(this, compactTree, [opt, app, preComp]);
_this.type = "compacttree";
_.extend(true, _this, (0, _tools.getDefaultProps)(compactTree.defaultProps()), opt);
return _this;
}
(0, _inherits2.default)(compactTree, _GraphsBase);
return (0, _createClass2.default)(compactTree, [{
key: "draw",
value: function draw(opt) {
var _this2 = this;
!opt && (opt = {});
_.extend(true, this, opt);
this.initData(opt.data).then(function (data) {
_this2.data = data;
_this2.layoutData();
_this2.widget();
_this2.induce.context.width = _this2.width;
_this2.induce.context.height = _this2.height;
_this2.sprite.context.x = parseInt(_this2.origin.x);
_this2.sprite.context.y = parseInt(_this2.origin.y);
//test bound
// this._bound = new Rect({
// context: {
// x: this.data.extents.left,
// y: this.data.extents.top,
// width: this.data.size.width,
// height: this.data.size.height,
// lineWidth:1,
// strokeStyle: 'red'
// }
// });
// this.graphsSp.addChild( this._bound )
if (!_this2.preGraphsSpPosition) {
_this2.graphsSpPosition = {
x: Math.max((_this2.width - _this2.data.size.width) / 2, _this2.app.padding.left),
y: _this2.height / 2
};
} else {
_this2.graphsSpPosition = {
x: _this2.preGraphsSpPosition.x,
y: _this2.preGraphsSpPosition.y
};
}
_this2.graphsSp.context.x = _this2.graphsSpPosition.x;
_this2.graphsSp.context.y = _this2.graphsSpPosition.y;
_this2.fire("complete");
});
}
//如果dataTrigger.origin 有传入, 则已经这个origin为参考点做重新布局
//TODO, 如果这个图的options中有配置 一个 符合 关系图的数据{nodes, edges, size}
//那么这个时候的resetData还不能满足,因为resetData的第一个个参数是dataFrame, 而options.data其实已经算是配置了,
//后面遇到这个情况再调整吧
}, {
key: "resetData",
value: function resetData(dataFrame, dataTrigger) {
var _this3 = this;
this._resetData(dataFrame, dataTrigger).then(function () {
_this3.fire("complete");
//test bound
// Object.assign( this._bound.context, {
// x: this.data.extents.left,
// y: this.data.extents.top,
// width: this.data.size.width,
// height: this.data.size.height
// } );
});
}
}, {
key: "widget",
value: function widget() {
this._drawEdges();
this._drawNodes();
}
//$data如果用户设置了符合data的数据格式数据{nodes, edges, size, extents},那就直接返回
}, {
key: "initData",
value: function initData($data, $dataTrigger) {
var _this4 = this;
return new Promise(function (resolve) {
if ($data && $data.nodes && $data.edges) {
resolve($data);
return;
}
;
var data = {
// relation 也好, tree也好, 最后都要转换成 nodes edges 渲染统一依赖 nodes 和 edges
//{ type,key,content,ctype,width,height,x,y }
nodes: [],
//{ type,key[],content,ctype,width,height,x,y }
edges: [],
size: {
width: 0,
height: 0
},
treeOriginData: null,
//原始全量的treeData
treeData: null,
//折叠过滤掉后的需要渲染的treeData
nodesLength: 0
};
var originData = _this4.app._data;
data.treeOriginData = originData;
//TODO 这里可以 判断 $dataTrigger 如果是来自图表内部的 collapse 等,
//就可以不用走下面的 arrayToTreeJsonForRelation , 后续优化
//项目里一般都建议直接使用treeData的格式,但是这里要做一次判断是因为chartpark上面做的demo只能下面的格式
/**
* [ {id:1,label:''},{id:2,label:''},{id:'1,2',label:''} ]
*/
//要把这个格式转成 {id:1,children: [{id:2}]} 这样的格式
//注意,这里不能用dataFrame去做判断,判断不出来的,只能用原始的 originData
if (Array.isArray(originData)) {
data.treeOriginData = _this4.arrayToTreeJsonForRelation(_this4.app.dataFrame.jsonOrg, _this4);
}
var t = new Date().getTime();
//然后从treeOriginData 过滤掉 需要显示的子树 到 treeData
//{treeData, nodeLength}这里设置了这两个属性
Object.assign(data, _this4._filterTreeData(data.treeOriginData));
var t1 = new Date().getTime();
_this4._initAllDataSize(data).then(function () {
//这个时候已经设置好了 treeData 的 size 属性width、height
//可以开始布局了,布局完就可以设置好 data 的 nodes edges 和 size 属性
resolve(data);
});
});
}
//treeOriginData 一定是一个 树结构的
}, {
key: "_filterTreeData",
value: function _filterTreeData(treeOriginData) {
var _this5 = this,
_this$data;
var nodesLength = 1;
var collapsedField = this.node.collapse.field;
var childrenField = this.childrenField;
var nodes = [];
var edges = [];
// let treeData = {};
// Object.assign( treeData, treeOriginData );
// let childrenField = this.childrenField;
// let children = treeOriginData[ childrenField ];
// treeData[ childrenField ] = [];
//parent指向的是treeData不是originData,这里要注意下
var _filter = function filter(treeOriginData, parent, depth, rowInd, treeData) {
if (treeOriginData) {
var _treeData$style;
Object.assign(treeData, {
depth: depth || 0,
parent: parent,
rowInd: rowInd //在parent中的Index
});
//resetData的时候,有些节点原本有数据的
var preChildrenList = treeData[childrenField] || [];
Object.assign(treeData, treeOriginData);
treeData['__originData'] = treeOriginData; //和原数据建立下关系,比如 treeData 中的一些数据便跟了要同步到原数据中去
treeData[childrenField] = [];
if ((treeData === null || treeData === void 0 ? void 0 : (_treeData$style = treeData.style) === null || _treeData$style === void 0 ? void 0 : _treeData$style.visible) == 'hidden') {
return;
}
//开始构建nodes
var content = _this5._getContent(treeData);
//下面这个判断逻辑主要用在resetData的时候用
if (treeData._node && content != treeData._node.content) {
treeData._node = null;
delete treeData._node;
if (!treeData.style) {
treeData.style = {
width: 0,
height: 0
};
}
if (!treeOriginData.style || treeOriginData.style && (!treeOriginData.style.width || !treeOriginData.style.height)) {
treeData.style.width = 0;
treeData.style.height = 0;
}
}
;
var node = _this5.getDefNode({
type: 'tree'
});
Object.assign(node, {
iNode: nodes.length,
rowData: treeData,
key: treeData[_this5.field],
content: content,
ctype: _this5._checkHtml(content) ? 'html' : 'canvas',
width: 0,
height: 0,
depth: depth || 0 //深度
});
//不能放到assign中去, getProp的处理中可能依赖node.rowData
node.shapeType = _this5.getProp(_this5.node.shapeType, node);
node.preIconCharCode = _this5.getProp(_this5.node.preIcon.charCode, node);
node.icons = _this5.getProp(_this5.node.icons, node) || [];
if (!Array.isArray(node.icons)) {
node.icons = [node.icons];
}
;
node.icons.forEach(function (icon) {
var _icon = Object.assign({}, _this5.node.iconsDefault, icon);
_icon.charCode = _this5.getProp(icon.charCode, node);
Object.assign(icon, _icon);
});
nodes.push(node);
treeData._node = node;
if (!treeData[collapsedField]) {
//如果这个节点未折叠
//检查他的子节点
(treeOriginData[childrenField] || []).forEach(function (child, rowInd) {
var preChildTreeData = preChildrenList.find(function (item) {
return item[_this5.field] == child[_this5.field];
}) || {};
var childTreeData = _filter(child, treeData, depth + 1, rowInd, preChildTreeData);
if (childTreeData) {
treeData[childrenField].push(childTreeData);
nodesLength++;
//开始构建edges
var rowData = {};
var _content = ''; //this._getContent(rowData);
var edge = _this5.getDefNode({
type: 'tree'
});
Object.assign(edge, {
isTree: true,
iNode: edges.length,
rowData: rowData,
key: [treeData[_this5.field], childTreeData[_this5.field]],
//treeData[ this.field ]+","+child[ this.field ],
content: _content,
ctype: _this5._checkHtml(_content) ? 'html' : 'canvas',
//如果是edge,要有source 和 target
source: treeData._node,
target: childTreeData._node,
sourceTreeData: treeData,
targetTreeData: childTreeData
});
edge.shapeType = _this5.getProp(_this5.line.shapeType, edge);
edges.push(edge);
}
});
}
}
return treeData;
};
var preTreeData = ((_this$data = this.data) === null || _this$data === void 0 ? void 0 : _this$data.treeData) || {};
var treeData = _filter(treeOriginData, null, 0, 0, preTreeData);
return {
treeData: treeData,
nodesLength: nodesLength,
nodes: nodes,
edges: edges
};
}
//所有对nodeData原始数据的改变都需要同步到原数据, 比如 collapsed 折叠状态, 还有动态计算出来的width 和 height
}, {
key: "_syncToOrigin",
value: function _syncToOrigin(treeData) {
for (var k in treeData) {
if (syncToOriginKeys.indexOf(k) > -1) {
treeData.__originData[k] = treeData[k];
}
}
}
}, {
key: "_eachTreeDataHandle",
value: function _eachTreeDataHandle(treeData, handle) {
var _this6 = this;
handle && handle(treeData);
(treeData[this.childrenField] || []).forEach(function (nodeData) {
_this6._eachTreeDataHandle(nodeData, handle);
});
}
}, {
key: "_initAllDataSize",
value: function _initAllDataSize(data) {
var _this7 = this;
var treeData = data.treeData,
nodesLength = data.nodesLength;
var initNum = 0;
return new Promise(function (resolve) {
_this7._eachTreeDataHandle(treeData, function (treeDataItem) {
//计算和设置node的尺寸
_this7._setSize(treeDataItem).then(function () {
_this7._setNodeBoundingClientWidth(treeDataItem);
// 重新校验一下size, 比如菱形的 外界矩形是不一样的
_this7.checkNodeSizeForShapeType(treeDataItem._node);
initNum++;
if (initNum == nodesLength) {
//全部处理完毕了
resolve(data);
}
});
});
});
}
}, {
key: "_setNodeBoundingClientWidth",
value: function _setNodeBoundingClientWidth(treeData) {
var node = treeData._node;
var boundingClientWidth = node.width || 0;
if (node.shapeType != 'diamond' && node.depth) {
if (treeData.__originData[this.childrenField] && treeData.__originData[this.childrenField].length) {
boundingClientWidth += iconWidth;
}
;
}
if (node.preIconCharCode) {
boundingClientWidth += iconWidth;
}
;
if (node.icons && node.icons.length) {
boundingClientWidth += iconWidth * node.icons.length;
}
;
node.boundingClientWidth = boundingClientWidth;
}
}, {
key: "_setSize",
value: function _setSize(treeData) {
var _this8 = this;
return new Promise(function (resolve) {
var node = treeData._node;
//这里的width都是指内容的size
var width = treeData.width || treeData.style && treeData.style.width || _this8.getProp(_this8.node.width, treeData);
var height = treeData.height || treeData.style && treeData.style.height || _this8.getProp(_this8.node.height, treeData);
if (width && height) {
//如果node上面已经有了 尺寸
//(treeData中自己带了尺寸数据,或者node.width node.height设置了固定的尺寸配置)
// 这个时候 contentElement 可能就是空(可以有可视范围内渲染优化,布局阶段不需要初始化contentElement),
var sizeOpt = {
width: width,
height: height,
contentElement: node.contentElement
};
// opt -> contentElement,width,height
_.extend(node, sizeOpt);
resolve(sizeOpt);
return;
}
;
//如果配置中没有设置size并且treedata中没有记录size,那么就只能初始化了cotnent来动态计算
_this8._initcontentElementAndSize(treeData).then(function (sizeOpt) {
_.extend(node, sizeOpt);
resolve(sizeOpt);
});
});
}
//通过 初始化 contnt 来动态计算 size 的走这里
}, {
key: "_initcontentElementAndSize",
value: function _initcontentElementAndSize(treeData) {
var _this9 = this;
return new Promise(function (resolve) {
var node = treeData._node;
//那么,走到这里, 就说明需要动态的计算size尺寸,动态计算, 是一定要有contentElement的
var contentType = node.ctype;
if (_this9._isField(contentType)) {
contentType = node.rowData[contentType];
}
;
!contentType && (contentType = 'canvas');
var _initEle;
if (contentType == 'canvas') {
_initEle = _this9._getEleAndsetCanvasSize;
}
;
if (contentType == 'html') {
_initEle = _this9._getEleAndsetHtmlSize;
}
;
_initEle.apply(_this9, [node]).then(function (sizeOpt) {
// sizeOpt -> contentElement,width,height
_.extend(node, sizeOpt);
//动态计算的尺寸,要写入到treeData中去,然后同步到 treeData的 originData,
//这样就可以 和 整个originData一起存入数据库,后续可以加快再次打开的渲染速度
if (!treeData.style) {
treeData.style = {};
}
;
treeData.style.width = node.width;
treeData.style.height = node.height;
_this9._syncToOrigin(treeData);
resolve(sizeOpt);
});
});
}
}, {
key: "layoutData",
value: function layoutData() {
if (_.isFunction(this.layout)) {
//layout需要设置好data中nodes的xy, 以及edges的points,和 size的width,height
this.layout(this.data);
} else {
this.treeLayout(this.data); //tree中自己实现layout
}
}
}, {
key: "treeLayout",
value: function treeLayout(data) {
var _this10 = this;
var childrenField = this.childrenField;
var layoutIsHorizontal = this.rankdir == 'LR' || this.rankdir == 'RL';
//layoutIsHorizontal = false;
var t1 = new Date().getTime();
var spaceX = this.nodesep; //20;
var spaceY = this.ranksep; //20;
var layout = (0, _tree2.default)({
spacing: spaceX,
nodeSize: function nodeSize(node) {
//计算的尺寸已经node的数据为准, 不取treeData的
var height = node.data._node.height || 0;
var boundingClientWidth = node.data._node.boundingClientWidth || 0;
if (layoutIsHorizontal) {
return [height, boundingClientWidth + spaceY];
}
return [boundingClientWidth, height + spaceY]; //因为节点高度包含节点下方的间距
},
children: function children(data) {
return data[childrenField];
}
});
var _tree = layout.hierarchy(data.treeData);
var _layout = layout(_tree);
var left = 0,
top = 0,
right = 0,
bottom = 0;
var maxRight = 0,
maxLeft = 0,
maxTop = 0,
maxBottom = 0;
var width = 0,
height = 0;
var nodes = [];
_layout.each(function (node) {
if (layoutIsHorizontal) {
var x = node.x;
node.x = node.y;
node.y = x;
}
;
if (node.x <= left) {
maxRight = node.x + node.data._node.boundingClientWidth;
}
;
left = Math.min(left, node.x);
if (node.x + node.data._node.boundingClientWidth >= right) {
maxLeft = node.x;
}
;
right = Math.max(right, node.x + node.data._node.boundingClientWidth);
if (node.y <= top) {
maxBottom = node.y + node.data._node.height;
}
;
top = Math.min(top, node.y);
if (node.y + node.data._node.height + spaceY >= bottom) {
maxTop = node.y;
}
bottom = Math.max(bottom, node.y + node.data._node.height + spaceY);
//node的x y 都是矩形的中心点
node.data._node.x = node.x + node.data._node.boundingClientWidth / 2;
node.data._node.y = node.y + node.data._node.height / 2;
node.data._node.depth = node.depth;
nodes.push(node.data._node);
});
width = right - left;
height = bottom - top - spaceY;
////设置edge的points
data.edges.forEach(function (edge) {
_this10.getEdgePoints(edge);
});
Object.assign(data, {
nodes: nodes,
size: {
width: width,
height: height
},
extents: {
left: left,
top: top,
right: right,
bottom: bottom
},
viewPort: {
maxRight: maxRight,
maxLeft: maxLeft,
maxTop: maxTop,
maxBottom: maxBottom
}
});
}
//可以继承覆盖
}, {
key: "getEdgePoints",
value: function getEdgePoints(edge) {
var points = [];
//firstPoint
var firstPoint = {
x: parseInt(edge.source.x + edge.source.boundingClientWidth / 2),
y: parseInt(edge.source.y)
};
if (!edge.source.depth) {
//根节点
firstPoint.x = parseInt(edge.source.x);
}
if (edge.source.shapeType == 'underLine') {
firstPoint.y = parseInt(edge.source.y + edge.source.height / 2);
}
points.push(firstPoint);
var secPoint = {
x: firstPoint.x + 10,
y: firstPoint.y
};
points.push(secPoint);
//lastPoint
var lastPoint = {
x: parseInt(edge.target.x - edge.target.boundingClientWidth / 2),
y: parseInt(edge.target.y)
};
if (edge.target.shapeType == 'underLine') {
lastPoint.y = parseInt(edge.target.y + edge.target.height / 2);
}
//LR
points.push({
x: secPoint.x + parseInt((lastPoint.x - secPoint.x) / 2),
y: lastPoint.y
});
points.push(lastPoint);
edge.points = points;
return points;
}
}, {
key: "_drawNodes",
value: function _drawNodes() {
var _this11 = this;
var me = this;
_.each(this.data.nodes, function (node) {
var key = node.rowData[_this11.field];
var drawNode = function drawNode() {
_this11._drawNode(node);
//处理一些tree 相对 relation 特有的逻辑
//collapse
if (node.depth && _this11.node.collapse.enabled) {
var iconId = key + "_collapse_icon";
var iconBackId = key + "_collapse_icon_back";
if (node.rowData[_this11.childrenField] && node.rowData.__originData[_this11.childrenField] && node.rowData.__originData[_this11.childrenField].length) {
var charCode = _this11.node.collapse.openCharCode;
if (!node.rowData.collapsed) {
charCode = _this11.node.collapse.closeCharCode;
}
;
var iconText = String.fromCharCode(parseInt(_this11.getProp(charCode, node), 16));
var fontSize = _this11.getProp(_this11.node.collapse.fontSize, node);
var fontColor = _this11.getProp(_this11.node.collapse.fontColor, node);
var fontFamily = _this11.getProp(_this11.node.collapse.fontFamily, node);
var offsetX = _this11.getProp(_this11.node.collapse.offsetX, node);
var offsetY = _this11.getProp(_this11.node.collapse.offsetY, node);
//let tipsContent= this.getProp( this.node.collapse.tipsContent , node);
var background = _this11.getProp(_this11.node.collapse.background, node);
var lineWidth = _this11.getProp(_this11.node.collapse.lineWidth, node);
var strokeStyle = _this11.getProp(_this11.node.collapse.strokeStyle, node);
var _collapseIcon = _this11.labelsSp.getChildById(iconId);
var _collapseIconBack = _this11.labelsSp.getChildById(iconBackId);
var x = parseInt(node.x + node.boundingClientWidth / 2 + offsetX - _this11.node.padding - fontSize / 4);
if (node.shapeType == 'diamond') {
x += _this11.node.padding + fontSize * 1 + 1;
}
var y = parseInt(node.y + offsetY);
//collapseIcon的 位置默认为左右方向的xy
var collapseCtx = {
x: x,
y: y + 1,
fontSize: fontSize,
fontFamily: fontFamily,
fillStyle: fontColor,
textAlign: "center",
textBaseline: "middle",
cursor: 'pointer'
};
var r = parseInt(fontSize * 0.5) + 2;
var _collapseBackCtx = {
x: x,
y: y,
r: r,
fillStyle: background,
strokeStyle: strokeStyle,
lineWidth: lineWidth
};
if (_collapseIcon) {
_collapseIcon.resetText(iconText);
Object.assign(_collapseIcon.context, collapseCtx);
Object.assign(_collapseIconBack.context, _collapseBackCtx);
} else {
_collapseIcon = new _canvax.default.Display.Text(iconText, {
id: iconId,
context: collapseCtx
});
_collapseIconBack = new Circle({
id: iconBackId,
context: _collapseBackCtx
});
_this11.labelsSp.addChild(_collapseIconBack);
_this11.labelsSp.addChild(_collapseIcon);
_collapseIcon._collapseIconBack = _collapseIconBack;
var _me = _this11;
//这里不能用箭头函数,听我的没错
_collapseIcon.on(event.types.get(), function (e) {
var trigger = _me.node.collapse;
e.eventInfo = {
trigger: trigger,
tipsContent: _me.node.collapse.tipsContent,
nodes: [node] //node
};
//下面的这个就只在鼠标环境下有就好了
if (_collapseIconBack.context) {
if (e.type == 'mousedown') {
_collapseIconBack.context.r += 1;
}
if (e.type == 'mouseup') {
_collapseIconBack.context.r -= 1;
}
}
;
if (_me.node.collapse.triggerEventType.indexOf(e.type) > -1) {
this.nodeData.rowData.collapsed = !this.nodeData.rowData.collapsed;
_me._syncToOrigin(this.nodeData.rowData);
var _trigger = new _trigger2.default(_me, {
origin: key
});
_me.app.resetData(null, _trigger);
}
_me.app.fire(e.type, e);
});
}
;
//TODO: 这个赋值只能在这里处理, 因为resetData的时候, 每次node都是一个新的node数据
//collapseIcon的引用就断了
_collapseIcon.nodeData = node;
node.collapseIcon = _collapseIcon;
node.collapseIconBack = _collapseIconBack;
} else {
var _collapseIcon2 = _this11.labelsSp.getChildById(iconId);
if (_collapseIcon2) _collapseIcon2.destroy();
var _collapseIconBack2 = _this11.labelsSp.getChildById(iconBackId);
if (_collapseIconBack2) _collapseIconBack2.destroy();
}
}
var getIconStyle = function getIconStyle(prop, charCode) {
var iconText = String.fromCharCode(parseInt(charCode, 16));
var fontSize = me.getProp(prop.fontSize, node, charCode);
var fontColor = me.getProp(prop.fontColor, node, charCode);
var fontFamily = me.getProp(prop.fontFamily, node, charCode);
var offsetX = me.getProp(prop.offsetX, node, charCode);
var offsetY = me.getProp(prop.offsetY, node, charCode);
var tipsContent = prop.tipsContent; //tips不需要提前计算,hover的时候计算 //me.getProp( prop.tipsContent, node, charCode);
return {
iconText: iconText,
fontSize: fontSize,
fontColor: fontColor,
fontFamily: fontFamily,
offsetX: offsetX,
offsetY: offsetY,
tipsContent: tipsContent
};
};
//绘制preIcon
if (node.preIconCharCode) {
var preIconId = key + "_pre_icon";
var _getIconStyle = getIconStyle(_this11.node.preIcon, node.preIconCharCode),
_iconText = _getIconStyle.iconText,
_fontSize = _getIconStyle.fontSize,
_fontColor = _getIconStyle.fontColor,
_fontFamily = _getIconStyle.fontFamily,
_offsetX = _getIconStyle.offsetX,
_offsetY = _getIconStyle.offsetY,
tipsContent = _getIconStyle.tipsContent;
var _x = parseInt(node.x - node.boundingClientWidth / 2 + _this11.node.padding + _offsetX);
var _y = parseInt(node.y + _offsetY);
//collapseIcon的 位置默认为左右方向的xy
var preIconCtx = {
x: _x,
y: _y + 1,
fontSize: _fontSize,
fontFamily: _fontFamily,
fillStyle: _fontColor,
textAlign: "left",
textBaseline: "middle",
cursor: 'pointer'
};
var _preIcon = _this11.labelsSp.getChildById(preIconId);
if (_preIcon) {
_preIcon.resetText(_iconText);
Object.assign(_preIcon.context, preIconCtx);
} else {
_preIcon = new _canvax.default.Display.Text(_iconText, {
id: preIconId,
context: preIconCtx
});
_this11.labelsSp.addChild(_preIcon);
}
;
node.preIconEl = _preIcon;
} else {
if (node.preIconEl) {
node.preIconEl.destroy();
delete node.preIconEl;
}
}
var iconsSpId = key + "_icons_sp";
var _iconsSp = _this11.labelsSp.getChildById(iconsSpId);
if (_iconsSp) {
_iconsSp.destroy();
}
;
if (node.icons && node.icons.length) {
_iconsSp = new _canvax.default.Display.Sprite({
id: iconsSpId
});
_this11.labelsSp.addChild(_iconsSp);
node.icons.forEach(function (icon, i) {
var _getIconStyle2 = getIconStyle(icon, icon.charCode),
iconText = _getIconStyle2.iconText,
fontSize = _getIconStyle2.fontSize,
fontColor = _getIconStyle2.fontColor,
fontFamily = _getIconStyle2.fontFamily,
offsetX = _getIconStyle2.offsetX,
offsetY = _getIconStyle2.offsetY,
tipsContent = _getIconStyle2.tipsContent;
var x = parseInt(node.x - node.boundingClientWidth / 2 + node.width + offsetX + (node.preIconEl ? iconWidth : 0) - _this11.node.padding / 2);
var y = parseInt(node.y + offsetY);
//collapseIcon的 位置默认为左右方向的xy
var iconCtx = {
x: x + i * iconWidth,
y: y + 1,
fontSize: fontSize,
fontFamily: fontFamily,
fillStyle: fontColor,
textAlign: "left",
textBaseline: "middle",
cursor: 'pointer'
};
var _icon = new _canvax.default.Display.Text(iconText, {
context: iconCtx
});
_iconsSp.addChild(_icon);
//这里不能用箭头函数,听我的没错
_icon.on(event.types.get(), function (e) {
var trigger = icon;
e.eventInfo = {
trigger: trigger,
tipsContent: tipsContent,
nodes: [node] //node
};
//下面的这个就只在鼠标环境下有就好了
if (this.context) {
if (e.type == 'mouseover') {
this.context.fontSize += 1;
}
if (e.type == 'mouseout') {
this.context.fontSize -= 1;
}
}
;
me.app.fire(e.type, e);
});
});
node.iconsSp = _iconsSp;
} else {
if (node.iconsSp) {
node.iconsSp.destroy();
delete node.iconsSp;
}
}
};
//绘制的时候一定要准备好conentElement的
_this11._initcontentElementAndSize(node.rowData).then(function () {
drawNode();
});
// if( !node.contentElement ){
// //绘制的时候如果发现没有 contentElement,那么就要把 contentElement 初始化了
// this._initcontentElementAndSize( node.rowData ).then( ()=>{
// drawNode();
// } )
// } else {
// drawNode();
// }
});
}
}, {
key: "_destroy",
value: function _destroy(item) {
var _this12 = this;
item.shapeElement && item.shapeElement.destroy();
if (item.contentElement) {
if (item.contentElement.destroy) {
item.contentElement.destroy();
} else {
//否则就可定是个dom
this.domContainer.removeChild(item.contentElement);
}
;
}
;
//下面的几个是销毁edge上面的元素
item.pathElement && item.pathElement.destroy();
item.labelElement && item.labelElement.destroy();
item.arrowElement && item.arrowElement.destroy();
item.edgeIconElement && item.edgeIconElement.destroy();
item.edgeIconBack && item.edgeIconBack.destroy();
//下面两个是tree中独有的
item.collapseIcon && item.collapseIcon.destroy();
item.collapseIconBack && item.collapseIconBack.destroy();
item.preIconEl && item.preIconEl.destroy();
item.iconsSp && item.iconsSp.destroy();
if (Array.isArray(item[this.field])) {
//是个edge的话,要检查下源头是不是没有子节点了, 没有子节点了, 还要把collapseIcon 都干掉
var sourceNode = item.source;
if (!this.data.edges.find(function (item) {
return item[_this12.field][0] == sourceNode[_this12.field];
})) {
//如歌edges里面还有 targetNode[this.field] 开头的,targetNode 还有子节点, 否则就可以把 targetNode的collapseIcon去掉
sourceNode.collapseIcon && sourceNode.collapseIcon.destroy();
sourceNode.collapseIconBack && sourceNode.collapseIconBack.destroy();
}
}
}
}, {
key: "arrayToTreeJsonForRelation",
value: function arrayToTreeJsonForRelation(data) {
var _this13 = this;
// [ { key: 1, name: },{key:'1,2'} ] to [ { name: children: [ {}... ] } ]
var _nodes = {};
var _edges = {};
_.each(data, function (item) {
var key = item[_this13.field] + '';
if (key.split(',').length == 1) {
_nodes[key] = item;
} else {
_edges[key] = item;
}
;
});
//先找到所有的一层
var arr = [];
_.each(_nodes, function (node, nkey) {
var isFirstLev = true;
_.each(_edges, function (edge, ekey) {
ekey = ekey + '';
if (ekey.split(',')[1] == nkey) {
isFirstLev = false;
return false;
}
});
if (isFirstLev) {
arr.push(node);
node.__inRelation = true;
}
;
});
//有了第一层就好办了
var _getChildren = function getChildren(list) {
_.each(list, function (node) {
if (node.__cycle) return;
var key = node[_this13.field];
_.each(_edges, function (edge, ekey) {
ekey = ekey + '';
if (ekey.split(',')[0] == key) {
//那么说明[1] 就是自己的children
var childNode = _nodes[ekey.split(',')[1]];
if (childNode) {
if (!node[_this13.childrenField]) node[_this13.childrenField] = [];
if (!_.find(node[_this13.childrenField], function (_child) {
return _child[_this13.field] == childNode[_this13.field];
})) {
node[_this13.childrenField].push(childNode);
}
;
//node[ this.childrenField ].push( childNode );
//如果这个目标节点__inRelation已经在关系结构中
//那么说明形成闭环了,不需要再分析这个节点的children
if (childNode.__inRelation) {
childNode.__cycle = true;
}
;
}
}
});
if (node[_this13.childrenField] && node[_this13.childrenField].length) {
_getChildren(node[_this13.childrenField]);
}
;
});
};
_getChildren(arr);
return arr.length ? arr[0] : null;
}
}], [{
key: "defaultProps",
value: function defaultProps() {
return {
childrenField: {
detail: '树结构数据的关联字段',
documentation: '如果是树结构的关联数据,不是行列式,那么就通过这个字段来建立父子关系',
default: 'children'
},
rankdir: {
detail: '布局方向',
default: 'LR'
},
layout: {
detail: '紧凑的树布局方案, 也可以设置为一个function,自定义布局算法',
default: "tree"
},
layoutOpts: {
detail: '布局引擎对应的配置',
propertys: {}
},
ranksep: {
detail: '排与排之间的距离',
default: 40
},
nodesep: {
detail: '同级node之间的距离',
default: 20
},
node: {
detail: '单个节点的配置',
propertys: {
content: {
detail: ' 内容配置',
propertys: {
textAlign: {
detail: '左右对齐方式',
default: 'left'
}
}
},
collapse: {
detail: '树状图是否有节点收缩按钮',
propertys: {
enabled: {
detail: "是否开启",
default: true
},
field: {
detail: "用来记录collapsed是否折叠的字段,在节点的数据上",
default: "collapsed"
},
triggerEventType: {
detail: '触发事件',
default: 'click,tap'
},
openCharCode: {
detail: "点击后触发展开的icon chartCode,当前状态为收缩",
default: ''
},
closeCharCode: {
detail: "点击后触发收缩的icon chartCode,当前状态为展开",
default: ''
},
fontSize: {
detail: "icon字号大小",
default: 10
},
fontColor: {
detail: "icon字体颜色",
default: '#666'
},
fontFamily: {
detail: "icon在css中的fontFamily",
default: 'iconfont'
},
tipsContent: {
detail: '鼠标移动到收缩icon上面的tips内容',
default: ''
},
offsetX: {
detail: 'x方向偏移量',
default: 0
},
offsetY: {
detail: 'y方向偏移量',
default: 0
},
background: {
detail: 'icon的 背景色',
default: '#fff'
},
lineWidth: {
detail: '边框大小',
default: 1
},
strokeStyle: {
detail: '描边颜色',
default: '#667894'
}
}
},
preIcon: {
detail: '内容前面的一个icon,主要用来描这个node的类型',
propertys: {
charCode: {
detail: "icon的iconfont字符串",
default: ''
},
fontSize: {
detail: "icon字号大小",
default: 18
},
fontColor: {
detail: "icon字体颜色",
default: '#666'
},
fontFamily: {
detail: "icon在css中的fontFamily",
default: 'iconfont'
},
tipsContent: {
detail: '鼠标移动到收缩icon上面的tips内容',
default: ''
},
offsetX: {
detail: 'x方向偏移量',
default: 0
},
offsetY: {
detail: 'y方向偏移量',
default: 0
}
}
},
icons: {
detail: '相对于preIcon,跟在label后面的一组icon',
default: []
},
iconsDefault: {
detail: '内容后面的一组icon,是个数组, 支持函数返回一组icon,单个icon的格式和preIcon保持一致',
propertys: {
charCode: {
detail: "icon的iconfont字符串",
default: ''
},
fontSize: {
detail: "icon字号大小",
default: 12
},
fontColor: {
detail: "icon字体颜色",
default: '#666'
},
fontFamily: {
detail: "icon在css中的fontFamily",
default: 'iconfont'
},
tipsContent: {
detail: '鼠标移动到收缩icon上面的tips内容',
default: ''
},
offsetX: {
detail: 'x方向偏移量',
default: 0
},
offsetY: {
detail: 'y方向偏移量',
default: 0
}
}
}
}
},
line: {
detail: '连线配置',
propertys: {
arrow: {
detail: '箭头配置',
propertys: {
enabled: {
detail: '是否显示',
default: false
}
}
},
edgeLabel: {
detail: '连线文本',
propertys: {
enabled: {
detail: '是否要连线的文本',
default: false
}
}
},
icon: {
detail: '连线上的icon',
propertys: {
enabled: {
detail: '是否要连线上的icon',
default: false
}
}
}
}
}
};
}
}]);
}(_base.default);
_base.default.registerComponent(compactTree, 'graphs', 'compacttree');
var _default = exports.default = compactTree;