提交 33083917 编写于 作者: L lang

Enhance symbol draw

上级 60ebda52
......@@ -13,20 +13,30 @@ define(function(require) {
this[name] = zrUtil.bind(chartInstance[name], chartInstance);
}, this);
function animateOrSetGraphicEl(isUpdate, el, props, cb) {
var ecModel = chartInstance.getModel();
var duration = ecModel.getShallow('animationDuration' + (isUpdate ? 'Update' : ''));
var animationEasing = ecModel.getShallow('animationEasing' + (isUpdate ? 'Update' : ''));
ecModel.getShallow('animation')
? el.animateTo(props, duration, animationEasing, cb)
: (el.attr(props), cb && cb());
}
/**
* Update element property
* @param {module:zrender/Element}
* @param {module:zrender/Element} el
* @param {Object} props
* @param {Function} [cb]
*/
this.updateGraphicEl = function (el, props) {
var ecModel = chartInstance.getModel();
var duration = ecModel.getShallow('animationDurationUpdate');
var enableAnimation = ecModel.getShallow('animation');
var animationEasing = ecModel.getShallow('animationEasing');
enableAnimation
? el.animateTo(props, duration, animationEasing)
: el.attr(props);
};
this.updateGraphicEl = zrUtil.curry(animateOrSetGraphicEl, true);
/**
* Init element property
* @param {module:zrender/Element} el
* @param {Object} props
* @param {Function} [cb]
*/
this.initGraphicEl = zrUtil.curry(animateOrSetGraphicEl, false);
}
return ExtensionAPI;
......
......@@ -37,14 +37,9 @@ define(function (require) {
var symbolDraw = this._symbolDraw;
var lineDraw = this._lineDraw;
symbolDraw.updateData(
data, seriesModel, api, true
);
lineDraw.updateData(
data.graph.edgeData,
seriesModel, api, false
);
symbolDraw.updateData(data, api);
lineDraw.updateData(data.graph.edgeData, api);
// Save the original lineWidth
data.graph.eachEdge(function (edge) {
......
......@@ -10,16 +10,16 @@ define(function (require) {
/**
* @param {module:echarts/data/List} data
* @param {module:echarts/model/Series} seriesModel
* @param {module:echarts/ExtensionAPI} api
* @param {boolean} [enableAnimation=false]
* @param {Function} [isIgnore]
*/
lineDrawProto.updateData = function (
data, seriesModel, api, enableAnimation, isIgnore
data, api, enableAnimation, isIgnore
) {
var group = this.group;
var oldData = this._data;
// var seriesModel = data.hostModel;
data.diff(oldData)
.add(function (idx) {
......
define(function (require) {
var zrUtil = require('zrender/core/util');
var symbolUtil = require('../../util/symbol');
var graphic = require('../../util/graphic');
function normalizeSymbolSize(symbolSize) {
if (!zrUtil.isArray(symbolSize)) {
symbolSize = [+symbolSize, +symbolSize];
}
return symbolSize;
}
/**
* @constructor
* @extends {module:zrender/graphic/Group}
*/
function Symbol(data, idx, api) {
graphic.Group.call(this);
var color = data.getItemVisual(idx, 'color');
var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
var symbolPath = symbolUtil.createSymbol(
symbolType, -0.5, -0.5, 1, 1, color
);
symbolPath.attr({
z2: 100
});
symbolPath.attr('scale', [0, 0]);
this.add(symbolPath);
var size = data.getItemVisual(idx, 'symbolSize');
// var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
api.initGraphicEl(symbolPath, {
scale: normalizeSymbolSize(size)
});
this._updateCommon(data, idx);
}
var symbolProto = Symbol.prototype;
symbolProto.updateSymbol = function (data, idx, api) {
var symbolPath = this.childAt(0);
var size = data.getItemVisual(idx, 'symbolSize');
// var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
api.updateGraphicEl(symbolPath, {
scale: normalizeSymbolSize(size)
});
this._updateCommon(data, idx);
};
// Update common properties
var normalStyleAccessPath = ['itemStyle', 'normal'];
var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
symbolProto._updateCommon = function (data, idx) {
var symbolPath = this.childAt(0);
var seriesModel = data.hostModel;
var itemModel = data.getItemModel(idx);
var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath);
var color = data.getItemVisual(idx, 'color');
var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();
symbolPath.setColor(color);
zrUtil.extend(
symbolPath.style,
// Color must be excluded.
// Because symbol provide setColor individually to set fill and stroke
normalItemStyleModel.getItemStyle(['color'])
);
var labelModel = itemModel.getModel('label.normal');
var hoverLabelModel = itemModel.getModel('label.emphasis');
var lastDim = data.dimensions[data.dimensions.length - 1];
var labelText = seriesModel.getFormattedLabel(idx, 'normal')
|| data.get(lastDim, idx);
var elStyle = symbolPath.style;
var showLabel = labelModel.get('show');
if (showLabel) {
graphic.setText(elStyle, labelModel, color);
elStyle.text = labelText;
}
else {
elStyle.text = '';
}
if (zrUtil.retrieve(hoverLabelModel.get('show'), showLabel)) {
graphic.setText(hoverStyle, hoverLabelModel, color);
hoverStyle.text = labelText;
}
else {
hoverStyle.text = '';
}
graphic.setHoverStyle(symbolPath, hoverStyle);
};
symbolProto.fadeOut = function (cb, api) {
var symbolPath = this.childAt(0);
api.updateGraphicEl(symbolPath, {
scale: [0, 0]
}, cb);
};
zrUtil.inherits(Symbol, graphic.Group);
return Symbol;
});
\ No newline at end of file
/**
* @module echarts/chart/helper/SymbolDraw
*/
define(function (require) {
var zrUtil = require('zrender/core/util');
var symbolUtil = require('../../util/symbol');
var graphic = require('../../util/graphic');
var Symbol = require('./Symbol');
function normalizeSymbolSize(symbolSize) {
if (!zrUtil.isArray(symbolSize)) {
symbolSize = [+symbolSize, +symbolSize];
}
return symbolSize;
}
function isAroundEqual(a, b) {
return Math.abs(a - b) < 1e-4;
}
function createSymbol(data, idx, enableAnimation) {
var point = data.getItemLayout(idx);
var color = data.getItemVisual(idx, 'color');
var size = data.getItemVisual(idx, 'symbolSize');
var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
if (symbolType === 'none') {
return;
}
size = normalizeSymbolSize(size);
var symbolEl = symbolUtil.createSymbol(
symbolType, -size[0] / 2, -size[1] / 2, size[0], size[1], color
);
symbolEl.attr({
position: point,
z2: 100
});
if (enableAnimation && symbolEl.shape) {
// FIXME Use scale to improve performance
var zeroShape = symbolUtil.getSymbolShape(
symbolType, 0, 0, 0, 0
).shape;
var normalShape = symbolEl.shape;
symbolEl.shape = zeroShape;
symbolEl.animateTo({
shape: normalShape
}, 500);
}
return symbolEl;
}
/**
* @constructor
*/
function SymbolDraw() {
this.group = new graphic.Group();
}
var symbolProto = SymbolDraw.prototype;
var symbolDrawProto = SymbolDraw.prototype;
/**
* @param {module:echarts/data/List} data
* @param {module:echarts/model/Series} seriesModel
* @param {module:echarts/ExtensionAPI} api
* @param {boolean} [enableAnimation=false]
* @param {Array.<boolean>} [isIgnore]
*/
symbolProto.updateData = function (
data, seriesModel, api, enableAnimation, isIgnore
) {
symbolDrawProto.updateData = function (data, api, isIgnore) {
var group = this.group;
var oldData = this._data;
data.diff(oldData)
.add(function (newIdx) {
if (data.hasValue(newIdx) && !(isIgnore && isIgnore(newIdx))) {
var symbolEl = createSymbol(data, newIdx, enableAnimation);
if (symbolEl) {
data.setItemGraphicEl(newIdx, symbolEl);
group.add(symbolEl);
}
if (
data.hasValue(newIdx) && !(isIgnore && isIgnore(newIdx))
&& data.getItemVisual(newIdx, 'symbol') !== 'none'
) {
var symbolEl = new Symbol(data, newIdx, api);
symbolEl.attr('position', data.getItemLayout(newIdx));
data.setItemGraphicEl(newIdx, symbolEl);
group.add(symbolEl);
}
})
.update(function (newIdx, oldIdx) {
var el = oldData.getItemGraphicEl(oldIdx);
var symbolEl = oldData.getItemGraphicEl(oldIdx);
// Empty data
if (!data.hasValue(newIdx) || (isIgnore && isIgnore(newIdx))) {
group.remove(el);
group.remove(symbolEl);
return;
}
var size = normalizeSymbolSize(
data.getItemVisual(newIdx, 'symbolSize')
);
var point = data.getItemLayout(newIdx);
var symbolType = data.getItemVisual(newIdx, 'symbol');
// Symbol changed
if (
oldData.getItemVisual(oldIdx, 'symbol') !== symbolType
|| (!el && !(isIgnore && isIgnore(newIdx)))
) {
// Remove the old one
el && group.remove(el);
el = createSymbol(data, newIdx, enableAnimation);
// Disable symbol by setting `symbol: 'none'`
if (!el) { return; }
if (!symbolEl) {
symbolEl = new Symbol(data, newIdx, api);
symbolEl.attr('position', point);
}
else {
// Update animation
if (!el) { return; }
// FIXME symbol created with pathStr has symbolSizeChanged
// FIXME Can't use symbolSize to determine if symbol has changed it's size
// Or animation will be wrong if symbolSize changed to frequently
var newTarget = (symbolUtil.getSymbolShape(
symbolType, -size[0] / 2, -size[1] / 2, size[0], size[1]
) || {});
newTarget.position = point;
if (!isAroundEqual(el.scale[0], 1)) { // May have scale 0
newTarget.scale = [1, 1];
}
if (enableAnimation) {
api.updateGraphicEl(el, newTarget);
}
else {
// May still have animation. Must stop
el.stopAnimation();
el.attr(newTarget);
}
symbolEl.updateSymbol(data, newIdx, api);
api.updateGraphicEl(symbolEl, {
position: point
});
}
data.setItemGraphicEl(newIdx, el);
// Add back
group.add(el);
group.add(symbolEl);
data.setItemGraphicEl(newIdx, symbolEl);
})
.remove(function (oldIdx) {
var el = oldData.getItemGraphicEl(oldIdx);
if (enableAnimation) {
el.animateTo({
scale: [0, 0]
}, 200, 'cubicOut', function () {
group.remove(el);
});
}
else {
// console.log(oldIdx);
el && el.fadeOut(function () {
group.remove(el);
}
}, api);
})
.execute();
// Update common properties
var normalStyleAccessPath = ['itemStyle', 'normal'];
var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
data.eachItemGraphicEl(function (el, idx) {
var itemModel = data.getItemModel(idx);
var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath);
var color = data.getItemVisual(idx, 'color');
var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();
el.setColor(color);
zrUtil.extend(
el.style,
// Color must be excluded.
// Because symbol provide setColor individually to set fill and stroke
normalItemStyleModel.getItemStyle(['color'])
);
var labelModel = itemModel.getModel('label.normal');
var hoverLabelModel = itemModel.getModel('label.emphasis');
var lastDim = data.dimensions[data.dimensions.length - 1];
var labelText = seriesModel.getFormattedLabel(idx, 'normal')
|| data.get(lastDim, idx);
var elStyle = el.style;
var showLabel = labelModel.get('show');
if (showLabel) {
graphic.setText(elStyle, labelModel, color);
elStyle.text = labelText;
}
else {
elStyle.text = '';
}
if (zrUtil.retrieve(hoverLabelModel.get('show'), showLabel)) {
graphic.setText(hoverStyle, hoverLabelModel, color);
hoverStyle.text = labelText;
}
else {
hoverStyle.text = '';
}
graphic.setHoverStyle(el, hoverStyle);
}, this);
this._data = data;
};
symbolProto.updateLayout = function () {
symbolDrawProto.updateLayout = function () {
var data = this._data;
if (data) {
// Not use animation
......@@ -212,17 +81,15 @@ define(function (require) {
}
};
symbolProto.remove = function (enableAnimation) {
symbolDrawProto.remove = function (api, enableAnimation) {
var group = this.group;
var data = this._data;
if (data) {
if (enableAnimation) {
data.eachItemGraphicEl(function (el) {
el.animateTo({
scale: [0, 0]
}, 200, 'cubicOut', function () {
el.fadeOut(function () {
group.remove(el);
});
}, api);
});
}
else {
......
......@@ -113,16 +113,12 @@ define(function(require) {
var isSymbolIgnore = !isCoordSysPolar && !seriesModel.get('showAllSymbol')
&& this._getSymbolIgnoreFunc(data, coordSys);
// Initialization animation or coordinate system changed
if (
!(polyline
&& prevCoordSys.type === coordSys.type)
) {
symbolDraw.updateData(
data, seriesModel, api, hasAnimation, isSymbolIgnore
);
symbolDraw.updateData(data, api, isSymbolIgnore);
polyline = this._newPolyline(group, points, coordSys, hasAnimation);
if (isAreaChart) {
polygon = this._newPolygon(
......@@ -133,10 +129,6 @@ define(function(require) {
}
}
else {
symbolDraw.updateData(
data, seriesModel, api, false, isSymbolIgnore
);
// Update clipPath
// FIXME Clip path used by more than one elements
if (hasAnimation) {
......@@ -153,6 +145,8 @@ define(function(require) {
if (!isPointsSame(this._stackedOnPoints, stackedOnPoints)
|| !isPointsSame(this._points, points)
) {
symbolDraw.updateData(data, api, isSymbolIgnore);
if (hasAnimation) {
this._updateAnimation(
data, stackedOnPoints, coordSys, api
......@@ -333,7 +327,6 @@ define(function(require) {
}
var updatedDataInfo = [];
var addedDataIndices = [];
var diffStatus = diff.status;
for (var i = 0; i < diffStatus.length; i++) {
......@@ -341,27 +334,16 @@ define(function(require) {
if (cmd === '=') {
var el = data.getItemGraphicEl(diffStatus[i].idx1);
if (el) {
el.stopAnimation();
updatedDataInfo.push({
el: el,
ptIdx: i // Index of points
});
}
}
else if (cmd === '+') {
addedDataIndices.push(diffStatus[i].idx);
}
}
if (polyline.animators) {
for (var i = 0; i < addedDataIndices.length; i++) {
var el = data.getItemGraphicEl(addedDataIndices[i]);
if (el) {
el.scale = [0, 0];
el.animateTo({
scale: [1, 1]
}, 300, 300, 'cubicOut');
}
}
polyline.animators[0].during(function () {
for (var i = 0; i < updatedDataInfo.length; i++) {
var el = updatedDataInfo[i].el;
......@@ -441,11 +423,11 @@ define(function(require) {
return clipPath;
},
remove: function (ecModel) {
remove: function (ecModel, api) {
var group = this.group;
group.remove(this._polyline);
group.remove(this._polygon);
this._symbolDraw.remove(ecModel.get('animation'));
this._symbolDraw.remove(api, true);
}
});
});
\ No newline at end of file
......@@ -67,10 +67,10 @@ define(function (require) {
* Create sector, label, and label line for each data
* @param {Object} layout
* @param {string} text
* @param {boolean} hasAnimations
* @param {boolean} hasAnimation
* @return {module:zrender/graphic/Sector}
*/
function createSectorAndLabel(layout, text, hasAnimation) {
function createSectorAndLabel(layout, text, hasAnimation, api) {
var shape = zrUtil.extend({}, layout);
delete shape.label;
......@@ -108,11 +108,11 @@ define(function (require) {
if (hasAnimation) {
sector.shape.endAngle = layout.startAngle;
sector.animateTo({
api.updateGraphicEl(sector, {
shape: {
endAngle: layout.endAngle
}
}, 300, 'cubicOut');
});
}
return sector;
......@@ -156,7 +156,7 @@ define(function (require) {
var layout = data.getItemLayout(idx);
var sector = createSectorAndLabel(
layout, '', hasAnimation && !isFirstRender
layout, '', !isFirstRender, api
);
selectedMode && sector.on('click', onSectorClick);
......@@ -231,7 +231,7 @@ define(function (require) {
var removeClipPath = zrUtil.bind(sectorGroup.removeClipPath, sectorGroup);
sectorGroup.setClipPath(this._createClipPath(
shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath
shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, api
));
}
......@@ -296,7 +296,9 @@ define(function (require) {
});
},
_createClipPath: function (cx, cy, r, startAngle, clockwise, cb) {
_createClipPath: function (
cx, cy, r, startAngle, clockwise, cb, api
) {
var clipPath = new graphic.Sector({
shape: {
cx: cx,
......@@ -309,11 +311,11 @@ define(function (require) {
}
});
clipPath.animateTo({
api.initGraphicEl(clipPath, {
shape: {
endAngle: startAngle + (clockwise ? 1 : -1) * Math.PI * 2
}
}, 1000, 'cubicOut', cb);
}, cb);
return clipPath;
},
......
......@@ -12,17 +12,15 @@ define(function (require) {
},
render: function (seriesModel, ecModel, api) {
this._symbolDraw.updateData(
seriesModel.getData(), seriesModel, api, ecModel.get('animation')
);
this._symbolDraw.updateData(seriesModel.getData(), api);
},
updateLayout: function () {
this._symbolDraw.updateLayout();
},
remove: function (ecModel) {
this._symbolDraw.remove(ecModel.get('animation'));
remove: function (ecModel, api) {
this._symbolDraw.remove(api, true);
}
});
});
\ No newline at end of file
......@@ -114,9 +114,7 @@ define(function (require) {
});
// TODO Text are wrong
symbolDraw.updateData(
mpData, mpModel, api, true
);
symbolDraw.updateData(mpData, api);
this.group.add(symbolDraw.group);
// Set host model for tooltip
......
......@@ -36,6 +36,7 @@ define(function () {
animationThreshold: 2000, // 动画元素阀值,产生的图形原素超过2000不出动画
animationDuration: 1000, // 过渡动画参数:进入
animationDurationUpdate: 300, // 过渡动画参数:更新
animationEasing: 'cubicOut' //BounceOut
animationEasing: 'cubicOut', //BounceOut
animationEasingUpdate: 'cubicOut'
};
});
\ No newline at end of file
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册