UNPKG

chartx

Version:

Data Visualization Chart Library

636 lines (616 loc) 20 kB
"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 _numeral = _interopRequireDefault(require("numeral")); var _axis = _interopRequireDefault(require("./axis")); var _tools = require("../../utils/tools"); 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._; var Line = _canvax.default.Shapes.Line; var xAxis = exports.default = /*#__PURE__*/function (_Axis) { function xAxis(opt, data, _coord) { var _this; (0, _classCallCheck2.default)(this, xAxis); _this = _callSuper(this, xAxis, [opt, data.org]); _this.type = "xAxis"; _this._coord = _coord || {}; _this._title = null; //this.title对应的文本对象 _this._axisLine = null; _this._formatTextSection = []; //dataSection的值format后一一对应的值 _this._textElements = []; //_formatTextSection中每个文本对应的canvax.shape.Text对象 _this.pos = { x: 0, y: 0 }; _this.layoutData = []; //{x:100, value:'1000',visible:true} _this.sprite = null; _this.isH = false; //是否为横向转向的x轴 _.extend(true, _this, (0, _tools.getDefaultProps)(xAxis.defaultProps()), opt); _this.init(opt); return _this; } (0, _inherits2.default)(xAxis, _Axis); return (0, _createClass2.default)(xAxis, [{ key: "init", value: function init(opt) { this._setField(); this._initHandle(opt); this.sprite = new _canvax.default.Display.Sprite({ id: "xAxisSprite_" + new Date().getTime() }); this.rulesSprite = new _canvax.default.Display.Sprite({ id: "xRulesSprite_" + new Date().getTime() }); this.sprite.addChild(this.rulesSprite); } }, { key: "_initHandle", value: function _initHandle(opt) { var me = this; if (opt) { if (opt.isH && (!opt.label || opt.label.rotaion === undefined)) { //如果是横向直角坐标系图 this.label.rotation = 90; } ; } ; this.setDataSection(); if (this.layoutType == 'proportion' && this.useDataOrgToSection) { me.dataSection = _.uniq(me.dataSection.concat(_.flatten(this.dataOrg))).sort(function (a, b) { return a - b; }); } me._formatTextSection = []; me._textElements = []; _.each(me.dataSection, function (val, i) { me._formatTextSection[i] = me._getFormatText(val, i); //从_formatTextSection中取出对应的格式化后的文本 var txt = new _canvax.default.Display.Text(me._formatTextSection[i], { context: { fontSize: me.label.fontSize } }); me._textElements[i] = txt; }); if (this.label.rotation != 0) { //如果是旋转的文本,那么以右边为旋转中心点 this.label.textAlign = "right"; } ; this._getTitle(); this._setXAxisHeight(); } }, { key: "_setField", value: function _setField(field) { if (field) { this.field = field; } ; //xAxis的field只有一个值 this.field = _.flatten([this.field])[0]; } }, { key: "draw", value: function draw(opt) { //首次渲染从 直角坐标系组件中会传入 opt,包含了width,origin等, 所有这个时候才能计算layoutData opt && _.extend(true, this, opt); this.setAxisLength(this.width); this._trimXAxis(); this._widget(opt); this.setX(this.pos.x); this.setY(this.pos.y); } //配置和数据变化 }, { key: "resetData", value: function resetData(dataFrame, opt) { // if( _opt ){ // if( 'width' in _opt ){ // this.width = _opt.width; // } // if( 'pos' in _opt ){ // if( 'x' in _opt.pos ) this.setX( _opt.pos.x ); // if( 'y' in _opt.pos ) this.setY( _opt.pos.y ); // } // } opt && _.extend(true, this, opt); this._setField(dataFrame.field); this.resetDataOrg(dataFrame.org); this._initHandle(); this.draw(opt); } }, { key: "setX", value: function setX($n) { this.sprite.context.x = $n; this.pos.x = $n; } }, { key: "setY", value: function setY($n) { this.sprite.context.y = $n; this.pos.y = $n; } }, { key: "_getTitle", value: function _getTitle() { if (this.title.text) { if (!this._title) { this._title = new _canvax.default.Display.Text(this.title.text, { context: { fontSize: this.title.fontSize, textAlign: this.title.textAlign, //"center",//this.isH ? "center" : "left", textBaseline: this.title.textBaseline, //"middle", //this.isH ? "top" : "middle", fillStyle: this.title.fontColor, strokeStyle: this.title.strokeStyle, lineWidth: this.title.lineWidth, rotation: this.isH ? -180 : 0 } }); } else { this._title.resetText(this.title.text || ''); } } } }, { key: "_setXAxisHeight", value: function _setXAxisHeight() { //检测下文字的高等 var me = this; if (!me.enabled) { me.height = 0; } else { var _maxTextHeight = 0; if (this.label.enabled) { _.each(me.dataSection, function (val, i) { //从_formatTextSection中取出对应的格式化后的文本 var txt = me._textElements[i]; var textWidth = txt.getTextWidth(); var textHeight = txt.getTextHeight(); //let width = textWidth; //文本在外接矩形width var height = textHeight; //文本在外接矩形height if (!!me.label.rotation) { //有设置旋转 if (me.label.rotation == 90) { //width = textHeight; height = textWidth; } else { var sinR = Math.sin(Math.abs(me.label.rotation) * Math.PI / 180); //let cosR = Math.cos(Math.abs(me.label.rotation) * Math.PI / 180); height = parseInt(sinR * textWidth); //width = parseInt( cosR * textWidth ); } ; } ; _maxTextHeight = Math.max(_maxTextHeight, height); }); } ; this.height = _maxTextHeight + this.tickLine.lineLength + this.tickLine.distance + this.label.distance; if (this._title) { this.height += this._title.getTextHeight(); } ; } } }, { key: "getNodeInfoOfX", value: function getNodeInfoOfX(x) { var ind = this.getIndexOfPos(x); var val = this.getValOfInd(ind); //this.getValOfPos(x);// var pos = this.getPosOf({ ind: ind, val: val }); return this._getNodeInfo(ind, val, pos); } }, { key: "getNodeInfoOfVal", value: function getNodeInfoOfVal(val) { var ind = this.getIndexOfVal(val); var pos = this.getPosOf({ ind: ind, val: val }); return this._getNodeInfo(ind, val, pos); } }, { key: "_getNodeInfo", value: function _getNodeInfo(ind, val, pos) { var o = { ind: ind, value: val, text: this._getFormatText(val, ind), //text是 format 后的数据 x: pos, //这里不能直接用鼠标的x field: this.field, layoutType: this.layoutType }; return o; } }, { key: "_trimXAxis", value: function _trimXAxis() { var tmpData = []; var data = this.dataSection; for (var a = 0, al = data.length; a < al; a++) { var text = this._formatTextSection[a]; var txt = this._textElements[a]; var o = { ind: a, value: data[a], text: text, x: this.getPosOf({ val: data[a], ind: a }), textWidth: txt.getTextWidth(), field: this.field, visible: null //trimgrapsh的时候才设置 }; tmpData.push(o); } ; this.layoutData = tmpData; this._trimLayoutData(); return tmpData; } }, { key: "_getFormatText", value: function _getFormatText(value, i) { if (this.label.format) { //如果有单独给label配置format,就用label上面的配置 if (_.isFunction(this.label.format)) { value = this.label.format.apply(this, arguments); } if (typeof this.label.format == 'string') { value = (0, _numeral.default)(value).format(this.label.format); } } else { //否则用fieldConfig上面的 var config = this._coord.fieldsConfig[this.field]; if (config) { value = this._coord.getFormatValue(value, config, i); } } ; return value; } }, { key: "_widget", value: function _widget(opt) { var _this2 = this; var me = this; !opt && (opt = {}); if (!me.enabled) { me.height = 0; //width不能为0 return; } ; var arr = me.layoutData; var visibleInd = 0; var _loop = function _loop(a) { _.isFunction(me.filter) && me.filter({ layoutData: arr, index: a }); var o = arr[a]; if (!o.visible) { return 1; // continue } ; var x = o.x, y = me.tickLine.lineLength + me.tickLine.distance + me.label.distance; var _node = me.rulesSprite.getChildAt(visibleInd); var _getProp = function _getProp(prop) { var _prop = prop; if (_.isFunction(prop)) { _prop = prop.apply(_this2, [o, arr, a]); } ; return _prop; }; //文字 var textContext = { x: o._text_x || o.x, y: y, fillStyle: _getProp(_this2.label.fontColor), fontSize: _getProp(_this2.label.fontSize), rotation: -Math.abs(_this2.label.rotation), textAlign: _getProp(_this2.label.textAlign), lineHeight: _getProp(_this2.label.lineHeight), textBaseline: !!_this2.label.rotation ? "middle" : "top", globalAlpha: _getProp(_this2.label.alpha) }; if (!!_this2.label.rotation && _this2.label.rotation != 90) { textContext.x += 5; textContext.y += 3; } ; //tick line var tickLineContext = { x: x, y: _this2.tickLine.distance, end: { x: 0, y: _this2.tickLine.lineLength }, lineWidth: _this2.tickLine.lineWidth, strokeStyle: _this2.tickLine.strokeStyle }; var duration = 300; var delay = visibleInd * Math.min(1000 / arr.length, 25); if (!me.animation || opt.resize) { duration = 0; delay = 0; } ; if (_node) { if (_node._tickLine && me.tickLine.enabled) { _node._tickLine.animate(tickLineContext, { duration: duration, id: _node._tickLine.id }); } ; if (_node._txt && me.label.enabled) { _node._txt.animate(textContext, { duration: duration, id: _node._txt.id }); _node._txt.resetText(o.text || ''); } ; } else { _node = new _canvax.default.Display.Sprite({ id: "xNode" + visibleInd }); //新建line if (me.tickLine.enabled) { _node._tickLine = new Line({ id: "xAxis_tickline_" + visibleInd, context: tickLineContext }); _node.addChild(_node._tickLine); } ; //新建txt if (me.label.enabled) { _node._txt = new _canvax.default.Display.Text(o.text, { id: "xAxis_txt_" + visibleInd, context: textContext }); _node.addChild(_node._txt); // TODO 后续x轴的动画要换成真实的动画效果,从画布外面移进来 // if (me.animation && !opt.resize) { // _node._txt.context.y += 20; // _node._txt.context.globalAlpha = 0; // _node._txt.animate( { // y: textContext.y, // globalAlpha: 1 // }, { // duration: 500, // delay: delay, // id: _node._txt.id // }); // }; } me.rulesSprite.addChild(_node); } ; visibleInd++; }; for (var a = 0, al = arr.length; a < al; a++) { if (_loop(a)) continue; } ; //把sprite.children中多余的给remove掉 if (this.rulesSprite.children.length >= visibleInd) { for (var _al = visibleInd, pl = this.rulesSprite.children.length; _al < pl; _al++) { this.rulesSprite.getChildAt(_al).remove(); _al--, pl--; } ; } ; //轴线 if (this.axisLine.enabled) { var _axisLineCtx = { start: { x: 0, y: 0 }, end: { x: this.width, y: 0 }, lineWidth: this.axisLine.lineWidth, strokeStyle: this.axisLine.strokeStyle }; if (!this._axisLine) { var _axisLine = new Line({ context: _axisLineCtx }); this.sprite.addChild(_axisLine); this._axisLine = _axisLine; } else { this._axisLine.animate(_axisLineCtx); } ; } ; if (this._title) { this._title.context.y = this.height - this._title.getTextHeight() / 2; this._title.context.x = this.width / 2; this.sprite.addChild(this._title); } ; } }, { key: "_trimLayoutData", value: function _trimLayoutData() { var me = this; var arr = this.layoutData; var l = arr.length; if (!this.enabled || !l) return; // rule , peak, proportion if (me.layoutType == "proportion") { this._checkOver(); } ; if (me.layoutType == "peak") { //TODO: peak暂时沿用 _checkOver ,这是保险的万无一失的。 this._checkOver(); } ; if (me.layoutType == "rule") { this._checkOver(); } ; } }, { key: "_getRootPR", value: function _getRootPR() { //找到paddingRight,在最后一个文本右移的时候需要用到 var rootPaddingRight = 0; if (this._coord.app) { rootPaddingRight = this._coord.app.padding.right; } ; return rootPaddingRight; } }, { key: "_checkOver", value: function _checkOver() { var me = this; var arr = me.layoutData; var l = arr.length; var textAlign = me.label.textAlign; //如果用户设置不想要做重叠检测 if (!this.label.evade || me.trimLayout) { _.each(arr, function (layoutItem) { layoutItem.visible = true; }); if (me.trimLayout) { //如果用户有手动的 trimLayout ,那么就全部visible为true,然后调用用户自己的过滤程序 //trimLayout就事把arr种的每个元素的visible设置为true和false的过程 me.trimLayout(arr); } ; //要避免最后一个label绘制出去了 //首先找到最后一个visible的label var lastNode; for (var i = l - 1; i >= 0; i--) { if (lastNode) break; if (arr[i].visible) lastNode = arr[i]; } ; if (lastNode) { if (textAlign == "center" && lastNode.x + lastNode.textWidth / 2 > me.width) { lastNode._text_x = me.width - lastNode.textWidth / 2 + me._getRootPR(); } ; if (textAlign == "left" && lastNode.x + lastNode.textWidth > me.width) { lastNode._text_x = me.width - lastNode.textWidth; } ; } ; return; } ; function checkOver(i) { var curr = arr[i]; if (curr === undefined) { return; } ; curr.visible = true; for (var ii = i; ii < l - 1; ii++) { var next = arr[ii + 1]; var nextWidth = next.textWidth; var currWidth = curr.textWidth; //如果有设置rotation,那么就固定一个最佳可视单位width为35 暂定 if (!!me.label.rotation) { nextWidth = Math.min(nextWidth, 22); currWidth = Math.min(currWidth, 22); } ; //默认left var next_left_x = next.x; //下个节点的起始 var curr_right_x = curr.x + currWidth; //当前节点的终点 if (textAlign == "center") { next_left_x = next.x - nextWidth / 2; curr_right_x = curr.x + currWidth / 2; } ; if (textAlign == "right") { next_left_x = next.x - nextWidth; curr_right_x = curr.x; } ; if (ii == l - 2) { if (next_left_x + nextWidth > me.width + me._getRootPR()) { //只有最后一个溢出了,才需要检测 //next是最后一个 if (textAlign == "center" && next.x + nextWidth / 2 > me.width) { next_left_x = me.width - nextWidth; next._text_x = me.width - nextWidth / 2 + me._getRootPR(); } if (textAlign == "left" && next.x + nextWidth > me.width) { next_left_x = me.width - nextWidth; next._text_x = me.width - nextWidth; } } ; } ; //必须要有1px的间隔 if (next_left_x - curr_right_x < 1) { if (ii == l - 2) { //最后一个的话,反把前面的给hide next.visible = true; curr.visible = false; return; } else { next.visible = false; } } else { checkOver(ii + 1); break; } } ; } ; checkOver(0); } }], [{ key: "defaultProps", value: function defaultProps() { return { useDataOrgToSection: { detail: '在layoutType为 proportion 的时候可以配置', documentation: '', default: false } }; } }]); }(_axis.default);