649 lines
16 KiB
JavaScript
649 lines
16 KiB
JavaScript
function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
||
|
||
function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
|
||
|
||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
||
|
||
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
|
||
|
||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
||
|
||
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
|
||
|
||
var Component = require('../component');
|
||
|
||
var Util = require('../util');
|
||
|
||
var Grid = require('./grid');
|
||
|
||
var Label = require('../label/base');
|
||
|
||
var _require = require('../const'),
|
||
FONT_FAMILY = _require.FONT_FAMILY;
|
||
|
||
var Axis = /*#__PURE__*/function (_Component) {
|
||
_inheritsLoose(Axis, _Component);
|
||
|
||
var _super = _createSuper(Axis);
|
||
|
||
function Axis() {
|
||
return _Component.apply(this, arguments) || this;
|
||
}
|
||
|
||
var _proto = Axis.prototype;
|
||
|
||
_proto.getDefaultCfg = function getDefaultCfg() {
|
||
var cfg = _Component.prototype.getDefaultCfg.call(this);
|
||
|
||
return Util.mix({}, cfg, {
|
||
/**
|
||
* 用于动画,唯一标识的 id
|
||
* @type {[type]}
|
||
*/
|
||
_id: null,
|
||
zIndex: 4,
|
||
|
||
/**
|
||
* 坐标轴上的坐标点
|
||
* @type {Array}
|
||
*/
|
||
ticks: null,
|
||
|
||
/**
|
||
* 坐标轴线的配置信息,如果设置成null,则不显示轴线
|
||
* @type {Object}
|
||
*/
|
||
line: null,
|
||
|
||
/**
|
||
* 坐标轴刻度线的配置,如果设置成null,则不显示刻度线
|
||
* @type {Object}
|
||
*/
|
||
tickLine: null,
|
||
|
||
/**
|
||
* 次刻度线个数配置
|
||
* @type {Number}
|
||
*/
|
||
subTickCount: 0,
|
||
|
||
/**
|
||
* 次刻度线样式配置
|
||
* @type {Object}
|
||
*/
|
||
subTickLine: null,
|
||
|
||
/**
|
||
* 网格线配置,如果值为 null,则不显示
|
||
* @type {Object}
|
||
*/
|
||
grid: null,
|
||
|
||
/**
|
||
* 坐标轴文本配置
|
||
* @type {Object}
|
||
*/
|
||
label: {
|
||
offset: 0,
|
||
offsetX: 0,
|
||
offsetY: 0,
|
||
textStyle: {},
|
||
// 坐标轴文本样式
|
||
autoRotate: true,
|
||
autoHide: false,
|
||
formatter: null // 坐标轴文本格式化回调函数
|
||
|
||
},
|
||
labelItems: [],
|
||
|
||
/**
|
||
* 坐标轴标题配置
|
||
* @type {Object}
|
||
*/
|
||
title: {
|
||
autoRotate: true,
|
||
// 文本是否自动旋转
|
||
textStyle: {} // 坐标轴标题样式
|
||
|
||
},
|
||
autoPaint: true
|
||
});
|
||
};
|
||
|
||
_proto.beforeRender = function beforeRender() {
|
||
var self = this;
|
||
var title = self.get('title');
|
||
var label = self.get('label');
|
||
var grid = self.get('grid');
|
||
|
||
if (title) {
|
||
self.set('title', Util.deepMix({
|
||
autoRotate: true,
|
||
textStyle: {
|
||
fontSize: 12,
|
||
fill: '#ccc',
|
||
textBaseline: 'middle',
|
||
fontFamily: FONT_FAMILY,
|
||
textAlign: 'center'
|
||
},
|
||
offset: 48
|
||
}, title));
|
||
}
|
||
|
||
if (label) {
|
||
self.set('label', Util.deepMix({
|
||
autoRotate: true,
|
||
autoHide: true,
|
||
textStyle: {
|
||
fontSize: 12,
|
||
fill: '#ccc',
|
||
textBaseline: 'middle',
|
||
fontFamily: FONT_FAMILY
|
||
},
|
||
offset: 10
|
||
}, label));
|
||
}
|
||
|
||
if (grid) {
|
||
self.set('grid', Util.deepMix({
|
||
lineStyle: {
|
||
lineWidth: 1,
|
||
stroke: '#C0D0E0'
|
||
}
|
||
}, grid));
|
||
}
|
||
};
|
||
|
||
_proto.render = function render() {
|
||
var self = this;
|
||
self.beforeRender();
|
||
var labelCfg = self.get('label');
|
||
|
||
if (labelCfg) {
|
||
self.renderLabels();
|
||
}
|
||
|
||
if (self.get('autoPaint')) {
|
||
self.paint();
|
||
}
|
||
|
||
if (!Util.isNil(self.get('title'))) {
|
||
self.renderTitle();
|
||
}
|
||
|
||
self.get('group').sort();
|
||
};
|
||
|
||
_proto.renderLabels = function renderLabels() {
|
||
var self = this;
|
||
var group = self.get('group');
|
||
var labelCfg = self.get('label');
|
||
var labelRenderer = new Label({
|
||
name: 'axis-label'
|
||
});
|
||
self.set('labelRenderer', labelRenderer);
|
||
labelRenderer.set('labelCfg', labelCfg);
|
||
var cfgs2copy = ['formatter', 'htmlTemplate', 'labelLine', 'textStyle', 'useHtml'];
|
||
Util.each(cfgs2copy, function (cfg) {
|
||
if (labelCfg[cfg]) {
|
||
labelRenderer.set(cfg, labelCfg[cfg]);
|
||
}
|
||
});
|
||
labelRenderer.set('coord', self.get('coord'));
|
||
labelRenderer.set('group', group.addGroup());
|
||
labelRenderer.set('canvas', self.get('canvas'));
|
||
};
|
||
|
||
_proto._parseTicks = function _parseTicks(ticks) {
|
||
ticks = ticks || [];
|
||
var ticksLength = ticks.length;
|
||
|
||
for (var i = 0; i < ticksLength; i++) {
|
||
var item = ticks[i];
|
||
|
||
if (!Util.isObject(item)) {
|
||
ticks[i] = this.parseTick(item, i, ticksLength);
|
||
}
|
||
}
|
||
|
||
this.set('ticks', ticks);
|
||
return ticks;
|
||
};
|
||
|
||
_proto._addTickItem = function _addTickItem(index, point, length, type) {
|
||
if (type === void 0) {
|
||
type = '';
|
||
}
|
||
|
||
var tickItems = this.get('tickItems');
|
||
var subTickItems = this.get('subTickItems');
|
||
var end = this.getTickEnd(point, length, index);
|
||
var cfg = {
|
||
x1: point.x,
|
||
y1: point.y,
|
||
x2: end.x,
|
||
y2: end.y
|
||
};
|
||
|
||
if (!tickItems) {
|
||
tickItems = [];
|
||
}
|
||
|
||
if (!subTickItems) {
|
||
subTickItems = [];
|
||
}
|
||
|
||
if (type === 'sub') {
|
||
subTickItems.push(cfg);
|
||
} else {
|
||
tickItems.push(cfg);
|
||
}
|
||
|
||
this.set('tickItems', tickItems);
|
||
this.set('subTickItems', subTickItems);
|
||
};
|
||
|
||
_proto._renderLine = function _renderLine() {
|
||
var self = this;
|
||
var lineCfg = self.get('line');
|
||
var path;
|
||
|
||
if (lineCfg) {
|
||
path = self.getLinePath();
|
||
lineCfg = Util.mix({
|
||
path: path
|
||
}, lineCfg);
|
||
var group = self.get('group');
|
||
var lineShape = group.addShape('path', {
|
||
attrs: lineCfg
|
||
});
|
||
lineShape.name = 'axis-line';
|
||
self.get('appendInfo') && lineShape.setSilent('appendInfo', self.get('appendInfo'));
|
||
self.set('lineShape', lineShape);
|
||
}
|
||
};
|
||
|
||
_proto._processCatTicks = function _processCatTicks() {
|
||
var self = this;
|
||
var labelCfg = self.get('label');
|
||
var tickLineCfg = self.get('tickLine');
|
||
var ticks = self.get('ticks');
|
||
ticks = self._parseTicks(ticks);
|
||
|
||
var new_ticks = self._getNormalizedTicks(ticks);
|
||
|
||
for (var i = 0; i < new_ticks.length; i += 3) {
|
||
var p = self.getTickPoint(new_ticks[i]);
|
||
var p0 = self.getTickPoint(new_ticks[i + 1]);
|
||
var p1 = self.getTickPoint(new_ticks[i + 2]);
|
||
var index = Math.floor(i / 3);
|
||
var tick = ticks[index];
|
||
|
||
if (tickLineCfg) {
|
||
if (index === 0) {
|
||
self._addTickItem(index, p0, tickLineCfg.length);
|
||
}
|
||
|
||
self._addTickItem(index, p1, tickLineCfg.length);
|
||
}
|
||
|
||
if (labelCfg) {
|
||
self.addLabel(tick, p, index);
|
||
}
|
||
}
|
||
};
|
||
|
||
_proto._getNormalizedTicks = function _getNormalizedTicks(ticks) {
|
||
var tickSeg = 0;
|
||
|
||
if (ticks.length > 1) {
|
||
tickSeg = (ticks[1].value - ticks[0].value) / 2;
|
||
}
|
||
|
||
var points = [];
|
||
|
||
for (var i = 0; i < ticks.length; i++) {
|
||
var tick = ticks[i];
|
||
var p = tick.value;
|
||
var p0 = tick.value - tickSeg;
|
||
var p1 = tick.value + tickSeg;
|
||
points.push(p, p0, p1);
|
||
}
|
||
|
||
var range = Util.arrayUtil.getRange(points);
|
||
return points.map(function (p) {
|
||
var norm = (p - range.min) / (range.max - range.min);
|
||
return norm;
|
||
});
|
||
};
|
||
|
||
_proto.addLabel = function addLabel(tick, point, index) {
|
||
var self = this;
|
||
var labelItems = self.get('labelItems');
|
||
var labelRenderer = self.get('labelRenderer');
|
||
var label = Util.deepMix({}, self.get('label'));
|
||
var rst;
|
||
|
||
if (labelRenderer) {
|
||
var offset = self.get('_labelOffset');
|
||
|
||
if (!Util.isNil(self.get('label').offset)) {
|
||
offset = self.get('label').offset;
|
||
}
|
||
|
||
var vector = self.getSideVector(offset, point, index);
|
||
point = {
|
||
x: point.x + vector[0] + label.offsetX,
|
||
y: point.y + vector[1] + label.offsetY
|
||
};
|
||
label.text = tick.text;
|
||
label.x = point.x;
|
||
label.y = point.y;
|
||
label.point = point;
|
||
label.textAlign = self.getTextAnchor(vector);
|
||
|
||
if (point.rotate) {
|
||
label.rotate = point.rotate;
|
||
}
|
||
|
||
labelItems.push(label);
|
||
}
|
||
|
||
return rst;
|
||
};
|
||
|
||
_proto._processTicks = function _processTicks() {
|
||
var self = this;
|
||
var labelCfg = self.get('label');
|
||
var subTickCount = self.get('subTickCount');
|
||
var tickLineCfg = self.get('tickLine');
|
||
var ticks = self.get('ticks');
|
||
ticks = self._parseTicks(ticks);
|
||
Util.each(ticks, function (tick, index) {
|
||
var tickPoint = self.getTickPoint(tick.value, index);
|
||
|
||
if (tickLineCfg) {
|
||
self._addTickItem(index, tickPoint, tickLineCfg.length);
|
||
}
|
||
|
||
if (labelCfg) {
|
||
self.addLabel(tick, tickPoint, index);
|
||
}
|
||
});
|
||
|
||
if (subTickCount) {
|
||
// 如果有设置次级分点,添加次级tick
|
||
var subTickLineCfg = self.get('subTickLine');
|
||
Util.each(ticks, function (tick, index) {
|
||
if (index > 0) {
|
||
var diff = tick.value - ticks[index - 1].value;
|
||
diff = diff / (self.get('subTickCount') + 1);
|
||
|
||
for (var i = 1; i <= subTickCount; i++) {
|
||
var subTick = {
|
||
text: '',
|
||
value: index ? ticks[index - 1].value + i * diff : i * diff
|
||
};
|
||
var tickPoint = self.getTickPoint(subTick.value);
|
||
var subTickLength = void 0;
|
||
|
||
if (subTickLineCfg && subTickLineCfg.length) {
|
||
subTickLength = subTickLineCfg.length;
|
||
} else {
|
||
subTickLength = parseInt(tickLineCfg.length * (3 / 5), 10);
|
||
}
|
||
|
||
self._addTickItem(i - 1, tickPoint, subTickLength, 'sub');
|
||
}
|
||
}
|
||
});
|
||
}
|
||
};
|
||
|
||
_proto._addTickLine = function _addTickLine(ticks, lineCfg) {
|
||
var self = this;
|
||
var cfg = Util.mix({}, lineCfg);
|
||
var path = [];
|
||
Util.each(ticks, function (item) {
|
||
path.push(['M', item.x1, item.y1]);
|
||
path.push(['L', item.x2, item.y2]);
|
||
});
|
||
delete cfg.length;
|
||
cfg.path = path;
|
||
var group = self.get('group');
|
||
var tickShape = group.addShape('path', {
|
||
attrs: cfg
|
||
});
|
||
tickShape.name = 'axis-ticks';
|
||
tickShape._id = self.get('_id') + '-ticks';
|
||
tickShape.set('coord', self.get('coord'));
|
||
self.get('appendInfo') && tickShape.setSilent('appendInfo', self.get('appendInfo'));
|
||
};
|
||
|
||
_proto._renderTicks = function _renderTicks() {
|
||
var self = this;
|
||
var tickItems = self.get('tickItems');
|
||
var subTickItems = self.get('subTickItems');
|
||
|
||
if (!Util.isEmpty(tickItems)) {
|
||
var tickLineCfg = self.get('tickLine');
|
||
|
||
self._addTickLine(tickItems, tickLineCfg);
|
||
}
|
||
|
||
if (!Util.isEmpty(subTickItems)) {
|
||
var subTickLineCfg = self.get('subTickLine') || self.get('tickLine');
|
||
|
||
self._addTickLine(subTickItems, subTickLineCfg);
|
||
}
|
||
};
|
||
|
||
_proto._renderGrid = function _renderGrid() {
|
||
var grid = this.get('grid');
|
||
|
||
if (!grid) {
|
||
return;
|
||
}
|
||
|
||
grid.coord = this.get('coord');
|
||
grid.appendInfo = this.get('appendInfo');
|
||
var group = this.get('group');
|
||
this.set('gridGroup', group.addGroup(Grid, grid));
|
||
};
|
||
|
||
_proto._renderLabels = function _renderLabels() {
|
||
var self = this;
|
||
var labelRenderer = self.get('labelRenderer');
|
||
var labelItems = self.get('labelItems');
|
||
|
||
if (labelRenderer) {
|
||
labelRenderer.set('items', labelItems);
|
||
|
||
labelRenderer._dryDraw();
|
||
}
|
||
};
|
||
|
||
_proto.paint = function paint() {
|
||
var self = this;
|
||
var tickLineCfg = self.get('tickLine');
|
||
var alignWithLabel = true;
|
||
|
||
if (tickLineCfg && tickLineCfg.hasOwnProperty('alignWithLabel')) {
|
||
alignWithLabel = tickLineCfg.alignWithLabel;
|
||
}
|
||
|
||
self._renderLine();
|
||
|
||
var type = self.get('type');
|
||
var isCat = type === 'cat' || type === 'timeCat';
|
||
|
||
if (isCat && alignWithLabel === false) {
|
||
self._processCatTicks();
|
||
} else {
|
||
self._processTicks();
|
||
}
|
||
|
||
self._renderTicks();
|
||
|
||
self._renderGrid();
|
||
|
||
self._renderLabels();
|
||
|
||
var labelCfg = this.get('label');
|
||
|
||
if (labelCfg && labelCfg.autoRotate) {
|
||
self.autoRotateLabels();
|
||
}
|
||
|
||
if (labelCfg && labelCfg.autoHide) {
|
||
self.autoHideLabels();
|
||
}
|
||
};
|
||
|
||
_proto.parseTick = function parseTick(tick, index, length) {
|
||
return {
|
||
text: tick,
|
||
value: index / (length - 1)
|
||
};
|
||
};
|
||
|
||
_proto.getTextAnchor = function getTextAnchor(vector) {
|
||
var ratio = Math.abs(vector[1] / vector[0]);
|
||
var align;
|
||
|
||
if (ratio >= 1) {
|
||
// 上面或者下面
|
||
align = 'center';
|
||
} else {
|
||
if (vector[0] > 0) {
|
||
// 右侧
|
||
align = 'start';
|
||
} else {
|
||
// 左侧
|
||
align = 'end';
|
||
}
|
||
}
|
||
|
||
return align;
|
||
};
|
||
|
||
_proto.getMaxLabelWidth = function getMaxLabelWidth(labelRenderer) {
|
||
var labels = labelRenderer.getLabels();
|
||
var max = 0;
|
||
Util.each(labels, function (label) {
|
||
var bbox = label.getBBox();
|
||
var width = bbox.width;
|
||
|
||
if (max < width) {
|
||
max = width;
|
||
}
|
||
});
|
||
return max;
|
||
};
|
||
|
||
_proto.getMaxLabelHeight = function getMaxLabelHeight(labelRenderer) {
|
||
var labels = labelRenderer.getLabels();
|
||
var max = 0;
|
||
Util.each(labels, function (label) {
|
||
var bbox = label.getBBox();
|
||
var height = bbox.height;
|
||
|
||
if (max < height) {
|
||
max = height;
|
||
}
|
||
});
|
||
return max;
|
||
};
|
||
|
||
_proto.destroy = function destroy() {
|
||
var self = this;
|
||
|
||
if (!self.destroyed) {
|
||
var gridGroup = self.get('gridGroup');
|
||
gridGroup && gridGroup.remove();
|
||
var labelRenderer = this.get('labelRenderer');
|
||
labelRenderer && labelRenderer.destroy();
|
||
var group = self.get('group');
|
||
group.destroy();
|
||
|
||
_Component.prototype.destroy.call(this); // 要最后调用 super.destroy 否则 get 属性会无效
|
||
|
||
}
|
||
};
|
||
|
||
_proto.clear = function clear() {
|
||
var self = this;
|
||
var group = self.get('group');
|
||
|
||
if (!group.get('destroyed') && group.get('children').length) {
|
||
var gridGroup = self.get('gridGroup');
|
||
gridGroup && gridGroup.clear();
|
||
var labelRenderer = this.get('labelRenderer');
|
||
labelRenderer && labelRenderer.clear();
|
||
|
||
var _group = self.get('group');
|
||
|
||
_group.clear();
|
||
}
|
||
}
|
||
/**
|
||
* 旋转文本
|
||
* @abstract
|
||
* @return {[type]} [description]
|
||
*/
|
||
;
|
||
|
||
_proto.autoRotateLabels = function autoRotateLabels() {}
|
||
/**
|
||
* 文本自动防遮罩
|
||
* @abstract
|
||
* @return {[type]} [description]
|
||
*/
|
||
;
|
||
|
||
_proto.autoHideLabels = function autoHideLabels() {}
|
||
/**
|
||
* 渲染标题
|
||
* @abstract
|
||
* @return {[type]} [description]
|
||
*/
|
||
;
|
||
|
||
_proto.renderTitle = function renderTitle() {}
|
||
/**
|
||
* 获取坐标轴线的 path
|
||
* @abstract
|
||
* @return {[type]} [description]
|
||
*/
|
||
;
|
||
|
||
_proto.getLinePath = function getLinePath() {}
|
||
/**
|
||
* 获取 tick 在画布上的位置
|
||
* @abstract
|
||
* @return {[type]} [description]
|
||
*/
|
||
;
|
||
|
||
_proto.getTickPoint = function getTickPoint() {}
|
||
/**
|
||
* 获取标示坐标点的线的终点
|
||
* @abstract
|
||
* @return {[type]} [description]
|
||
*/
|
||
;
|
||
|
||
_proto.getTickEnd = function getTickEnd() {}
|
||
/**
|
||
* 获取距离坐标轴的向量
|
||
* @abstract
|
||
* @return {[type]} [description]
|
||
*/
|
||
;
|
||
|
||
_proto.getSideVector = function getSideVector() {};
|
||
|
||
return Axis;
|
||
}(Component);
|
||
|
||
module.exports = Axis; |