You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
624 lines
18 KiB
624 lines
18 KiB
/**
|
|
* echarts图表动画基类
|
|
*
|
|
* @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
|
|
* @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
|
|
*
|
|
*/
|
|
define(function (require) {
|
|
var zrUtil = require('zrender/tool/util');
|
|
var curveTool = require('zrender/tool/curve');
|
|
|
|
/**
|
|
* 折线型动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function pointList(zr, oldShape, newShape, duration, easing) {
|
|
var newPointList = newShape.style.pointList;
|
|
var newPointListLen = newPointList.length;
|
|
var oldPointList;
|
|
|
|
if (!oldShape) { // add
|
|
oldPointList = [];
|
|
if (newShape._orient != 'vertical') {
|
|
var y = newPointList[0][1];
|
|
for (var i = 0; i < newPointListLen; i++) {
|
|
oldPointList[i] = [newPointList[i][0], y];
|
|
}
|
|
}
|
|
else {
|
|
var x = newPointList[0][0];
|
|
for (var i = 0; i < newPointListLen; i++) {
|
|
oldPointList[i] = [x, newPointList[i][1]];
|
|
}
|
|
}
|
|
|
|
if (newShape.type == 'half-smooth-polygon') {
|
|
oldPointList[newPointListLen - 1] = zrUtil.clone(newPointList[newPointListLen - 1]);
|
|
oldPointList[newPointListLen - 2] = zrUtil.clone(newPointList[newPointListLen - 2]);
|
|
}
|
|
oldShape = {style : {pointList : oldPointList}};
|
|
}
|
|
|
|
oldPointList = oldShape.style.pointList;
|
|
var oldPointListLen = oldPointList.length;
|
|
if (oldPointListLen == newPointListLen) {
|
|
newShape.style.pointList = oldPointList;
|
|
}
|
|
else if (oldPointListLen < newPointListLen) {
|
|
// 原来短,新的长,补全
|
|
newShape.style.pointList = oldPointList.concat(newPointList.slice(oldPointListLen));
|
|
}
|
|
else {
|
|
// 原来长,新的短,截断
|
|
newShape.style.pointList = oldPointList.slice(0, newPointListLen);
|
|
}
|
|
|
|
zr.addShape(newShape);
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{ pointList: newPointList }
|
|
)
|
|
.during(function () {
|
|
// Updating bezier points
|
|
if (newShape.updateControlPoints) {
|
|
newShape.updateControlPoints(newShape.style);
|
|
}
|
|
})
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
|
|
/**
|
|
* 复制样式
|
|
*
|
|
* @inner
|
|
* @param {Object} target 目标对象
|
|
* @param {Object} source 源对象
|
|
* @param {...string} props 复制的属性列表
|
|
*/
|
|
function cloneStyle(target, source) {
|
|
var len = arguments.length;
|
|
for (var i = 2; i < len; i++) {
|
|
var prop = arguments[i];
|
|
target.style[prop] = source.style[prop];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 方型动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function rectangle(zr, oldShape, newShape, duration, easing) {
|
|
var newShapeStyle = newShape.style;
|
|
if (!oldShape) { // add
|
|
oldShape = {
|
|
position : newShape.position,
|
|
style : {
|
|
x : newShapeStyle.x,
|
|
y : newShape._orient == 'vertical'
|
|
? newShapeStyle.y + newShapeStyle.height
|
|
: newShapeStyle.y,
|
|
width: newShape._orient == 'vertical'
|
|
? newShapeStyle.width : 0,
|
|
height: newShape._orient != 'vertical'
|
|
? newShapeStyle.height : 0
|
|
}
|
|
};
|
|
}
|
|
|
|
var newX = newShapeStyle.x;
|
|
var newY = newShapeStyle.y;
|
|
var newWidth = newShapeStyle.width;
|
|
var newHeight = newShapeStyle.height;
|
|
var newPosition = [newShape.position[0], newShape.position[1]];
|
|
cloneStyle(
|
|
newShape, oldShape,
|
|
'x', 'y', 'width', 'height'
|
|
);
|
|
newShape.position = oldShape.position;
|
|
|
|
zr.addShape(newShape);
|
|
if (newPosition[0] != oldShape.position[0] || newPosition[1] != oldShape.position[1]) {
|
|
zr.animate(newShape.id, '')
|
|
.when(
|
|
duration,
|
|
{
|
|
position: newPosition
|
|
}
|
|
)
|
|
.start(easing);
|
|
}
|
|
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{
|
|
x: newX,
|
|
y: newY,
|
|
width: newWidth,
|
|
height: newHeight
|
|
}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
|
|
/**
|
|
* 蜡烛动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function candle(zr, oldShape, newShape, duration, easing) {
|
|
if (!oldShape) { // add
|
|
var y = newShape.style.y;
|
|
oldShape = {style : {y : [y[0], y[0], y[0], y[0]]}};
|
|
}
|
|
|
|
var newY = newShape.style.y;
|
|
newShape.style.y = oldShape.style.y;
|
|
zr.addShape(newShape);
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{ y: newY }
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
|
|
/**
|
|
* 环型动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function ring(zr, oldShape, newShape, duration, easing) {
|
|
var x = newShape.style.x;
|
|
var y = newShape.style.y;
|
|
var r0 = newShape.style.r0;
|
|
var r = newShape.style.r;
|
|
|
|
newShape.__animating = true;
|
|
|
|
if (newShape._animationAdd != 'r') {
|
|
newShape.style.r0 = 0;
|
|
newShape.style.r = 0;
|
|
newShape.rotation = [Math.PI*2, x, y];
|
|
|
|
zr.addShape(newShape);
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{
|
|
r0 : r0,
|
|
r : r
|
|
}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
zr.animate(newShape.id, '')
|
|
.when(
|
|
duration,
|
|
{ rotation : [0, x, y] }
|
|
)
|
|
.start(easing);
|
|
}
|
|
else {
|
|
newShape.style.r0 = newShape.style.r;
|
|
|
|
zr.addShape(newShape);
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{
|
|
r0 : r0
|
|
}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 扇形动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function sector(zr, oldShape, newShape, duration, easing) {
|
|
if (!oldShape) { // add
|
|
if (newShape._animationAdd != 'r') {
|
|
oldShape = {
|
|
style : {
|
|
startAngle : newShape.style.startAngle,
|
|
endAngle : newShape.style.startAngle
|
|
}
|
|
};
|
|
}
|
|
else {
|
|
oldShape = {style : {r0 : newShape.style.r}};
|
|
}
|
|
}
|
|
|
|
var startAngle = newShape.style.startAngle;
|
|
var endAngle = newShape.style.endAngle;
|
|
|
|
cloneStyle(
|
|
newShape, oldShape,
|
|
'startAngle', 'endAngle'
|
|
);
|
|
|
|
zr.addShape(newShape);
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{
|
|
startAngle : startAngle,
|
|
endAngle : endAngle
|
|
}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
|
|
/**
|
|
* 文本动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function text(zr, oldShape, newShape, duration, easing) {
|
|
if (!oldShape) { // add
|
|
oldShape = {
|
|
style : {
|
|
x : newShape.style.textAlign == 'left'
|
|
? newShape.style.x + 100
|
|
: newShape.style.x - 100,
|
|
y : newShape.style.y
|
|
}
|
|
};
|
|
}
|
|
|
|
var x = newShape.style.x;
|
|
var y = newShape.style.y;
|
|
|
|
cloneStyle(
|
|
newShape, oldShape,
|
|
'x', 'y'
|
|
);
|
|
|
|
zr.addShape(newShape);
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{
|
|
x : x,
|
|
y : y
|
|
}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
|
|
/**
|
|
* 多边形动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function polygon(zr, oldShape, newShape, duration, easing) {
|
|
var rect = require('zrender/shape/Polygon').prototype.getRect(newShape.style);
|
|
var x = rect.x + rect.width / 2;
|
|
var y = rect.y + rect.height / 2;
|
|
|
|
newShape.scale = [0.1, 0.1, x, y];
|
|
zr.addShape(newShape);
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, '')
|
|
.when(
|
|
duration,
|
|
{
|
|
scale : [1, 1, x, y]
|
|
}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
|
|
/**
|
|
* 和弦动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function ribbon(zr, oldShape, newShape, duration, easing) {
|
|
if (!oldShape) { // add
|
|
oldShape = {
|
|
style : {
|
|
source0 : 0,
|
|
source1 : newShape.style.source1 > 0 ? 360 : -360,
|
|
target0 : 0,
|
|
target1 : newShape.style.target1 > 0 ? 360 : -360
|
|
}
|
|
};
|
|
}
|
|
|
|
var source0 = newShape.style.source0;
|
|
var source1 = newShape.style.source1;
|
|
var target0 = newShape.style.target0;
|
|
var target1 = newShape.style.target1;
|
|
|
|
if (oldShape.style) {
|
|
cloneStyle(
|
|
newShape, oldShape,
|
|
'source0', 'source1', 'target0', 'target1'
|
|
);
|
|
}
|
|
|
|
zr.addShape(newShape);
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{
|
|
source0 : source0,
|
|
source1 : source1,
|
|
target0 : target0,
|
|
target1 : target1
|
|
}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
|
|
/**
|
|
* gaugePointer动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function gaugePointer(zr, oldShape, newShape, duration, easing) {
|
|
if (!oldShape) { // add
|
|
oldShape = {
|
|
style : {
|
|
angle : newShape.style.startAngle
|
|
}
|
|
};
|
|
}
|
|
|
|
var angle = newShape.style.angle;
|
|
newShape.style.angle = oldShape.style.angle;
|
|
zr.addShape(newShape);
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{
|
|
angle : angle
|
|
}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
|
|
/**
|
|
* icon动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function icon(zr, oldShape, newShape, duration, easing, delay) {
|
|
// 避免markPoint特效取值在动画帧上
|
|
newShape.style._x = newShape.style.x;
|
|
newShape.style._y = newShape.style.y;
|
|
newShape.style._width = newShape.style.width;
|
|
newShape.style._height = newShape.style.height;
|
|
|
|
if (!oldShape) { // add
|
|
var x = newShape._x || 0;
|
|
var y = newShape._y || 0;
|
|
newShape.scale = [0.01, 0.01, x, y];
|
|
zr.addShape(newShape);
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, '')
|
|
.delay(delay)
|
|
.when(
|
|
duration,
|
|
{scale : [1, 1, x, y]}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing || 'QuinticOut');
|
|
}
|
|
else { // mod
|
|
rectangle(zr, oldShape, newShape, duration, easing);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* line动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function line(zr, oldShape, newShape, duration, easing) {
|
|
if (!oldShape) {
|
|
oldShape = {
|
|
style : {
|
|
xStart : newShape.style.xStart,
|
|
yStart : newShape.style.yStart,
|
|
xEnd : newShape.style.xStart,
|
|
yEnd : newShape.style.yStart
|
|
}
|
|
};
|
|
}
|
|
|
|
var xStart = newShape.style.xStart;
|
|
var xEnd = newShape.style.xEnd;
|
|
var yStart = newShape.style.yStart;
|
|
var yEnd = newShape.style.yEnd;
|
|
|
|
cloneStyle(
|
|
newShape, oldShape,
|
|
'xStart', 'xEnd', 'yStart', 'yEnd'
|
|
);
|
|
|
|
zr.addShape(newShape);
|
|
newShape.__animating = true;
|
|
zr.animate(newShape.id, 'style')
|
|
.when(
|
|
duration,
|
|
{
|
|
xStart: xStart,
|
|
xEnd: xEnd,
|
|
yStart: yStart,
|
|
yEnd: yEnd
|
|
}
|
|
)
|
|
.done(function() {
|
|
newShape.__animating = false;
|
|
})
|
|
.start(easing);
|
|
}
|
|
|
|
/**
|
|
* markline动画
|
|
*
|
|
* @param {ZRender} zr
|
|
* @param {shape} oldShape
|
|
* @param {shape} newShape
|
|
* @param {number} duration
|
|
* @param {tring} easing
|
|
*/
|
|
function markline(zr, oldShape, newShape, duration, easing) {
|
|
easing = easing || 'QuinticOut';
|
|
newShape.__animating = true;
|
|
zr.addShape(newShape);
|
|
var newShapeStyle = newShape.style;
|
|
|
|
var animationDone = function () {
|
|
newShape.__animating = false;
|
|
};
|
|
var x0 = newShapeStyle.xStart;
|
|
var y0 = newShapeStyle.yStart;
|
|
var x2 = newShapeStyle.xEnd;
|
|
var y2 = newShapeStyle.yEnd;
|
|
if (newShapeStyle.curveness > 0) {
|
|
newShape.updatePoints(newShapeStyle);
|
|
var obj = { p: 0 };
|
|
var x1 = newShapeStyle.cpX1;
|
|
var y1 = newShapeStyle.cpY1;
|
|
var newXArr = [];
|
|
var newYArr = [];
|
|
var subdivide = curveTool.quadraticSubdivide;
|
|
zr.animation.animate(obj)
|
|
.when(duration, { p: 1 })
|
|
.during(function () {
|
|
// Calculate subdivided curve
|
|
subdivide(x0, x1, x2, obj.p, newXArr);
|
|
subdivide(y0, y1, y2, obj.p, newYArr);
|
|
newShapeStyle.cpX1 = newXArr[1];
|
|
newShapeStyle.cpY1 = newYArr[1];
|
|
newShapeStyle.xEnd = newXArr[2];
|
|
newShapeStyle.yEnd = newYArr[2];
|
|
zr.modShape(newShape);
|
|
})
|
|
.done(animationDone)
|
|
.start(easing);
|
|
}
|
|
else {
|
|
zr.animate(newShape.id, 'style')
|
|
.when(0, {
|
|
xEnd: x0,
|
|
yEnd: y0
|
|
})
|
|
.when(duration, {
|
|
xEnd: x2,
|
|
yEnd: y2
|
|
})
|
|
.done(animationDone)
|
|
.start(easing);
|
|
}
|
|
}
|
|
|
|
return {
|
|
pointList : pointList,
|
|
rectangle : rectangle,
|
|
candle : candle,
|
|
ring : ring,
|
|
sector : sector,
|
|
text : text,
|
|
polygon : polygon,
|
|
ribbon : ribbon,
|
|
gaugePointer : gaugePointer,
|
|
icon : icon,
|
|
line : line,
|
|
markline : markline
|
|
};
|
|
});
|
|
|