提交 d42d48c0 编写于 作者: L lang

Improve markLine and some other tweak

上级 f7fb732e
/**
* @module echarts/component/marker/LineDraw
*/
define(function (require) {
var graphic = require('../../util/graphic');
var numberUtil = require('../../util/number');
var zrUtil = require('zrender/core/util');
var symbolUtil = require('../../util/symbol');
var vector = require('zrender/core/vector');
function tangentRotation(p1, p2) {
return -Math.PI / 2 - Math.atan2(
p2[1] - p1[1], p2[0] - p1[0]
);
}
/**
* @inner
*/
function createSymbol(data, idx) {
var color = data.getItemVisual(idx, 'color');
var symbolType = data.getItemVisual(idx, 'symbol');
var symbolSize = data.getItemVisual(idx, 'symbolSize');
if (symbolType === 'none') {
return;
}
if (!zrUtil.isArray(symbolSize)) {
symbolSize = [symbolSize, symbolSize];
}
var symbolPath = symbolUtil.createSymbol(
symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2,
symbolSize[0], symbolSize[1], color
);
return symbolPath;
}
function isSymbolArrow(symbol) {
return symbol.type === 'symbol' && symbol.shape.symbolType === 'arrow';
}
function updateSymbolBeforeLineUpdate () {
var lineGroup = this;
var line = lineGroup.childOfName('line');
var symbolFrom = lineGroup.childOfName('fromSymbol');
var symbolTo = lineGroup.childOfName('toSymbol');
var label = lineGroup.childOfName('label');
var lineShape = line.shape;
var fromPos = [lineShape.x1, lineShape.y1];
var toPos = [lineShape.x2, lineShape.y2];
var d = vector.sub([], toPos, fromPos);
vector.normalize(d, d);
if (symbolFrom) {
symbolFrom.attr('position', fromPos);
// Rotate the arrow
// FIXME Hard coded ?
if (isSymbolArrow(symbolTo)) {
symbolTo.attr('rotation', tangentRotation(fromPos, toPos));
}
}
if (symbolTo) {
symbolTo.attr('position', toPos);
if (isSymbolArrow(symbolFrom)) {
symbolFrom.attr('rotation', tangentRotation(toPos, fromPos));
}
}
label.attr('position', toPos);
var textPosition;
var textAlign;
var textBaseline;
// End
if (label.__position === 'end') {
textPosition = [d[0] * 5 + toPos[0], d[1] * 5 + toPos[1]];
textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center');
textBaseline = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle');
}
// Start
else {
textPosition = [-d[0] * 5 + fromPos[0], -d[1] * 5 + fromPos[1]];
textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center');
textBaseline = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle');
}
label.attr({
style: {
textBaseline: textBaseline,
textAlign: textAlign
},
position: textPosition
});
}
/**
* @alias module:echarts/component/marker/LineDraw
* @constructor
*/
function LineDraw() {
this.group = new graphic.Group();
}
......@@ -9,78 +106,155 @@ define(function (require) {
var lineDrawProto = LineDraw.prototype;
/**
* @param {module:echarts/data/List} data
* @param {module:echarts/data/List} lineData
* @param {module:echarts/data/List} [fromData]
* @param {module:echarts/data/List} [toData]
* @param {module:echarts/model/Model} seriesModel
* @param {module:echarts/ExtensionAPI} api
* @param {Function} [isIgnore]
*/
lineDrawProto.updateData = function (data, api, isIgnore) {
lineDrawProto.update = function (
lineData, fromData, toData, seriesModel, api
) {
var oldFromData = this._fromData;
var oldToData = this._toData;
var oldLineData = this._lineData;
var group = this.group;
var oldData = this._data;
// var seriesModel = data.hostModel;
data.diff(oldData)
lineData.diff(oldLineData)
.add(function (idx) {
var shape = data.getItemLayout(idx);
var line = new graphic[shape.cpx1 != null ? 'BezierCurve' : 'Line']({
shape: shape
var linePoints = lineData.getItemLayout(idx);
var p1 = linePoints[0];
var p2 = linePoints[1];
var itemModel = lineData.getItemModel(idx);
var labelModel = itemModel.getModel('label.normal');
var textStyleModel = labelModel.getModel('textStyle');
var lineGroup = new graphic.Group();
var line = new graphic.Line({
name: 'line',
shape: {
x1: p1[0], y1: p1[1],
x2: p1[0], y2: p1[1]
}
});
api.initGraphicEl(line, {
shape: {
x2: p2[0], y2: p2[1]
}
});
lineGroup.add(line);
var label = new graphic.Text({
name: 'label',
style: {
text: seriesModel.getFormattedLabel(idx, 'normal')
|| numberUtil.round(seriesModel.getData().getRawValue(idx)),
textFont: textStyleModel.getFont(),
fill: textStyleModel.get('color') || lineData.getItemVisual(idx, 'color')
}
});
lineGroup.add(label);
label.__position = labelModel.get('position');
data.setItemGraphicEl(idx, line);
group.add(line);
if (fromData) {
var symbolFrom = createSymbol(fromData, idx);
symbolFrom.name = 'fromSymbol';
// symbols must added after line to make sure
// it will be updated after line#update.
// Or symbol position and rotation update in line#beforeUpdate will be one frame slow
lineGroup.add(symbolFrom);
}
if (toData) {
var symbolTo = createSymbol(toData, idx);
symbolTo.name = 'toSymbol';
lineGroup.add(symbolTo);
}
// Update symbol position and rotation
lineGroup.beforeUpdate = updateSymbolBeforeLineUpdate;
lineData.setItemGraphicEl(idx, lineGroup);
group.add(lineGroup);
})
.update(function (newIdx, oldIdx) {
var line = oldData.getItemGraphicEl(oldIdx);
var shape = data.getItemLayout(newIdx);
if (shape.cpx1 != null && line.type === 'line') {
var oldShape = line.shape;
line = new graphic.BezierCurve({
shape: oldShape
});
line.setShape({
cpx1: (oldShape.x1 + oldShape.x2) / 2,
cpy1: (oldShape.y1 + oldShape.y2) / 2
});
}
var lineGroup = oldLineData.getItemGraphicEl(oldIdx);
var line = lineGroup.childOfName('line');
var linePoints = lineData.getItemLayout(newIdx);
var p1 = linePoints[0];
var p2 = linePoints[1];
api.updateGraphicEl(line, {
shape: shape
shape: {
x1: p1[0],
y1: p1[1],
x2: p2[0],
y2: p2[1]
}
});
data.setItemGraphicEl(newIdx, line);
group.add(line);
// Symbol changed
if (fromData) {
var fromSymbolType = fromData.getItemVisual(newIdx, 'symbol');
if (!oldFromData || fromSymbolType !== oldFromData.getItemVisual(oldIdx, 'symbol')) {
var symbolFrom = createSymbol(fromData, newIdx);
symbolFrom.name = 'fromSymbol';
lineGroup.remove(line.childOfName('fromSymbol'));
lineGroup.add(symbolFrom);
}
}
if (toData) {
var toSymbolType = toData.getItemVisual(newIdx, 'symbol');
// Symbol changed
if (!oldToData || toSymbolType !== oldToData.getItemVisual(oldIdx, 'symbol')) {
var symbolTo = createSymbol(toData, newIdx);
symbolTo.name = 'toSymbol';
lineGroup.remove(line.childOfName('toSymbol'));
lineGroup.add(symbolTo);
}
}
lineData.setItemGraphicEl(newIdx, lineGroup);
group.add(lineGroup);
})
.remove(function (idx) {
group.remove(oldData.getItemGraphicEl(idx));
group.remove(lineData.getItemGraphicEl(idx));
})
.execute();
this._data = data;
lineData.eachItemGraphicEl(function (lineGroup, idx) {
var line = lineGroup.childOfName('line');
var itemModel = lineData.getItemModel(idx);
this.updateVisual();
};
line.setStyle(zrUtil.defaults(
{
stroke: lineData.getItemVisual(idx, 'color')
},
itemModel.getModel('lineStyle.normal').getLineStyle()
));
lineDrawProto.updateVisual = function () {
var data = this._data;
data.eachItemGraphicEl(function (el, idx) {
var itemModel = data.getItemModel(idx);
el.setStyle(itemModel.getModel('lineStyle.normal').getLineStyle());
graphic.setHoverStyle(
line,
itemModel.getModel('lineStyle.emphasis').getLineStyle()
);
});
this._lineData = lineData;
this._fromData = fromData;
this._toData = toData;
};
lineDrawProto.updateLayout = function () {
var data = this._data;
data.eachItemGraphicEl(function (el, idx) {
var points = data.getItemLayout(idx);
data.setShape({
x1: points[0][0],
y1: points[0][1],
x2: points[1][0],
y2: points[1][1]
});
});
};
lineDrawProto.remove = function () {
this.group.removeAll();
};
return LineDraw;
......
......@@ -10,7 +10,7 @@ define(function (require) {
var markerHelper = require('./markerHelper');
var SeriesMarkLine = require('./SeriesMarkLine');
var LineDraw = require('../../chart/helper/LineDraw');
var markLineTransform = function (data, coordSys, baseAxis, valueAxis, item) {
// Special type markLine like 'min', 'max', 'average'
......@@ -31,7 +31,7 @@ define(function (require) {
var extent = data.getDataExtent(valueAxis.dim, true);
delete mlFrom.type; // Remove type
mlFrom.type = null;
// FIXME Polar should use circle
mlFrom[baseAxisKey] = baseScaleExtent[0];
......@@ -47,15 +47,20 @@ define(function (require) {
mlFrom[valueAxisKey] = mlTo[valueAxisKey] = value;
item = [mlFrom, mlTo, { // Extra option for tooltip and label
__rawValue: value,
name: item.name
__rawValue: value
}];
}
return [
item = [
markerHelper.dataTransform(data, coordSys, item[0]),
markerHelper.dataTransform(data, coordSys, item[1]),
item[2]
{}
];
// Merge from option and to option into line option
zrUtil.merge(item[2], item[0]);
zrUtil.merge(item[2], item[1]);
return item;
};
function markLineFilter(coordSys, dimensionInverse, item) {
......@@ -102,9 +107,9 @@ define(function (require) {
},
render: function (markLineModel, ecModel, api) {
var seriesMarkLineMap = this._markLineMap;
for (var name in seriesMarkLineMap) {
seriesMarkLineMap[name].__keep = false;
var lineDrawMap = this._markLineMap;
for (var name in lineDrawMap) {
lineDrawMap[name].__keep = false;
}
ecModel.eachSeries(function (seriesModel) {
......@@ -112,9 +117,9 @@ define(function (require) {
mlModel && this._renderSeriesML(seriesModel, mlModel, ecModel, api);
}, this);
for (var name in seriesMarkLineMap) {
if (!seriesMarkLineMap[name].__keep) {
this.group.remove(seriesMarkLineMap[name].group);
for (var name in lineDrawMap) {
if (!lineDrawMap[name].__keep) {
this.group.remove(lineDrawMap[name].group);
}
}
},
......@@ -124,18 +129,19 @@ define(function (require) {
var seriesName = seriesModel.name;
var seriesData = seriesModel.getData();
var seriesMarkLineMap = this._markLineMap;
var seriesMarkLine = seriesMarkLineMap[seriesName];
if (!seriesMarkLine) {
seriesMarkLine = seriesMarkLineMap[seriesName] = new SeriesMarkLine();
var lineDrawMap = this._markLineMap;
var lineDraw = lineDrawMap[seriesName];
if (!lineDraw) {
lineDraw = lineDrawMap[seriesName] = new LineDraw();
}
this.group.add(seriesMarkLine.group);
this.group.add(lineDraw.group);
var mlData = createList(coordSys, seriesData, mlModel);
var dims = coordSys.dimensions;
var fromData = mlData.from;
var toData = mlData.to;
var lineData = mlData.line;
// Line data for tooltip and formatter
var lineData = mlData.line;
......@@ -155,19 +161,32 @@ define(function (require) {
symbolSize = [symbolSize, symbolSize];
}
// Update visual and layout of from symbol and to symbol
mlData.from.each(function (idx) {
updateDataVisualAndLayout(fromData, idx, true);
updateDataVisualAndLayout(toData, idx);
});
seriesMarkLine.update(
fromData, toData, mlModel, api, ecModel.get('animation')
);
// Update visual and layout of line
lineData.each(function (idx) {
var lineColor = lineData.getItemModel(idx).get('lineStyle.normal.color');
lineData.setItemVisual(idx, {
color: lineColor || fromData.getItemVisual(idx, 'color')
});
lineData.setItemLayout(idx, [
fromData.getItemLayout(idx),
toData.getItemLayout(idx)
]);
});
lineDraw.update(lineData, fromData, toData, mlModel, api);
// Set host model for tooltip
// FIXME
mlData.from.eachItemGraphicEl(function (el, idx) {
el.hostModel = mlModel;
mlData.line.eachItemGraphicEl(function (el, idx) {
el.eachChild(function (child) {
child.hostModel = mlModel;
});
});
function updateDataVisualAndLayout(data, idx, isFrom) {
......@@ -197,7 +216,7 @@ define(function (require) {
});
}
seriesMarkLine.__keep = true;
lineDraw.__keep = true;
}
});
......
......@@ -201,8 +201,8 @@ define(function (require) {
hideLater: function (time) {
if (this._show && !(this._inContent && this.enterable)) {
if (time) {
// Set show false to avoid invoke hideLater mutiple times
this._hideDelay = time;
// Set show false to avoid invoke hideLater mutiple times
this._show = false;
this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time);
}
......
......@@ -19,9 +19,11 @@ define(function (require) {
// 触发类型,默认数据触发,见下图,可选为:'item' ¦ 'axis'
trigger: 'item',
// If the tooltip follow the mouse position
// TODO
// followMouse: true,
// 触发条件,支持 'click' | 'mousemove'
triggerOn: 'mousemove',
// 是否永远显示 content
// alwaysShowContent: false,
// 位置 {Array} | {Function}
// position: null
......
......@@ -23,7 +23,7 @@ define(function (require) {
onZero: true,
// 属性lineStyle控制线条样式
lineStyle: {
color: '#000',
color: '#333',
width: 1,
type: 'solid'
}
......
......@@ -70,7 +70,9 @@ define(function(require) {
zrUtil.merge(option, this.getDefaultOption());
// Default label emphasis `position` and `show`
modelUtil.defaultEmphasis(option.label);
modelUtil.defaultEmphasis(
option.label, ['position', 'show', 'textStyle', 'distance', 'formatter']
);
},
mergeOption: function (newSeriesOption, ecModel) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册