chartx
Version:
Data Visualization Chart Library
758 lines (746 loc) • 24.9 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
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 _index = _interopRequireDefault(require("../index"));
var _tools = require("../../../utils/tools");
var _index2 = _interopRequireDefault(require("../../../layout/pack/index"));
var _index3 = _interopRequireDefault(require("../../../layout/hierarchy/index"));
var _color = require("../../../utils/color");
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 BubbleGraphs = /*#__PURE__*/function (_GraphsBase) {
function BubbleGraphs(opt, app) {
var _this;
(0, _classCallCheck2.default)(this, BubbleGraphs);
_this = _callSuper(this, BubbleGraphs, [opt, app]);
_this.type = "bubble";
_.extend(true, _this, (0, _tools.getDefaultProps)(BubbleGraphs.defaultProps()), opt);
_this.init();
return _this;
}
(0, _inherits2.default)(BubbleGraphs, _GraphsBase);
return (0, _createClass2.default)(BubbleGraphs, [{
key: "init",
value: function init() {
this._shapesp = new _canvax.default.Display.Sprite({
id: "shapesp"
});
this._textsp = new _canvax.default.Display.Sprite({
id: "textsp"
});
this.sprite.addChild(this._shapesp);
this.sprite.addChild(this._textsp);
this.sprite.context.x = this.app.padding.left;
this.sprite.context.y = this.app.padding.top;
}
}, {
key: "draw",
value: function draw(opt) {
!opt && (opt = {});
_.extend(true, this, opt);
this.data = this._trimGraphs();
this._widget();
var me = this;
if (this.animation && !opt.resize && !me.inited) {
this.grow(function () {
me.fire("complete");
});
} else {
this.fire("complete");
}
;
//inited 和 complete还不同,complete 是需要等动画结束
this.inited = true;
return this;
}
}, {
key: "resetData",
value: function resetData(dataFrame) {
this.dataFrame = dataFrame;
this.data = this._trimGraphs();
this._widget();
this.grow();
}
}, {
key: "getNodesAt",
value: function getNodesAt() {
return [];
}
}, {
key: "_trimGraphs",
value: function _trimGraphs() {
var pack = (0, _index2.default)().size([this.app.width - this.app.padding.left - this.app.padding.right, this.app.height - this.app.padding.top - this.app.padding.bottom]).padding(this.node.margin);
var root = (0, _index3.default)({
children: this.dataFrame.jsonOrg
}).sum(function (d) {
return d.value;
}); // 根据你的数据结构可能需要调整
var nodes = pack(root).descendants();
var _coord = this.app.getComponent({
name: 'coord'
});
var fieldConfig = _coord.getFieldConfig(this.field);
this._alphaData = null;
this._alphaMaxValue = null;
this._alphaMinValue = null;
var tmplData = [];
var iNode = -1;
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
if (!node.depth && !this.node.showRootNode) {
continue;
}
if (node.children && node.children.length && !this.node.showSubGroupNode) {
continue;
}
iNode++;
var radius = Math.min(node.r, this.node.maxRadius);
var color = this.color || this._getStyle(this.node.fillStyle, node) || fieldConfig.color;
var fillStyle = {
points: [0, -node.r, 0, node.r],
lineargradient: [{
position: 0,
color: (0, _color.colorRgba)(color, 1)
}, {
position: 1,
color: (0, _color.colorRgba)(color, 0.6)
}]
};
var strokeStyle = this._getStyle(this.node.strokeStyle || this.node.fillStyle, node);
Object.assign(node, {
type: "bubble",
rowData: node.data,
//为了和其他的的数据结构rowData保存一致
field: this.field,
fieldColor: color,
iNode: iNode,
focused: false,
selected: false,
//下面的属性都单独设置
radius: radius,
fillStyle: fillStyle,
color: color,
strokeStyle: strokeStyle,
lineType: null,
lineDash: null,
strokeAlpha: 1,
lineWidth: 0,
label: null,
fillAlpha: 1,
nodeElement: null //对应的canvax 节点, 在widget之后赋值
});
this._setFillAlpha(node);
this._setLineWidth(node);
this._setLineType(node);
this._setLineDash(node);
this._setStrokeAlpha(node);
this._setText(node);
tmplData.push(node);
}
return tmplData;
}
}, {
key: "_setText",
value: function _setText(nodeLayoutData) {
if (this.label.field != null) {
if (_.isString(this.label.field) && nodeLayoutData.rowData[this.label.field]) {
nodeLayoutData.label = this.label.format(nodeLayoutData.rowData[this.label.field], nodeLayoutData);
}
}
}
}, {
key: "_setFillAlpha",
value: function _setFillAlpha(nodeLayoutData) {
// nodeLayoutData.fillAlpha = this._getProp( this.node.fillAlpha, nodeLayoutData );
// return this;
var alpha;
var _alpha = this.node.fillAlpha;
var minAlpha = this.node.minFillAlpha;
var maxAlpha = this.node.maxFillAlpha;
var rowData = nodeLayoutData.rowData;
if (_alpha != null) {
if (_.isString(_alpha) && rowData[_alpha]) {
//如果配置了某个字段作为r,那么就要自动计算比例
if (!this._alphaData && !this._alphaMaxValue && !this._alphaMinValue) {
this._alphaData = this.dataFrame.getFieldData(_alpha);
this._alphaData = this._alphaData.filter(function (item) {
return item || item == 0;
});
this._alphaMaxValue = _.max(this._alphaData);
this._alphaMinValue = _.min(this._alphaData);
}
;
var rVal = rowData[_alpha];
if (this._alphaMaxValue == this._alphaMinValue) {
alpha = minAlpha + (maxAlpha - minAlpha) / 2;
} else {
alpha = minAlpha + (rVal - this._alphaMinValue) / (this._alphaMaxValue - this._alphaMinValue) * (maxAlpha - minAlpha);
}
;
} else {
alpha = this._getProp(this.node.fillAlpha, nodeLayoutData);
}
} else {
alpha = 0;
}
//console.log(alpha)
nodeLayoutData.fillAlpha = alpha;
return this;
}
}, {
key: "_setStrokeAlpha",
value: function _setStrokeAlpha(nodeLayoutData) {
nodeLayoutData.strokeAlpha = this._getProp(this.node.strokeAlpha, nodeLayoutData);
return this;
}
}, {
key: "_getProp",
value: function _getProp(prop, nodeLayoutData) {
var _prop = prop;
if (_.isArray(prop)) {
_prop = prop[nodeLayoutData.iGroup];
}
;
if (_.isFunction(prop)) {
_prop = prop.apply(this, [nodeLayoutData]);
}
;
return _prop;
}
}, {
key: "_getStyle",
value: function _getStyle(style, nodeLayoutData) {
var _style = style;
if (_.isArray(style)) {
_style = style[nodeLayoutData.iGroup];
}
;
if (_.isFunction(style)) {
_style = style.apply(this, [nodeLayoutData]);
}
;
if (!_style) {
_style = nodeLayoutData.fieldColor;
}
;
return _style;
}
}, {
key: "_setLineWidth",
value: function _setLineWidth(nodeLayoutData) {
nodeLayoutData.lineWidth = this._getProp(this.node.lineWidth, nodeLayoutData);
return this;
}
}, {
key: "_setLineType",
value: function _setLineType(nodeLayoutData) {
nodeLayoutData.lineType = this._getProp(this.node.lineType, nodeLayoutData);
return this;
}
}, {
key: "_setLineDash",
value: function _setLineDash(nodeLayoutData) {
var _this2 = this;
var _getProp = function _getProp(prop, nodeLayoutData) {
var _prop = prop;
// if( _.isArray( prop ) ){
// _prop = prop[ nodeLayoutData.iGroup ]
// };
if (_.isFunction(prop)) {
_prop = prop.apply(_this2, [nodeLayoutData]);
}
;
return _prop;
};
nodeLayoutData.lineDash = _getProp(this.node.lineDash, nodeLayoutData);
return this;
}
//根据layoutdata开始绘制
}, {
key: "_widget",
value: function _widget() {
var me = this;
_.each(_.flatten([me._shapesp.children, me._textsp.children]), function (el) {
el.__used = false;
});
_.each(me.data, function (nodeData, iNode) {
var _nodeElement = me._getNodeElement(nodeData, iNode);
if (!_nodeElement) {
nodeData.__isNew = true;
}
;
var _context = {
x: nodeData.x,
y: nodeData.y,
r: nodeData.radius,
fillStyle: nodeData.fillStyle,
strokeStyle: nodeData.strokeStyle,
strokeAlpha: nodeData.strokeAlpha,
lineWidth: nodeData.lineWidth,
lineType: nodeData.lineType,
lineDash: nodeData.lineDash,
fillAlpha: nodeData.fillAlpha,
cursor: "pointer"
};
if (me.animation && (!me.inited || nodeData.__isNew)) {
_context.r = 1;
}
;
if (!_nodeElement) {
_nodeElement = new Circle({
id: "shape_" + iNode,
hoverClone: false,
context: _context
});
me._shapesp.addChild(_nodeElement);
_nodeElement.on(event.types.get(), function (e) {
e.eventInfo = {
title: null,
trigger: 'this.node',
//me.node,
nodes: [this.nodeData]
};
if (e.type == 'mouseover') {
me.focusAt(this.nodeData);
}
;
if (e.type == 'mouseout') {
!this.nodeData.selected && me.unfocusAt(this.nodeData);
}
;
//fire到root上面去的是为了让root去处理tips
//先触发用户事件,再处理后面的选中事件
me.app.fire(e.type, e);
});
} else {
//_nodeElement.context = _context;
//_.extend( _nodeElement.context, _context );
_nodeElement.animate(_context);
}
;
_nodeElement.__used = true;
//数据和canvax原件相互引用
_nodeElement.nodeData = nodeData;
_nodeElement.iNode = iNode;
nodeData.nodeElement = _nodeElement;
//如果有label
if (nodeData.label && me.label.enabled && nodeData.radius > 15) {
//20*2就是40 至少要放的下两个字符才有房文本的意义
var _label = _nodeElement.labelElement;
if (!_label) {
_label = new _canvax.default.Display.Text(nodeData.label, {
id: "scat_text_" + iNode,
context: {}
});
_.extend(_label.context, me._getTextContext(_label, _context, nodeData));
me._textsp.addChild(_label);
} else {
_label.resetText(nodeData.label);
_label.animate(me._getTextContext(_label, _context, nodeData));
}
;
_label.__used = true;
//图形节点和text文本相互引用
_nodeElement.labelElement = _label;
_label.nodeElement = _nodeElement;
if (_label.getTextWidth() + 10 > nodeData.radius * 2) {
//_label.context.visible = false
var newLabels = [''];
for (var i = 0, l = nodeData.label.length; i < l; i++) {
var str = nodeData.label[i];
//newLabels[ newLabels.length-1 ] += str
_label.resetText(newLabels.join('\n') + str);
if (_label.getTextWidth() + 10 > nodeData.radius * 2) {
if (newLabels[0].length == 1) {
//加入一样只能放一个字符,那么就没有必要显示 多行了, 直接一行就好了
//_label.context.visible = false //也不隐藏
break;
}
if (newLabels.length < 3) {
//最多显示3行label
newLabels.push(str);
} else {
newLabels[newLabels.length - 1] = newLabels[newLabels.length - 1].slice(0, -2);
_label.resetText(newLabels.join('\n') + '...');
//调整下垂直高度后居中
var h = _label.getTextHeight();
_label.__offsetY = -(h / 2 - 8);
_label.context.y += _label.__offsetY;
break;
}
} else {
newLabels[newLabels.length - 1] += str;
}
if (i == l - 1) {
//调整下垂直高度后居中
var _h = _label.getTextHeight();
_label.__offsetY = -(_h / 2 - 8);
_label.context.y += _label.__offsetY;
}
}
}
}
;
});
//多余的元素渐隐后销毁
_.each(_.flatten([me._shapesp.children, me._textsp.children]), function (el) {
if (!el.__used) {
el.animate({
globalAlpha: 0,
r: 0
}, {
onComplete: function onComplete() {
el.destroy();
}
});
}
});
}
}, {
key: "_getNodeElement",
value: function _getNodeElement(nodeData, iNode) {
var me = this;
var nodeEle;
var dataKey = me.node.dataKey;
if (!dataKey) {
nodeEle = me._shapesp.getChildAt(iNode);
} else {
if (_.isString(dataKey)) {
dataKey = dataKey.split(",");
}
;
for (var i = 0, l = this._shapesp.children.length; i < l; i++) {
var _nodeEle = this._shapesp.children[i];
var isThisNodeEle = true;
for (var ii = 0, ll = dataKey.length; ii < ll; ii++) {
var key = dataKey[ii];
if (_nodeEle.nodeData.rowData[key] != nodeData.rowData[key]) {
isThisNodeEle = false;
break;
}
;
}
;
if (isThisNodeEle && dataKey.length) {
nodeEle = _nodeEle;
break;
}
;
}
;
}
;
return nodeEle;
}
}, {
key: "_getTextContext",
value: function _getTextContext(_label, _context, node) {
var fontSize = this.label.fontSize;
if (_label.getTextWidth() > _context.r * 2) {
fontSize -= 2;
}
;
var ctx = {
x: _context.x,
y: _context.y,
fillStyle: this._getStyle(this.label.fontColor, node),
fontSize: fontSize,
textAlign: 'center',
textBaseline: 'middle'
};
return ctx;
}
/**
* 生长动画
*/
}, {
key: "grow",
value: function grow(callback) {
var i = 0;
var l = this.data.length - 1;
var me = this;
_.each(this.data, function (nodeData) {
if (nodeData.__isNew) {
me._growNode(nodeData, function () {
i = i + 1;
delete nodeData.__isNew;
if (i == l) {
callback && callback();
}
});
}
;
});
}
}, {
key: "_growNode",
value: function _growNode(nodeData, callback) {
var me = this;
nodeData.nodeElement.animate({
x: nodeData.x,
y: nodeData.y,
r: nodeData.radius
}, {
onUpdate: function onUpdate(opt) {
if (this.labelElement && this.labelElement.context) {
this.labelElement.context.x = opt.x;
this.labelElement.context.y = opt.y + (this.labelElement.__offsetY || 0);
}
},
delay: Math.round(Math.random() * 300),
onComplete: function onComplete() {
callback && callback();
}
});
}
}, {
key: "focusAt",
value: function focusAt(target) {
var nodeData;
var iNode;
if ((0, _typeof2.default)(target) == 'object') {
nodeData = target;
} else {
iNode = target;
nodeData = this.data.find(function (item) {
return item.iNode == iNode;
});
}
if (!this.node.focus.enabled || nodeData.focused) return;
var nctx = nodeData.nodeElement.context;
nctx.lineWidth = this._getProp(this.node.focus.lineWidth, nodeData);
nctx.strokeAlpha = this._getProp(this.node.focus.strokeAlpha, nodeData);
nctx.fillAlpha = this._getProp(this.node.focus.fillAlpha, nodeData);
nodeData.focused = true;
}
}, {
key: "unfocusAt",
value: function unfocusAt(target) {
var nodeData;
var iNode;
if ((0, _typeof2.default)(target) == 'object') {
nodeData = target;
} else {
iNode = target;
nodeData = this.data.find(function (item) {
return item.iNode == iNode;
});
}
if (!this.node.focus.enabled || !nodeData.focused) return;
var nctx = nodeData.nodeElement.context;
nctx.lineWidth = this._getProp(nodeData.lineWidth, nodeData);
nctx.strokeAlpha = this._getProp(nodeData.strokeAlpha, nodeData);
nctx.fillAlpha = this._getProp(nodeData.fillAlpha, nodeData);
nctx.strokeStyle = this._getProp(nodeData.strokeStyle, nodeData);
nodeData.focused = false;
}
}, {
key: "selectAt",
value: function selectAt(target) {
//let nodeData = this.data[ ind ];
var nodeData;
var iNode;
if ((0, _typeof2.default)(target) == 'object') {
nodeData = target;
} else {
iNode = target;
nodeData = this.data.find(function (item) {
return item.iNode == iNode;
});
}
if (!this.node.select.enabled || nodeData.selected) return;
var nctx = nodeData.nodeElement.context;
nctx.lineWidth = this._getProp(this.node.select.lineWidth, nodeData);
nctx.strokeAlpha = this._getProp(this.node.select.strokeAlpha, nodeData);
nctx.fillAlpha = this._getProp(this.node.select.fillAlpha, nodeData);
nodeData.selected = true;
}
}, {
key: "unselectAt",
value: function unselectAt(target) {
//let nodeData = this.data[ ind ];
var nodeData;
var iNode;
if ((0, _typeof2.default)(target) == 'object') {
nodeData = target;
} else {
iNode = target;
nodeData = this.data.find(function (item) {
return item.iNode == iNode;
});
}
if (!this.node.select.enabled || !nodeData.selected) return;
var nctx = nodeData.nodeElement.context;
if (nodeData.focused) {
//有e 说明这个函数是事件触发的,鼠标肯定还在node上面
nctx.lineWidth = this._getProp(this.node.focus.lineWidth, nodeData);
nctx.strokeAlpha = this._getProp(this.node.focus.strokeAlpha, nodeData);
nctx.fillAlpha = this._getProp(this.node.focus.fillAlpha, nodeData);
} else {
nctx.lineWidth = nodeData.lineWidth;
nctx.strokeAlpha = nodeData.strokeAlpha;
nctx.fillAlpha = nodeData.fillAlpha;
}
;
nodeData.selected = false;
}
}, {
key: "getNodesOfPos",
value: function getNodesOfPos() {
//sat的 getNodesOfPos 一定要有两个点
var _nodesInfoList = []; //节点信息集合
return _nodesInfoList;
}
}], [{
key: "defaultProps",
value: function defaultProps() {
return {
field: {
detail: '字段配置',
default: null
},
node: {
detail: '单数据节点图形设置',
propertys: {
margin: {
detail: '圆于圆之间的间隔',
default: '10'
},
maxRadius: {
detail: '圆点最大半径',
default: '100'
},
showRootNode: {
detail: '是否显示根节点的圆',
default: false
},
showSubGroupNode: {
detail: '是否显示子节点的拥有子节点的分组节点',
default: true
},
fillStyle: {
detail: '节点景色',
default: null
},
fillAlpha: {
detail: '节点透明度',
default: 0.8
},
maxFillAlpha: {
detail: '节点最大透明度',
default: 1
},
minFillAlpha: {
detail: '节点最小透明度',
default: 0.2
},
strokeStyle: {
detail: '节点描边颜色',
default: null
},
lineWidth: {
detail: '节点描边线宽',
default: 0
},
lineType: {
detail: '描边样式',
default: 'solid'
},
lineDash: {
detail: '虚线样式',
default: [2, 6]
},
strokeAlpha: {
detail: '节点描边透明度',
default: 1
},
focus: {
detail: "节点hover态设置",
propertys: {
enabled: {
detail: '是否开启',
default: true
},
lineWidth: {
detail: 'hover后的边框大小',
default: 6
},
strokeAlpha: {
detail: 'hover后的边框透明度',
default: 0.2
},
fillAlpha: {
detail: 'hover后的背景透明度',
default: 0.8
}
}
},
select: {
detail: "节点选中态设置",
propertys: {
enabled: {
detail: '是否开启',
default: false
},
lineWidth: {
detail: '选中后的边框大小',
default: 8
},
strokeAlpha: {
detail: '选中后的边框透明度',
default: 0.4
},
fillAlpha: {
detail: '选中后的背景透明度',
default: 1
}
}
}
}
},
label: {
detail: '文本设置',
propertys: {
enabled: {
detail: '是否开启',
default: true
},
field: {
detail: '获取label的字段',
default: null
},
format: {
detail: 'label格式化处理函数',
default: function _default(txt) {
return txt;
}
},
fontSize: {
detail: 'label字体大小',
default: 13
},
fontColor: {
detail: '字体颜色',
default: '#fff'
}
}
}
};
}
}]);
}(_index.default);
_index.default.registerComponent(BubbleGraphs, 'graphs', 'bubble');
var _default2 = exports.default = BubbleGraphs;