UNPKG

chartx

Version:

Data Visualization Chart Library

503 lines (496 loc) 17.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); 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 _index = _interopRequireDefault(require("../index")); var force = _interopRequireWildcard(require("d3-force")); var _tools = require("../../../utils/tools"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } 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; })(); } //import * as force from "../../../layout/force/index"; var _ = _canvax.default._, event = _canvax.default.event; var Circle = _canvax.default.Shapes.Circle; var Text = _canvax.default.Display.Text; var Line = _canvax.default.Shapes.Line; var Force = /*#__PURE__*/function (_GraphsBase) { function Force(opt, app) { var _this; (0, _classCallCheck2.default)(this, Force); _this = _callSuper(this, Force, [opt, app]); _this.type = "force"; _.extend(true, _this, (0, _tools.getDefaultProps)(Force.defaultProps()), opt); _this.init(); return _this; } (0, _inherits2.default)(Force, _GraphsBase); return (0, _createClass2.default)(Force, [{ key: "init", value: function init() { this.nodesSp = new _canvax.default.Display.Sprite({ id: "nodesSp" }); this.edgesSp = new _canvax.default.Display.Sprite({ id: "edgesSp" }); this.graphsSp = new _canvax.default.Display.Sprite({ id: "graphsSp" }); this.graphsSp.addChild(this.edgesSp); this.graphsSp.addChild(this.nodesSp); this.sprite.addChild(this.graphsSp); } }, { key: "draw", value: function draw(opt) { !opt && (opt = {}); _.extend(true, this, opt); this.data = opt.data || this._initData(); this.widget(); this.fire("complete"); } }, { key: "_initData", value: function _initData() { var _this2 = this; //和关系图那边保持data格式的统一 var data = { nodes: [ //{ type,key,label,ctype,width,height,x,y } ], edges: [ //{ type,key[],label,ctype,width,height,x,y } ], size: { width: this.app.width, height: this.app.height } }; var _nodeMap = {}; var nodeValMin = 0, nodeValMax = 0, lineValMin = 0, lineValMax = 0; for (var i = 0; i < this.dataFrame.length; i++) { var rowData = this.dataFrame.getRowDataAt(i); var fields = _.flatten([(rowData[this.keyField] + "").split(",")]); var label = this._getContent(rowData); var key = fields.length == 1 ? fields[0] : fields; var value = rowData[this.field]; var element = new _canvax.default.Display.Sprite({ id: "nodeSp_" + key }); this.graphsSp.addChild(element); var node = { type: "force", field: this.field, iNode: i, rowData: rowData, key: key, value: value, label: label, //下面三个属性在_setElementAndSize中设置 element: element, //外面传的layout数据可能没有element,widget的时候要检测下 width: null, height: null, //radius : 1, //默认为1 //distance: 20, //如果是 //这个在layout的时候设置 x: null, y: null, shapeType: null, //如果是edge,要填写这两节点 source: null, target: null }; //_.extend(node, this._getElementAndSize(node)); if (fields.length == 1) { node.shapeType = this.getProp(this.node.shapeType, node); data.nodes.push(node); _nodeMap[node.key] = node; if (value != undefined) { nodeValMin = Math.min(nodeValMin, value); nodeValMax = Math.max(nodeValMax, value); } } else { node.shapeType = "line"; data.edges.push(node); if (value != undefined) { lineValMin = Math.min(lineValMin, value); lineValMax = Math.max(lineValMax, value); } } ; } ; this.nodeValMin = nodeValMin; this.nodeValMax = nodeValMax; this.lineValMin = lineValMin; this.lineValMax = lineValMax; data.nodes.forEach(function (node) { //计算 node的 半径 width height 和 style等 node.radius = _this2.node.radius ? _this2.getProp(_this2.node.radius, node) : _this2._getNodeRadius(node); node.width = node.height = node.radius * 2; }); data.edges.forEach(function (edge) { var keys = edge.key; edge.source = _nodeMap[keys[0]]; edge.target = _nodeMap[keys[1]]; edge.distance = _this2.line.distance ? _this2.getProp(_this2.node.distance, edge) : _this2._getLineDistance(edge); }); return data; } //this.node.radius为null的时候 内部默认的计算radius的方法 }, { key: "_getNodeRadius", value: function _getNodeRadius(nodeData) { var val = nodeData.value; var radius = this.node.radiusMin; if (val) { radius += (this.node.radiusMax - this.node.radiusMin) / (this.nodeValMax - this.nodeValMin) * val; } return parseInt(radius); } //this.line.distance 为null的时候 内部默认的计算 distance 的方法 }, { key: "_getLineDistance", value: function _getLineDistance(nodeData) { var val = nodeData.value; var distance = this.line.distanceMin; if (val) { distance += (this.line.distanceMax - this.line.distanceMin) / (this.lineValMax - this.lineValMin) * val; } return parseInt(distance); } }, { key: "widget", value: function widget() { var _this3 = this; var me = this; var keyField = this.keyField; var field = this.field; var links = this.data.edges.map(function (d) { //source: "Napoleon", target: "Myriel", value: 1 return { source: d.source[keyField], target: d.target[keyField], value: d.rowData[field], nodeData: d }; }); var nodes = this.data.nodes.map(function (d) { var node = Object.create(d); node.id = d.key; node.nodeData = d; return node; }); var _this$data$size = this.data.size, width = _this$data$size.width, height = _this$data$size.height; var simulation = force.forceSimulation(nodes).force("link", force.forceLink(links).id(function (d) { return d.id; }).distance(function (edge, edgeIndex, edges) { var distance = edge.nodeData.distance; var distanceNodes = edge.source.nodeData.radius + edge.target.nodeData.radius; return Math.max(distance, distanceNodes); })).force("charge", force.forceManyBody().distanceMin(this.line.distanceMin).distanceMax(this.line.distanceMax).strength(this.node.strength)) //节点间作用力 .force("center", force.forceCenter(width / 2, height / 2)).force('collide', force.forceCollide().radius(function (node, nodeIndex, nodes) { return node.nodeData.radius; })).force("x", force.forceX()).force("y", force.forceY()).alpha(0.5); nodes.forEach(function (node) { var fillStyle = me.getProp(me.node.fillStyle, node.nodeData); var strokeStyle = me.getProp(me.node.strokeStyle, node.nodeData); var lineWidth = me.getProp(me.node.lineWidth, node.nodeData); var nodeAlpha = me.getProp(me.node.nodeAlpha, node.nodeData); //写回nodeData里面,tips等地方需要 node.nodeData.fillStyle = fillStyle; var r = node.nodeData.radius; var _node = new Circle({ context: { r: r, fillStyle: fillStyle, strokeStyle: strokeStyle, lineWidth: lineWidth, globalAlpha: nodeAlpha, cursor: 'pointer' } }); node.nodeData.element.addChild(_node); _node.nodeData = node.nodeData; _node.on(event.types.get(), function (e) { e.eventInfo = { trigger: 'this.node', nodes: [this.nodeData] }; me.app.fire(e.type, e); }); var labelFontSize = me.getProp(me.label.fontSize, node.nodeData); var labelFontColor = me.getProp(me.label.fontColor, node.nodeData); var labelTextBaseline = me.getProp(me.label.textBaseline, node.nodeData); var labelTextAlign = me.getProp(me.label.textAlign, node.nodeData); var _label = new Text(node.nodeData.label, { context: { fontSize: labelFontSize, fillStyle: labelFontColor, textBaseline: labelTextBaseline, textAlign: labelTextAlign, globalAlpha: 0.7 } }); node.nodeData.element.addChild(_label); }); links.forEach(function (link) { var lineWidth = me.getProp(me.line.lineWidth, link.nodeData); var strokeStyle = me.getProp(me.line.strokeStyle, link.nodeData); var lineType = me.getProp(me.line.lineType, link.nodeData); var lineAlpha = me.getProp(me.line.lineAlpha, link.nodeData); link.nodeData.strokeStyle = strokeStyle; var _line = new Line({ context: { lineWidth: lineWidth, strokeStyle: strokeStyle, lineType: lineType, start: { x: 0, y: 0 }, end: { x: 0, y: 0 }, globalAlpha: lineAlpha } }); _this3.edgesSp.addChild(_line); link.line = _line; }); simulation.on("tick", function () { if (simulation.alpha() <= 0.05) { simulation.stop(); return; } ; nodes.forEach(function (node) { var elemCtx = node.nodeData.element.context; if (elemCtx) { elemCtx.x = node.x; elemCtx.y = node.y; } ; }); links.forEach(function (link) { var lineCtx = link.line.context; if (lineCtx) { lineCtx.start.x = link.source.x; lineCtx.start.y = link.source.y; lineCtx.end.x = link.target.x; lineCtx.end.y = link.target.y; } }); }); } /** * 字符串是否含有html标签的检测 */ }, { key: "_checkHtml", value: function _checkHtml(str) { var reg = /<[^>]+>/g; return reg.test(str); } }, { key: "_getContent", value: function _getContent(rowData) { var me = this; var _c; //this.label; if (this._isField(this.label.field)) { _c = rowData[this.label.field]; } ; if (me.label.format) { if (_.isFunction(me.label.format)) { _c = me.label.format.apply(this, [_c, rowData]); } } else { //否则用fieldConfig上面的 var _coord = me.app.getComponent({ name: 'coord' }); var fieldConfig = _coord.getFieldConfig(me.keyField); if (fieldConfig) { _c = fieldConfig.getFormatValue(_c); } ; } ; return _c; } }, { key: "_isField", value: function _isField(str) { return ~this.dataFrame.fields.indexOf(str); } }, { key: "getNodesAt", value: function getNodesAt() {} }, { key: "getProp", value: function getProp(prop, nodeData) { var _prop = prop; if (this._isField(prop) && nodeData.rowData) { _prop = nodeData.rowData[prop]; } else { if (_.isArray(prop)) { _prop = prop[nodeData.iNode]; } ; if (_.isFunction(prop)) { _prop = prop.apply(this, [nodeData]); } ; } ; return _prop; } }], [{ key: "defaultProps", value: function defaultProps() { return { keyField: { detail: 'key字段', default: '' }, field: { detail: 'value字段,node,link都公用这个字段', default: '' }, node: { detail: '单个节点的配置', propertys: { shapeType: { detail: '节点图形', default: 'circle' }, radiusMin: { detail: '最小节点半径', default: 6 }, radiusMax: { detail: '最大节点半径', default: 30 }, radius: { detail: '节点半径', default: null }, fillStyle: { detail: '节点背景色', default: '#acdf7d' }, strokeStyle: { detail: '描边颜色', default: '#e5e5e5' }, lineWidth: { detail: '描边线宽', default: 0 }, nodeAlpha: { detail: '节点透明度', default: 1 }, strength: { detail: '节点之间作用力', default: -300 } } }, line: { detail: '两个节点连线配置', propertys: { lineWidth: { detail: '线宽', default: 1 }, strokeStyle: { detail: '连线的颜色', default: '#e5e5e5' }, lineType: { detail: '连线样式(虚线等)', default: 'solid' }, lineAlpha: { detail: '连线透明度', default: 0.6 }, distanceMin: { detail: '最小连线距离', default: 30 }, distanceMax: { detail: '最大连线距离', default: 200 }, distance: { detail: '连线距离', default: null }, arrow: { detail: '是否有箭头', default: true } } }, label: { detail: '节点内容配置', propertys: { field: { detail: '内容字段', default: 'label' }, fontColor: { detail: '内容文本颜色', default: '#666' }, format: { detail: '内容格式化处理函数', default: null }, textAlign: { detail: "textAlign", default: "center" }, textBaseline: { detail: 'textBaseline', default: "middle" } } } }; } }, { key: "polyfill", value: function polyfill(opt) { if (opt.valueField) { //20220304 所有的graph都统一一个field opt.field = opt.valueField; delete opt.valueField; } return opt; } }]); }(_index.default); _index.default.registerComponent(Force, 'graphs', 'force'); var _default = exports.default = Force;