chartx
Version:
Data Visualization Chart Library
458 lines (453 loc) • 16.1 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 _component = _interopRequireDefault(require("../component"));
var _canvax = _interopRequireDefault(require("canvax"));
var _tools = require("../../utils/tools");
var _intersect = require("../../utils/intersect");
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 BrokenLine = _canvax.default.Shapes.BrokenLine;
var Arrow = _canvax.default.Shapes.Arrow;
var Text = _canvax.default.Display.Text;
var Circle = _canvax.default.Shapes.Circle;
var relationBackLine = /*#__PURE__*/function (_Component) {
function relationBackLine(opt, app) {
var _this;
(0, _classCallCheck2.default)(this, relationBackLine);
_this = _callSuper(this, relationBackLine, [opt, app]);
_this.name = "relation_backline";
_.extend(true, _this, (0, _tools.getDefaultProps)(relationBackLine.defaultProps()), opt);
_this.pointList = null;
_this.sprite = new _canvax.default.Display.Sprite();
_this._line = null;
_this._arrow = null;
_this._label = null;
_this._icon = null;
return _this;
}
(0, _inherits2.default)(relationBackLine, _Component);
return (0, _createClass2.default)(relationBackLine, [{
key: "draw",
value: function draw(opt) {
!opt && (opt = {});
this.width = opt.width;
this.height = opt.height;
this.origin = opt.origin;
this._widget();
}
}, {
key: "reset",
value: function reset(opt) {
opt && _.extend(true, this, opt);
this._widget();
}
}, {
key: "_widget",
value: function _widget() {
var _this2 = this;
var _graphs = this.app.getGraphs();
if (_graphs.length) {
var _graph = _graphs[0];
_graph.on('complete', function () {
_this2._setPoints(_graph);
_this2._drawLine();
_this2._drawArrow();
_this2._drawIcon();
_graph.graphsSp.addChild(_this2.sprite);
});
}
;
}
}, {
key: "_setPoints",
value: function _setPoints(_graph) {
if (!this.line.pointList) {
var key = this.key;
var beginNode = _graph.data.nodes.find(function (_g) {
return _g.key == key.split(',')[0];
});
var beginNodeBBox = {
x: beginNode.x - beginNode.width / 2,
y: beginNode.y - beginNode.height / 2,
width: beginNode.width,
height: beginNode.height
};
var endNode = _graph.data.nodes.find(function (_g) {
return _g.key == key.split(',')[1];
});
var endNodeBBox = {
x: endNode.x - endNode.width / 2,
y: endNode.y - endNode.height / 2,
width: endNode.width,
height: endNode.height
};
var fristPoint = [beginNodeBBox.x + beginNodeBBox.width, beginNodeBBox.y + beginNodeBBox.height / 2];
var secondPoint = [beginNodeBBox.x + beginNodeBBox.width + 20, beginNodeBBox.y + beginNodeBBox.height / 2];
var endPoint;
var endNodePointX = endNodeBBox.x + endNodeBBox.width / 2;
var endNodeTopPoint = [endNodePointX, endNodeBBox.y];
var endNodeBottomPoint = [endNodePointX, endNodeBBox.y + endNodeBBox.height];
endPoint = endNodeTopPoint;
var getThroughNodesNum = function getThroughNodesNum(dissY) {
var y = secondPoint[1] + dissY;
var num = 0;
_graph.data.nodes.forEach(function (node) {
var rectX = node.x - node.width / 2;
var rectY = node.y - node.height / 2;
var nodeRect = {
x: rectX,
y: rectY,
xMax: rectX + node.width,
yMax: rectY + node.height
};
if ((0, _intersect.lineRect)({
x: secondPoint[0],
y: y
}, {
x: endNodePointX,
y: y
}, nodeRect)) {
num++;
}
;
});
return num;
};
var dissY,
topDissY,
bottomDissY,
lines = [];
if (this.line.dissY == null) {
topDissY = -(secondPoint[1] - (Math.min(endNodeBBox.y, beginNodeBBox.y) - 6));
lines.push({
dissY: topDissY,
throughNodesNum: getThroughNodesNum(topDissY),
endPoint: endNodeTopPoint,
type: 'n'
});
//如果发现两个节点中间有足够的间隙,还可以
if (endNodeBBox.y - (beginNodeBBox.y + beginNodeBBox.height) > 20) {
//向下连接 z 形状
topDissY = beginNodeBBox.y + beginNodeBBox.height + (endNodeBBox.y - (beginNodeBBox.y + beginNodeBBox.height)) / 2 - secondPoint[1];
lines.push({
dissY: topDissY,
throughNodesNum: getThroughNodesNum(topDissY),
endPoint: endNodeTopPoint,
type: 'down_z'
});
}
;
//然后检测出来连接目标节点下面的点,只能从下往上
var endBottomY = endNodeBottomPoint[1];
bottomDissY = Math.max(endBottomY, beginNodeBBox.y + beginNodeBBox.height) + 6 - secondPoint[1];
lines.push({
dissY: bottomDissY,
throughNodesNum: getThroughNodesNum(bottomDissY),
endPoint: endNodeBottomPoint,
type: 'u'
});
if (beginNodeBBox.y - endBottomY > 20) {
//向上的z 形状连接
bottomDissY = endBottomY + (beginNodeBBox.y - endBottomY) / 2 - secondPoint[1];
lines.push({
dissY: bottomDissY,
throughNodesNum: getThroughNodesNum(bottomDissY),
endPoint: endNodeBottomPoint,
type: 'up_z'
});
}
;
//先按照最小的穿过node的数量排序, 取穿过node最少的line
lines = lines.sort(function (a, b) {
return a.throughNodesNum - b.throughNodesNum;
});
//如果前面有几个是throughNodesNum相同的,组成一个小组,重新按照dissY的绝对值最小值排序
var _lines = [];
lines.forEach(function (line) {
if (line.throughNodesNum == lines[0].throughNodesNum) {
_lines.push(line);
}
});
_lines = _lines.sort(function (a, b) {
return Math.abs(a.dissY) - Math.abs(b.dissY);
});
dissY = _lines[0].dissY;
endPoint = _lines[0].endPoint;
} else {
dissY = this.line.dissY;
}
;
var thirdPoint, secondLastPoint;
thirdPoint = [secondPoint[0], secondPoint[1] + dissY];
secondLastPoint = [endPoint[0], secondPoint[1] + dissY];
this.pointList = [fristPoint, secondPoint, thirdPoint, secondLastPoint, endPoint];
} else {
this.pointList = this.line.pointList;
}
}
}, {
key: "_drawLine",
value: function _drawLine() {
var me = this;
if (!me.line.enabled) return;
var lineOpt = {
pointList: this.pointList,
lineWidth: this.line.lineWidth,
strokeStyle: this.line.strokeStyle,
lineType: this.line.lineType
};
if (this._line) {
_.extend(this._line.context, lineOpt);
} else {
this._line = new BrokenLine({
context: lineOpt
});
this.sprite.addChild(this._line);
}
;
//线条渲染结束
}
}, {
key: "_drawArrow",
value: function _drawArrow() {
var pointsList = this.pointList;
var offsetY = 2;
var endPoint = pointsList[pointsList.length - 1];
var secondLastPoint = pointsList[pointsList.length - 2];
if (secondLastPoint[1] < endPoint[1]) {
offsetY = -2;
}
var strokeStyle = this.line.strokeStyle;
var ctx = {
y: offsetY,
control: {
x: secondLastPoint[0],
y: secondLastPoint[1]
},
point: {
x: endPoint[0],
y: endPoint[1]
},
strokeStyle: strokeStyle,
fillStyle: strokeStyle
};
if (this._arrow) {
_.extend(true, this._arrow.context, ctx);
// this._line.context.y = ctx.y;
// this._line.context.control.x = ctx.control.x;
// this._line.context.control.y = ctx.control.y;
// this._line.context.point.x = ctx.point.x;
// this._line.context.point.y = ctx.point.y;
// this._line.context.strokeStyle = ctx.strokeStyle;
// this._line.context.fillStyle = ctx.fillStyle;
} else {
this._arrow = new Arrow({
context: ctx
});
this.sprite.addChild(this._arrow);
}
}
}, {
key: "_drawIcon",
value: function _drawIcon() {
var me = this;
if (this.icon.enabled) {
var _chartCode = this._getProp(this.icon.charCode, this);
var charCode = String.fromCharCode(parseInt(_chartCode, 16));
if (_chartCode != '') {
var secondPoint = this.pointList[1];
var lineWidth = this._getProp(this.icon.lineWidth, this);
var strokeStyle = this._getProp(this.icon.strokeStyle, this);
var fontFamily = this._getProp(this.icon.fontFamily, this);
var fontSize = this._getProp(this.icon.fontSize, this);
var fontColor = this._getProp(this.icon.fontColor, this);
var background = this._getProp(this.icon.background, this);
var textAlign = 'center';
var textBaseline = 'middle';
var offset = this._getProp(this.icon.offset, this);
var offsetX = this._getProp(this.icon.offsetX, this);
var offsetY = this._getProp(this.icon.offsetY, this);
if (!offset) {
//default 使用edge.x edge.y 也就是edge label的位置
offset = {
x: secondPoint[0] + offsetX,
y: secondPoint[1] + offsetY
};
}
;
var _iconBackCtx = {
x: offset.x,
y: offset.y - 1,
r: parseInt(fontSize * 0.5) + 2,
fillStyle: background,
strokeStyle: strokeStyle,
lineWidth: lineWidth
};
if (this._iconBack) {
//_.extend( true, _iconBack.context, _iconBackCtx )
Object.assign(this._iconBack.context, _iconBackCtx);
} else {
this._iconBack = new Circle({
context: _iconBackCtx
});
this.sprite.addChild(this._iconBack);
}
;
if (this._icon) {
this._icon.resetText(charCode);
this._icon.context.x = offset.x;
this._icon.context.y = offset.y;
this._icon.context.fontSize = fontSize;
this._icon.context.fillStyle = fontColor;
this._icon.context.textAlign = textAlign;
this._icon.context.textBaseline = textBaseline;
this._icon.context.fontFamily = fontFamily;
this._icon.context.lineWidth = lineWidth;
this._icon.context.strokeStyle = strokeStyle;
} else {
this._icon = new Text(charCode, {
context: {
x: offset.x,
y: offset.y,
fillStyle: fontColor,
cursor: 'pointer',
fontSize: fontSize,
textAlign: textAlign,
textBaseline: textBaseline,
fontFamily: fontFamily,
lineWidth: lineWidth,
strokeStyle: strokeStyle
}
});
this._icon.on(event.types.get(), function (e) {
var trigger = me.line;
if (me.icon['on' + e.type]) {
trigger = me.icon;
}
;
e.eventInfo = {
trigger: trigger,
nodes: [{
name: me.key
}]
};
me.app.fire(e.type, e);
});
me.sprite.addChild(this._icon);
}
}
}
}
}, {
key: "_getProp",
value: function _getProp(prop, nodeData) {
var _prop = prop;
if (_.isFunction(prop)) {
_prop = prop.apply(this, [nodeData]);
}
;
return _prop;
}
}], [{
key: "defaultProps",
value: function defaultProps() {
return {
key: {
detail: '和relation的line保持一致,用逗号分割',
default: null
},
line: {
detail: '线的配置',
propertys: {
enabled: {
detail: '是否开启',
default: true
},
pointList: {
detail: '回链线的points',
default: null
},
lineWidth: {
detail: '线宽',
default: 1
},
strokeStyle: {
detail: '线的颜色',
default: '#e5e5e5'
},
lineType: {
detail: '线的样式,虚线(dashed)实线(solid)',
default: 'solid'
},
dissY: {
detail: '拐点和起始节点的距离',
default: null
}
}
},
icon: {
detail: 'line上面的icon',
propertys: {
enabled: {
detail: '是否开启线上的icon设置',
default: true
},
charCode: {
detail: 'iconfont上面对应的unicode中&#x后面的字符',
default: null
},
lineWidth: {
detail: 'icon描边线宽',
default: 1
},
strokeStyle: {
detail: 'icon的描边颜色',
default: '#e5e5e5'
},
fontColor: {
detail: 'icon的颜色',
default: '#e5e5e5'
},
fontFamily: {
detail: 'font-face的font-family设置',
default: 'iconfont'
},
fontSize: {
detail: 'icon的字体大小',
default: 14
},
offset: {
detail: 'icon的位置,函数,参数是整个edge对象',
default: null
},
offsetX: {
detail: '在计算出offset后的X再次便宜量',
default: 1
},
offsetY: {
detail: '在计算出offset后的Y再次便宜量',
default: 2
},
background: {
detail: 'icon的背景颜色,背景为圆形',
default: "#fff"
}
}
}
};
}
}]);
}(_component.default);
_component.default.registerComponent(relationBackLine, 'relation_backline');
var _default = exports.default = relationBackLine;