ecAnimation.js 18.0 KB
Newer Older
K
kener 已提交
1 2 3 4
/**
 * echarts图表动画基类
 *
 * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
K
kener 已提交
5
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
K
kener 已提交
6 7 8
 *
 */
define(function (require) {
K
kener 已提交
9
    var zrUtil = require('zrender/tool/util');
10
    var curveTool = require('zrender/tool/curve');
K
kener 已提交
11
    
K
kener 已提交
12 13 14 15 16 17 18 19 20 21
    /**
     * 折线型动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
    function pointList(zr, oldShape, newShape, duration, easing) {
E
erik 已提交
22 23 24 25
        var newPointList = newShape.style.pointList;
        var newPointListLen = newPointList.length;
        var oldPointList;

K
kener 已提交
26
        if (!oldShape) {        // add
E
erik 已提交
27
            oldPointList = [];
K
kener 已提交
28
            if (newShape._orient != 'vertical') {
E
erik 已提交
29 30 31
                var y = newPointList[0][1];
                for (var i = 0; i < newPointListLen; i++) {
                    oldPointList[i] = [newPointList[i][0], y];
K
kener 已提交
32 33 34
                }
            }
            else {
E
erik 已提交
35 36 37
                var x = newPointList[0][0];
                for (var i = 0; i < newPointListLen; i++) {
                    oldPointList[i] = [x, newPointList[i][1]];
K
kener 已提交
38 39
                }
            }
E
erik 已提交
40

K
kener 已提交
41
            if (newShape.type == 'half-smooth-polygon') {
E
erik 已提交
42 43
                oldPointList[newPointListLen - 1] = zrUtil.clone(newPointList[newPointListLen - 1]);
                oldPointList[newPointListLen - 2] = zrUtil.clone(newPointList[newPointListLen - 2]);
K
kener 已提交
44
            }
E
erik 已提交
45
            oldShape = {style : {pointList : oldPointList}};
K
kener 已提交
46 47
        }
        
E
erik 已提交
48 49 50 51
        oldPointList = oldShape.style.pointList;
        var oldPointListLen = oldPointList.length;
        if (oldPointListLen == newPointListLen) {
            newShape.style.pointList = oldPointList;
K
kener 已提交
52
        }
E
erik 已提交
53
        else if (oldPointListLen < newPointListLen) {
K
kener 已提交
54
            // 原来短,新的长,补全
E
erik 已提交
55
            newShape.style.pointList = oldPointList.concat(newPointList.slice(oldPointListLen));
K
kener 已提交
56 57 58
        }
        else {
            // 原来长,新的短,截断
E
erik 已提交
59
            newShape.style.pointList = oldPointList.slice(0, newPointListLen);
K
kener 已提交
60
        }
E
erik 已提交
61

K
kener 已提交
62
        zr.addShape(newShape);
L
lang 已提交
63
        newShape.__animating = true;
K
kener 已提交
64 65 66 67 68
        zr.animate(newShape.id, 'style')
            .when(
                duration,
                { pointList: newPointList }
            )
L
lang 已提交
69 70 71 72 73 74
            .during(function () {
                // Updating bezier points
                if (newShape.updateControlPoints) {
                    newShape.updateControlPoints(newShape.style);
                }
            })
K
Kener 已提交
75
            .done(function() {
L
lang 已提交
76
                newShape.__animating = false;
K
Kener 已提交
77
            })
K
kener 已提交
78 79 80
            .start(easing);
    }
    
E
erik 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    /**
     * 复制样式
     * 
     * @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];
        }
    }

K
kener 已提交
97 98 99 100 101 102 103 104 105 106
    /**
     * 方型动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
    function rectangle(zr, oldShape, newShape, duration, easing) {
E
erik 已提交
107
        var newShapeStyle = newShape.style;
K
kener 已提交
108 109
        if (!oldShape) {        // add
            oldShape = {
K
kener 已提交
110
                position : newShape.position,
K
kener 已提交
111
                style : {
E
erik 已提交
112
                    x : newShapeStyle.x,
K
kener 已提交
113
                    y : newShape._orient == 'vertical'
E
erik 已提交
114 115
                        ? newShapeStyle.y + newShapeStyle.height
                        : newShapeStyle.y,
K
kener 已提交
116
                    width: newShape._orient == 'vertical' 
E
erik 已提交
117
                           ? newShapeStyle.width : 0,
K
kener 已提交
118
                    height: newShape._orient != 'vertical' 
E
erik 已提交
119
                           ? newShapeStyle.height : 0
K
kener 已提交
120 121 122 123
                }
            };
        }
        
E
erik 已提交
124 125 126 127
        var newX = newShapeStyle.x;
        var newY = newShapeStyle.y;
        var newWidth = newShapeStyle.width;
        var newHeight = newShapeStyle.height;
K
kener 已提交
128
        var newPosition = [newShape.position[0], newShape.position[1]];
E
erik 已提交
129 130 131 132
        cloneStyle(
            newShape, oldShape,
            'x', 'y', 'width', 'height'
        );
K
kener 已提交
133
        newShape.position = oldShape.position;
E
erik 已提交
134

K
kener 已提交
135
        zr.addShape(newShape);
K
kener 已提交
136 137 138 139 140 141 142 143 144 145 146
        if (newPosition[0] != oldShape.position[0] || newPosition[1] != oldShape.position[1]) {
            zr.animate(newShape.id, '')
                .when(
                    duration,
                    {
                        position: newPosition
                    }
                )
                .start(easing);
        }
        
L
lang 已提交
147
        newShape.__animating = true;
K
kener 已提交
148 149 150 151 152 153 154 155 156 157
        zr.animate(newShape.id, 'style')
            .when(
                duration,
                {
                    x: newX,
                    y: newY,
                    width: newWidth,
                    height: newHeight
                }
            )
K
Kener 已提交
158
            .done(function() {
L
lang 已提交
159
                newShape.__animating = false;
K
Kener 已提交
160
            })
K
kener 已提交
161 162 163 164 165 166 167 168 169 170 171 172 173
            .start(easing);
    }
    
    /**
     * 蜡烛动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
    function candle(zr, oldShape, newShape, duration, easing) {
K
kener 已提交
174 175 176 177 178
        if (!oldShape) {        // add
            var y = newShape.style.y;
            oldShape = {style : {y : [y[0], y[0], y[0], y[0]]}};
        }
        
K
kener 已提交
179 180 181
        var newY = newShape.style.y;
        newShape.style.y = oldShape.style.y;
        zr.addShape(newShape);
L
lang 已提交
182
        newShape.__animating = true;
K
kener 已提交
183 184 185 186 187
        zr.animate(newShape.id, 'style')
            .when(
                duration,
                { y: newY }
            )
K
Kener 已提交
188
            .done(function() {
L
lang 已提交
189
                newShape.__animating = false;
K
Kener 已提交
190
            })
K
kener 已提交
191 192
            .start(easing);
    }
193

K
kener 已提交
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
    /**
     * 环型动画
     * 
     * @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;
        
L
lang 已提交
209
        newShape.__animating = true;
K
Kener 已提交
210

K
kener 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224
        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
                    }
                )
K
Kener 已提交
225
                .done(function() {
L
lang 已提交
226
                    newShape.__animating = false;
K
Kener 已提交
227
                })
K
kener 已提交
228 229 230
                .start(easing);
            zr.animate(newShape.id, '')
                .when(
231
                    duration,
K
kener 已提交
232 233 234 235 236
                    { rotation : [0, x, y] }
                )
                .start(easing);
        }
        else {
K
kener 已提交
237
            newShape.style.r0 = newShape.style.r;
K
kener 已提交
238 239 240 241 242 243 244 245 246
            
            zr.addShape(newShape);
            zr.animate(newShape.id, 'style')
                .when(
                    duration,
                    {
                        r0 : r0
                    }
                )
K
Kener 已提交
247
                .done(function() {
L
lang 已提交
248
                    newShape.__animating = false;
K
Kener 已提交
249
                })
K
kener 已提交
250 251
                .start(easing);
        }
K
kener 已提交
252 253 254 255 256 257 258 259 260 261 262 263
    }
    
    /**
     * 扇形动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
    function sector(zr, oldShape, newShape, duration, easing) {
K
kener 已提交
264 265 266 267 268 269 270 271 272 273 274 275 276 277
        if (!oldShape) {        // add
            if (newShape._animationAdd != 'r') {
                oldShape = {
                    style : {
                        startAngle : newShape.style.startAngle,
                        endAngle : newShape.style.startAngle
                    }
                };
            }
            else {
                oldShape = {style : {r0 : newShape.style.r}};
            }
        }
        
K
kener 已提交
278 279
        var startAngle = newShape.style.startAngle;
        var endAngle = newShape.style.endAngle;
K
kener 已提交
280
        
E
erik 已提交
281 282 283 284
        cloneStyle(
            newShape, oldShape,
            'startAngle', 'endAngle'
        );
K
kener 已提交
285
        
K
kener 已提交
286
        zr.addShape(newShape);
L
lang 已提交
287
        newShape.__animating = true;
K
kener 已提交
288 289 290 291 292 293 294 295
        zr.animate(newShape.id, 'style')
            .when(
                duration,
                {
                    startAngle : startAngle,
                    endAngle : endAngle
                }
            )
K
Kener 已提交
296
            .done(function() {
L
lang 已提交
297
                newShape.__animating = false;
K
Kener 已提交
298
            })
K
kener 已提交
299 300 301 302 303 304 305 306 307 308 309 310 311
            .start(easing);
    }
    
    /**
     * 文本动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
    function text(zr, oldShape, newShape, duration, easing) {
K
kener 已提交
312 313 314 315 316 317 318 319 320 321 322
        if (!oldShape) {        // add
            oldShape = {
                style : {
                    x : newShape.style.textAlign == 'left' 
                        ? newShape.style.x + 100
                        : newShape.style.x - 100,
                    y : newShape.style.y
                }
            };
        }
        
K
kener 已提交
323 324
        var x = newShape.style.x;
        var y = newShape.style.y;
K
kener 已提交
325
        
E
erik 已提交
326 327 328 329
        cloneStyle(
            newShape, oldShape,
            'x', 'y'
        );
K
kener 已提交
330
        
K
kener 已提交
331
        zr.addShape(newShape);
L
lang 已提交
332
        newShape.__animating = true;
K
kener 已提交
333 334 335 336 337 338 339 340
        zr.animate(newShape.id, 'style')
            .when(
                duration,
                {
                    x : x,
                    y : y
                }
            )
K
Kener 已提交
341
            .done(function() {
L
lang 已提交
342
                newShape.__animating = false;
K
Kener 已提交
343
            })
K
kener 已提交
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
            .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;
K
kener 已提交
360
        
K
kener 已提交
361 362
        newShape.scale = [0.1, 0.1, x, y];
        zr.addShape(newShape);
L
lang 已提交
363
        newShape.__animating = true;
K
kener 已提交
364 365 366 367 368 369 370
        zr.animate(newShape.id, '')
            .when(
                duration,
                {
                    scale : [1, 1, x, y]
                }
            )
K
Kener 已提交
371
            .done(function() {
L
lang 已提交
372
                newShape.__animating = false;
K
Kener 已提交
373
            })
K
kener 已提交
374 375 376 377 378 379 380 381 382 383 384 385
            .start(easing);
    }
    
    /**
     * 和弦动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
L
lang 已提交
386
    function ribbon(zr, oldShape, newShape, duration, easing) {
K
kener 已提交
387 388 389
        if (!oldShape) {        // add
            oldShape = {
                style : {
L
lang 已提交
390 391 392 393
                    source0 : 0,
                    source1 : newShape.style.source1 > 0 ? 360 : -360,
                    target0 : 0,
                    target1 : newShape.style.target1 > 0 ? 360 : -360
K
kener 已提交
394 395 396 397
                }
            };
        }
        
K
kener 已提交
398 399 400 401 402 403
        var source0 = newShape.style.source0;
        var source1 = newShape.style.source1;
        var target0 = newShape.style.target0;
        var target1 = newShape.style.target1;
        
        if (oldShape.style) {
E
erik 已提交
404 405 406 407
            cloneStyle(
                newShape, oldShape,
                'source0', 'source1', 'target0', 'target1'
            );
K
kener 已提交
408
        }
K
kener 已提交
409 410
        
        zr.addShape(newShape);
L
lang 已提交
411
        newShape.__animating = true;
K
kener 已提交
412 413 414 415 416 417 418 419 420 421
        zr.animate(newShape.id, 'style')
            .when(
                duration,
                {
                    source0 : source0,
                    source1 : source1,
                    target0 : target0,
                    target1 : target1
                }
            )
K
Kener 已提交
422
            .done(function() {
L
lang 已提交
423
                newShape.__animating = false;
K
Kener 已提交
424
            })
K
kener 已提交
425 426
            .start(easing);
    }
K
kener 已提交
427 428 429 430 431 432 433 434 435 436 437
    
    /**
     * gaugePointer动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
    function gaugePointer(zr, oldShape, newShape, duration, easing) {
K
kener 已提交
438 439 440 441 442 443 444 445
        if (!oldShape) {        // add
            oldShape = {
                style : {
                    angle : newShape.style.startAngle
                }
            };
        }
        
K
kener 已提交
446 447 448
        var angle = newShape.style.angle;
        newShape.style.angle = oldShape.style.angle;
        zr.addShape(newShape);
L
lang 已提交
449
        newShape.__animating = true;
K
kener 已提交
450 451 452 453 454 455 456
        zr.animate(newShape.id, 'style')
            .when(
                duration,
                {
                    angle : angle
                }
            )
K
Kener 已提交
457
            .done(function() {
L
lang 已提交
458
                newShape.__animating = false;
K
Kener 已提交
459
            })
K
kener 已提交
460 461
            .start(easing);
    }
K
kener 已提交
462 463 464 465 466 467 468 469 470 471
    
    /**
     * icon动画
     * 
     * @param {ZRender} zr
     * @param {shape} oldShape
     * @param {shape} newShape
     * @param {number} duration
     * @param {tring} easing
     */
K
kener 已提交
472
    function icon(zr, oldShape, newShape, duration, easing, delay) {
K
kener 已提交
473 474 475 476 477
        // 避免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;
E
erik 已提交
478

K
kener 已提交
479 480 481
        if (!oldShape) {    // add
            var x = newShape._x || 0;
            var y = newShape._y || 0;
K
kener 已提交
482
            newShape.scale = [0.01, 0.01, x, y];
K
kener 已提交
483
            zr.addShape(newShape);
L
lang 已提交
484
            newShape.__animating = true;
K
kener 已提交
485
            zr.animate(newShape.id, '')
K
kener 已提交
486
                .delay(delay)
K
kener 已提交
487 488 489 490
                .when(
                    duration,
                    {scale : [1, 1, x, y]}
                )
K
Kener 已提交
491
                .done(function() {
L
lang 已提交
492
                    newShape.__animating = false;
K
Kener 已提交
493
                })
K
kener 已提交
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
                .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 : {
K
kener 已提交
514 515
                    xStart : newShape.style.xStart,
                    yStart : newShape.style.yStart,
K
kener 已提交
516 517 518
                    xEnd : newShape.style.xStart,
                    yEnd : newShape.style.yStart
                }
K
kener 已提交
519
            };
K
kener 已提交
520 521 522 523 524 525
        }
        
        var xStart = newShape.style.xStart;
        var xEnd = newShape.style.xEnd;
        var yStart = newShape.style.yStart;
        var yEnd = newShape.style.yEnd;
E
erik 已提交
526 527 528 529 530 531

        cloneStyle(
            newShape, oldShape,
            'xStart', 'xEnd', 'yStart', 'yEnd'
        );

K
kener 已提交
532
        zr.addShape(newShape);
L
lang 已提交
533
        newShape.__animating = true;
K
kener 已提交
534 535 536 537 538 539 540 541 542 543
        zr.animate(newShape.id, 'style')
            .when(
                duration,
                {
                    xStart: xStart,
                    xEnd: xEnd,
                    yStart: yStart,
                    yEnd: yEnd
                }
            )
K
Kener 已提交
544
            .done(function() {
L
lang 已提交
545
                newShape.__animating = false;
K
Kener 已提交
546
            })
K
kener 已提交
547 548 549 550 551 552 553 554 555 556 557 558 559
            .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) {
560
        easing = easing || 'QuinticOut';
L
lang 已提交
561
        newShape.__animating = true;
562 563 564 565
        zr.addShape(newShape);
        var newShapeStyle = newShape.style;

        var animationDone = function () {
L
lang 已提交
566
            newShape.__animating = false;
L
lang 已提交
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
        };
        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);
594
        }
L
lang 已提交
595
        else {
596
            zr.animate(newShape.id, 'style')
597
                .when(0, {
L
lang 已提交
598 599
                    xEnd: x0,
                    yEnd: y0
K
Kener 已提交
600
                })
601
                .when(duration, {
L
lang 已提交
602 603
                    xEnd: x2,
                    yEnd: y2
604 605 606
                })
                .done(animationDone)
                .start(easing);
K
kener 已提交
607 608
        }
    }
K
kener 已提交
609

K
kener 已提交
610 611 612 613 614 615 616 617
    return {
        pointList : pointList,
        rectangle : rectangle,
        candle : candle,
        ring : ring,
        sector : sector,
        text : text,
        polygon : polygon,
L
lang 已提交
618
        ribbon : ribbon,
K
kener 已提交
619 620 621 622
        gaugePointer : gaugePointer,
        icon : icon,
        line : line,
        markline : markline
K
kener 已提交
623
    };
K
kener 已提交
624
});