echarts.js 63.1 KB
Newer Older
K
kener 已提交
1 2 3
/*!
 * ECharts, a javascript interactive chart library.
 *  
K
kener 已提交
4
 * Copyright (c) 2014, Baidu Inc.
K
kener 已提交
5 6
 * All rights reserved.
 * 
K
kener 已提交
7 8
 * LICENSE
 * https://github.com/ecomfe/echarts/blob/master/LICENSE.txt
K
kener 已提交
9 10
 */

K
kener 已提交
11 12 13 14
/**
 * echarts
 *
 * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
K
kener 已提交
15
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
K
kener 已提交
16 17
 *
 */
K
kener 已提交
18
define(function (require) {
K
kener 已提交
19
    var ecConfig = require('./config');
K
kener 已提交
20
    var zrUtil = require('zrender/tool/util');
L
lang 已提交
21
    var zrEvent = require('zrender/tool/event');
K
kener 已提交
22
    
K
kener 已提交
23
    var self = {};
K
kener 已提交
24
    
K
kener 已提交
25
    var _canvasSupported = require('zrender/tool/env').canvasSupported;
K
kener 已提交
26
    var _idBase = new Date() - 0;
K
kener 已提交
27
    var _instances = {};    // ECharts实例map索引
K
kener 已提交
28 29
    var DOM_ATTRIBUTE_KEY = '_echarts_instance_';
    
K
2.1.10  
kener 已提交
30
    self.version = '2.1.10';
K
kener 已提交
31
    self.dependencies = {
K
kener 已提交
32
        zrender: '2.0.6'
K
kener 已提交
33
    };
K
kener 已提交
34 35 36
    /**
     * 入口方法 
     */
K
kener 已提交
37
    self.init = function (dom, theme) {
K
kener 已提交
38 39 40 41 42 43 44 45 46 47 48 49
        var zrender = require('zrender');
        if (((zrender.version || '1.0.3').replace('.', '') - 0)
            < (self.dependencies.zrender.replace('.', '') - 0)
        ) {
            console.error(
                'ZRender ' + (zrender.version || '1.0.3-') 
                + ' is too old for ECharts ' + self.version 
                + '. Current version need ZRender ' 
                + self.dependencies.zrender + '+'
            );
        }
            
K
kener 已提交
50
        dom = dom instanceof Array ? dom[0] : dom;
51

K
kener 已提交
52 53 54
        // dom与echarts实例映射索引
        var key = dom.getAttribute(DOM_ATTRIBUTE_KEY);
        if (!key) {
K
kener 已提交
55
            key = _idBase++;
K
kener 已提交
56 57
            dom.setAttribute(DOM_ATTRIBUTE_KEY, key);
        }
58

59 60 61 62 63
        if (_instances[key]) {
            // 同一个dom上多次init,自动释放已有实例
            _instances[key].dispose();
        }
        _instances[key] = new Echarts(dom);
K
kener 已提交
64
        _instances[key].id = key;
65
        _instances[key].canvasSupported = _canvasSupported;
K
kener 已提交
66 67
        _instances[key].setTheme(theme);
        
K
kener 已提交
68
        return  _instances[key];
K
kener 已提交
69
    };
K
kener 已提交
70 71 72 73
    
    /**
     * 通过id获得ECharts实例,id可在实例化后读取 
     */
K
kener 已提交
74
    self.getInstanceById = function (key) {
K
kener 已提交
75
        return _instances[key];
K
kener 已提交
76
    };
K
kener 已提交
77

L
lang 已提交
78 79 80 81 82 83 84 85
    /**
     * 消息中心
     */
    function MessageCenter() {
        zrEvent.Dispatcher.call(this);
    }
    zrUtil.merge(MessageCenter.prototype, zrEvent.Dispatcher.prototype, true);

K
kener 已提交
86 87 88 89
    /**
     * 基于zrender实现Echarts接口层
     * @param {HtmlElement} dom 必要
     */
K
kener 已提交
90
    function Echarts(dom) {
K
kener 已提交
91
        this._themeConfig = zrUtil.clone(ecConfig);
K
kener 已提交
92 93 94

        this.dom = dom;
        // this._zr;
K
kener 已提交
95
        // this._option;                    // curOption clone
K
kener 已提交
96 97 98
        // this._optionRestore;             // for restore;
        // this._island;
        // this._toolbox;
K
kener 已提交
99
        // this._timeline;
K
kener 已提交
100 101 102 103
        // this._refreshInside;             // 内部刷新标志位
        
        this._connected = false;
        this._status = {                    // 用于图表间通信
K
kener 已提交
104 105 106
            dragIn: false,
            dragOut: false,
            needRefresh: false
K
kener 已提交
107
        };
K
kener 已提交
108
        this._curEventType = false;         // 破循环信号灯
K
kener 已提交
109
        this._chartList = [];               // 图表实例
L
lang 已提交
110 111 112 113

        this._messageCenter = new MessageCenter();

        this._messageCenterOutSide = new MessageCenter();    // Echarts层的外部消息中心,做Echarts层的消息转发
K
kener 已提交
114 115 116
        
        // resize方法经常被绑定到window.resize上,闭包一个this
        this.resize = this.resize();
K
kener 已提交
117
        
K
kener 已提交
118
        // 初始化::构造函数
K
kener 已提交
119 120 121
        this._init();
    }
    
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
    /**
     * ZRender EVENT
     * 
     * @inner
     * @const
     * @type {Object}
     */
    var ZR_EVENT = require('zrender/config').EVENT;

    /**
     * 要绑定监听的zrender事件列表
     * 
     * @const
     * @inner
     * @type {Array}
     */
    var ZR_EVENT_LISTENS = [
K
kener 已提交
139
        'CLICK', 'DBLCLICK', 'MOUSEOVER', 'MOUSEOUT',
140 141 142
        'DRAGSTART', 'DRAGEND', 'DRAGENTER', 'DRAGOVER', 'DRAGLEAVE', 'DROP'
    ];

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    /**
     * 对echarts的实例中的chartList属性成员,逐个进行方法调用,遍历顺序为逆序
     * 由于在事件触发的默认行为处理中,多次用到相同逻辑,所以抽象了该方法
     * 由于所有的调用场景里,最多只有两个参数,基于性能和体积考虑,这里就不使用call或者apply了
     * 
     * @inner
     * @param {ECharts} ecInstance ECharts实例
     * @param {string} methodName 要调用的方法名
     * @param {*} arg0 调用参数1
     * @param {*} arg1 调用参数2
     * @param {*} arg2 调用参数3
     */
    function callChartListMethodReverse(ecInstance, methodName, arg0, arg1, arg2) {
        var chartList = ecInstance._chartList;
        var len = chartList.length;

        while (len--) {
            var chart = chartList[len];
            if (typeof chart[methodName] === 'function') {
                chart[methodName](arg0, arg1, arg2);
            }
        }
    }
166

K
kener 已提交
167
    Echarts.prototype = {
K
kener 已提交
168 169 170
        /**
         * 初始化::构造函数
         */ 
K
kener 已提交
171
        _init: function () {
K
kener 已提交
172
            var self = this;
K
kener 已提交
173 174
            var _zr = require('zrender').init(this.dom);
            this._zr = _zr;
K
kener 已提交
175
            
K
kener 已提交
176
            // wrap: n,e,d,t for name event data this
L
lang 已提交
177
            this._messageCenter.dispatch = function(type, event, eventPackage, that) {
K
kener 已提交
178
                eventPackage = eventPackage || {};
L
lang 已提交
179 180 181 182
                eventPackage.type = type;
                eventPackage.event = event;

                self._messageCenter.dispatchWithContext(type, eventPackage, that);
K
kener 已提交
183
                if (type != 'HOVER' && type != 'MOUSEOUT') {    // 频繁事件直接抛出
K
kener 已提交
184
                    setTimeout(function(){
L
lang 已提交
185 186 187
                        self._messageCenterOutSide.dispatchWithContext(
                            type, eventPackage, that
                        );
K
kener 已提交
188 189 190
                    },50);
                }
                else {
L
lang 已提交
191 192 193
                    self._messageCenterOutSide.dispatchWithContext(
                        type, eventPackage, that
                    );
K
kener 已提交
194
                }
K
kener 已提交
195
            };
K
kener 已提交
196
            
K
kener 已提交
197 198 199
            this._onevent = function(param){
                return self.__onevent(param);
            };
K
kener 已提交
200
            for (var e in ecConfig.EVENT) {
K
kener 已提交
201 202 203
                if (e != 'CLICK' && e != 'DBLCLICK' 
                    && e != 'HOVER' && e != 'MOUSEOUT' && e != 'MAP_ROAM'
                ) {
L
lang 已提交
204
                    this._messageCenter.bind(ecConfig.EVENT[e], this._onevent, this);
K
kener 已提交
205 206
                }
            }
K
kener 已提交
207

208

K
kener 已提交
209
            var eventBehaviors = {};
210 211
            this._onzrevent = function (param) {
                return self[eventBehaviors[ param.type ]](param);
K
kener 已提交
212
            };
213 214 215

            // 挂载关心的事件
            for (var i = 0, len = ZR_EVENT_LISTENS.length; i < len; i++) {
K
kener 已提交
216
                var eventName = ZR_EVENT_LISTENS[i];
217 218 219 220
                var eventValue = ZR_EVENT[eventName];
                eventBehaviors[eventValue] = '_on' + eventName.toLowerCase();
                _zr.on(eventValue, this._onzrevent);
            }
K
kener 已提交
221

K
kener 已提交
222 223
            this.chart = {};            // 图表索引
            this.component = {};        // 组件索引
224
            
K
kener 已提交
225
            // 内置图表
226
            // 孤岛
K
kener 已提交
227
            var Island = require('./chart/island');
K
kener 已提交
228
            this._island = new Island(this._themeConfig, this._messageCenter, _zr, {}, this);
229
            this.chart.island = this._island;
230
            
K
kener 已提交
231
            // 内置通用组件
232
            // 工具箱
K
kener 已提交
233
            var Toolbox = require('./component/toolbox');
K
kener 已提交
234
            this._toolbox = new Toolbox(this._themeConfig, this._messageCenter, _zr, {}, this);
235
            this.component.toolbox = this._toolbox;
236
            
237 238 239 240
            var componentLibrary = require('./component');
            componentLibrary.define('title', require('./component/title'));
            componentLibrary.define('tooltip', require('./component/tooltip'));
            componentLibrary.define('legend', require('./component/legend'));
K
kener 已提交
241
            
K
kener 已提交
242
            if (_zr.getWidth() === 0 || _zr.getHeight() === 0) {
K
kener 已提交
243 244
                console.error('Dom’s width & height should be ready before init.');
            }
K
kener 已提交
245
        },
K
kener 已提交
246

K
kener 已提交
247 248 249
        /**
         * ECharts事件处理中心 
         */
K
kener 已提交
250
        __onevent: function (param){
K
kener 已提交
251
            param.__echartsId = param.__echartsId || this.id;
E
erik 已提交
252 253

            // 来自其他联动图表的事件
K
kener 已提交
254
            var fromMyself = (param.__echartsId === this.id);
K
kener 已提交
255
            
K
kener 已提交
256 257
            if (!this._curEventType) {
                this._curEventType = param.type;
K
kener 已提交
258 259
            }
            
E
erik 已提交
260
            switch (param.type) {
K
kener 已提交
261
                case ecConfig.EVENT.LEGEND_SELECTED :
K
kener 已提交
262
                    this._onlegendSelected(param);
K
kener 已提交
263 264 265
                    break;
                case ecConfig.EVENT.DATA_ZOOM :
                    if (!fromMyself) {
K
kener 已提交
266
                        var dz = this.component.dataZoom;
K
kener 已提交
267 268 269 270 271 272
                        if (dz) {
                            dz.silence(true);
                            dz.absoluteZoom(param.zoom);
                            dz.silence(false);
                        }
                    }
K
kener 已提交
273
                    this._ondataZoom(param);
K
kener 已提交
274 275
                    break;        
                case ecConfig.EVENT.DATA_RANGE :
K
kener 已提交
276
                    fromMyself && this._ondataRange(param);
K
kener 已提交
277 278 279
                    break;        
                case ecConfig.EVENT.MAGIC_TYPE_CHANGED :
                    if (!fromMyself) {
K
kener 已提交
280
                        var tb = this.component.toolbox;
K
kener 已提交
281 282 283 284 285 286
                        if (tb) {
                            tb.silence(true);
                            tb.setMagicType(param.magicType);
                            tb.silence(false);
                        }
                    }
K
kener 已提交
287
                    this._onmagicTypeChanged(param);
K
kener 已提交
288 289
                    break;        
                case ecConfig.EVENT.DATA_VIEW_CHANGED :
K
kener 已提交
290
                    fromMyself && this._ondataViewChanged(param);
K
kener 已提交
291 292
                    break;        
                case ecConfig.EVENT.TOOLTIP_HOVER :
K
kener 已提交
293
                    fromMyself && this._tooltipHover(param);
K
kener 已提交
294 295
                    break;        
                case ecConfig.EVENT.RESTORE :
K
kener 已提交
296
                    this._onrestore();
K
kener 已提交
297 298
                    break;        
                case ecConfig.EVENT.REFRESH :
K
kener 已提交
299
                    fromMyself && this._onrefresh(param);
K
kener 已提交
300 301 302
                    break;
                // 鼠标同步
                case ecConfig.EVENT.TOOLTIP_IN_GRID :
303 304
                case ecConfig.EVENT.TOOLTIP_OUT_GRID :
                    if (!fromMyself) {
K
kener 已提交
305
                        // 只处理来自外部的鼠标同步
K
kener 已提交
306
                        var grid = this.component.grid;
K
kener 已提交
307
                        if (grid) {
K
kener 已提交
308
                            this._zr.trigger(
K
kener 已提交
309 310
                                'mousemove',
                                {
K
kener 已提交
311 312 313
                                    connectTrigger: true,
                                    zrenderX: grid.getX() + param.x * grid.getWidth(),
                                    zrenderY: grid.getY() + param.y * grid.getHeight()
K
kener 已提交
314 315 316
                                }
                            );
                        }
317
                    } 
K
kener 已提交
318
                    else if (this._connected) {
319
                        // 来自自己,并且存在多图联动,空间坐标映射修改参数分发
K
kener 已提交
320
                        var grid = this.component.grid;
321 322 323 324
                        if (grid) {
                            param.x = (param.event.zrenderX - grid.getX()) / grid.getWidth();
                            param.y = (param.event.zrenderY - grid.getY()) / grid.getHeight();
                        }
K
kener 已提交
325 326 327 328 329 330 331 332 333 334 335 336
                    }
                    break;
                /*
                case ecConfig.EVENT.RESIZE :
                case ecConfig.EVENT.DATA_CHANGED :
                case ecConfig.EVENT.PIE_SELECTED :
                case ecConfig.EVENT.MAP_SELECTED :
                    break;
                */
            }
            
            // 多图联动,只做自己的一级事件分发,避免级联事件循环
K
kener 已提交
337
            if (this._connected && fromMyself && this._curEventType === param.type) { 
K
kener 已提交
338 339
                for (var c in this._connected) {
                    this._connected[c].connectedEventHandler(param);
K
kener 已提交
340 341
                }
                // 分发完毕后复位
K
kener 已提交
342
                this._curEventType = null;
K
kener 已提交
343 344
            }
            
K
kener 已提交
345 346
            if (!fromMyself || (!this._connected && fromMyself)) {  // 处理了完联动事件复位
                this._curEventType = null;
K
kener 已提交
347
            }
K
kener 已提交
348
        },
349

K
kener 已提交
350 351 352
        /**
         * 点击事件,响应zrender事件,包装后分发到Echarts层
         */
K
kener 已提交
353
        _onclick: function (param) {
354 355
            callChartListMethodReverse(this, 'onclick', param);

K
kener 已提交
356
            if (param.target) {
K
kener 已提交
357
                var ecData = this._eventPackage(param.target);
358
                if (ecData && ecData.seriesIndex != null) {
K
kener 已提交
359
                    this._messageCenter.dispatch(
K
kener 已提交
360 361
                        ecConfig.EVENT.CLICK,
                        param.event,
K
kener 已提交
362 363
                        ecData,
                        this
K
kener 已提交
364 365
                    );
                }
K
kener 已提交
366 367 368 369 370 371
            }
        },
        
        /**
         * 双击事件,响应zrender事件,包装后分发到Echarts层
         */
K
kener 已提交
372
        _ondblclick: function (param) {
K
kener 已提交
373 374 375 376 377 378 379 380 381 382 383 384
            callChartListMethodReverse(this, 'ondblclick', param);

            if (param.target) {
                var ecData = this._eventPackage(param.target);
                if (ecData && ecData.seriesIndex != null) {
                    this._messageCenter.dispatch(
                        ecConfig.EVENT.DBLCLICK,
                        param.event,
                        ecData,
                        this
                    );
                }
K
kener 已提交
385
            }
K
kener 已提交
386
        },
K
kener 已提交
387

K
kener 已提交
388 389 390
        /**
         * 鼠标移入事件,响应zrender事件,包装后分发到Echarts层
         */
K
kener 已提交
391
        _onmouseover: function (param) {
K
kener 已提交
392
            if (param.target) {
K
kener 已提交
393
                var ecData = this._eventPackage(param.target);
394
                if (ecData && ecData.seriesIndex != null) {
K
kener 已提交
395
                    this._messageCenter.dispatch(
K
kener 已提交
396 397
                        ecConfig.EVENT.HOVER,
                        param.event,
K
kener 已提交
398 399
                        ecData,
                        this
K
kener 已提交
400 401 402
                    );
                }
            }
K
kener 已提交
403
        },
K
kener 已提交
404 405 406 407
        
        /**
         * 鼠标移出事件,响应zrender事件,包装后分发到Echarts层
         */
K
kener 已提交
408
        _onmouseout: function (param) {
K
kener 已提交
409 410 411 412 413 414 415 416 417 418 419 420
            if (param.target) {
                var ecData = this._eventPackage(param.target);
                if (ecData && ecData.seriesIndex != null) {
                    this._messageCenter.dispatch(
                        ecConfig.EVENT.MOUSEOUT,
                        param.event,
                        ecData,
                        this
                    );
                }
            }
        },
K
kener 已提交
421 422 423 424

        /**
         * dragstart回调,可计算特性实现
         */
K
kener 已提交
425
        _ondragstart: function (param) {
K
kener 已提交
426
            // 复位用于图表间通信拖拽标识
K
kener 已提交
427
            this._status = {
K
kener 已提交
428 429 430
                dragIn: false,
                dragOut: false,
                needRefresh: false
K
kener 已提交
431
            };
432 433

            callChartListMethodReverse(this, 'ondragstart', param);
K
kener 已提交
434
        },
K
kener 已提交
435 436 437 438

        /**
         * dragging回调,可计算特性实现
         */
K
kener 已提交
439
        _ondragenter: function (param) {
440
            callChartListMethodReverse(this, 'ondragenter', param);
K
kener 已提交
441
        },
K
kener 已提交
442 443 444 445

        /**
         * dragstart回调,可计算特性实现
         */
K
kener 已提交
446
        _ondragover: function (param) {
447
            callChartListMethodReverse(this, 'ondragover', param);
K
kener 已提交
448 449
        },
        
K
kener 已提交
450 451 452
        /**
         * dragstart回调,可计算特性实现
         */
K
kener 已提交
453
        _ondragleave: function (param) {
454
            callChartListMethodReverse(this, 'ondragleave', param);
K
kener 已提交
455
        },
K
kener 已提交
456 457 458 459

        /**
         * dragstart回调,可计算特性实现
         */
K
kener 已提交
460
        _ondrop: function (param) {
461
            callChartListMethodReverse(this, 'ondrop', param, this._status);
K
kener 已提交
462 463
            this._island.ondrop(param, this._status);
        },
K
kener 已提交
464 465 466 467

        /**
         * dragdone回调 ,可计算特性实现
         */
K
kener 已提交
468
        _ondragend: function (param) {
469 470
            callChartListMethodReverse(this, 'ondragend', param, this._status);

K
kener 已提交
471
            this._timeline && this._timeline.ondragend(param, this._status);
K
kener 已提交
472
            this._island.ondragend(param, this._status);
K
kener 已提交
473 474

            // 发生过重计算
K
kener 已提交
475
            if (this._status.needRefresh) {
476
                this._syncBackupData(this._option);
477 478 479

                var messageCenter = this._messageCenter;
                messageCenter.dispatch(
K
kener 已提交
480 481
                    ecConfig.EVENT.DATA_CHANGED,
                    param.event,
K
kener 已提交
482 483
                    this._eventPackage(param.target),
                    this
K
kener 已提交
484
                );
485
                messageCenter.dispatch(ecConfig.EVENT.REFRESH, null, null, this);
K
kener 已提交
486
            }
K
kener 已提交
487
        },
K
kener 已提交
488

K
kener 已提交
489 490 491
        /**
         * 图例选择响应
         */
K
kener 已提交
492
        _onlegendSelected: function (param) {
K
kener 已提交
493
            // 用于图表间通信
K
kener 已提交
494
            this._status.needRefresh = false;
495 496
            callChartListMethodReverse(this, 'onlegendSelected', param, this._status);

K
kener 已提交
497
            if (this._status.needRefresh) {
K
kener 已提交
498
                this._messageCenter.dispatch(ecConfig.EVENT.REFRESH, null, null, this);
K
kener 已提交
499
            }
K
kener 已提交
500
        },
K
kener 已提交
501

K
kener 已提交
502 503 504
        /**
         * 数据区域缩放响应 
         */
K
kener 已提交
505
        _ondataZoom: function (param) {
K
kener 已提交
506
            // 用于图表间通信
K
kener 已提交
507
            this._status.needRefresh = false;
508
            callChartListMethodReverse(this, 'ondataZoom', param, this._status);
K
kener 已提交
509

K
kener 已提交
510
            if (this._status.needRefresh) {
K
kener 已提交
511
                this._messageCenter.dispatch(ecConfig.EVENT.REFRESH, null, null, this);
K
kener 已提交
512
            }
K
kener 已提交
513
        },
K
kener 已提交
514 515 516 517

        /**
         * 值域漫游响应 
         */
K
kener 已提交
518
        _ondataRange: function (param) {
K
kener 已提交
519
            this._clearEffect();
K
kener 已提交
520
            // 用于图表间通信
K
kener 已提交
521
            this._status.needRefresh = false;
522
            callChartListMethodReverse(this, 'ondataRange', param, this._status);
K
kener 已提交
523
            
K
kener 已提交
524
            // 没有相互影响,直接刷新即可
K
kener 已提交
525 526
            if (this._status.needRefresh) {
                this._zr.refresh();
K
kener 已提交
527
            }
K
kener 已提交
528
        },
K
kener 已提交
529

K
kener 已提交
530 531 532
        /**
         * 动态类型切换响应 
         */
K
kener 已提交
533
        _onmagicTypeChanged: function () {
K
kener 已提交
534
            this._clearEffect();
535
            this._render(this._toolbox.getMagicOption());
K
kener 已提交
536
        },
537 538 539 540

        /**
         * 数据视图修改响应 
         */
K
kener 已提交
541
        _ondataViewChanged: function (param) {
K
kener 已提交
542 543
            this._syncBackupData(param.option);
            this._messageCenter.dispatch(
544 545
                ecConfig.EVENT.DATA_CHANGED,
                null,
K
kener 已提交
546 547
                param,
                this
548
            );
K
kener 已提交
549
            this._messageCenter.dispatch(ecConfig.EVENT.REFRESH, null, null, this);
K
kener 已提交
550
        },
K
kener 已提交
551 552 553 554
        
        /**
         * tooltip与图表间通信 
         */
K
kener 已提交
555
        _tooltipHover: function (param) {
K
kener 已提交
556
            var tipShape = [];
557
            callChartListMethodReverse(this, 'ontooltipHover', param, tipShape);
K
kener 已提交
558
        },
559 560 561 562

        /**
         * 还原 
         */
K
kener 已提交
563
        _onrestore: function () {
K
kener 已提交
564 565
            this.restore();
        },
566 567 568 569

        /**
         * 刷新 
         */
K
kener 已提交
570
        _onrefresh: function (param) {
K
kener 已提交
571 572 573 574
            this._refreshInside = true;
            this.refresh(param);
            this._refreshInside = false;
        },
K
kener 已提交
575
        
576
        /**
577
         * 数据修改后的反向同步dataZoom持有的备份数据 
K
kener 已提交
578
         */
K
kener 已提交
579
        _syncBackupData: function (curOption) {
580
            this.component.dataZoom && this.component.dataZoom.syncBackupData(curOption);
K
kener 已提交
581
        },
K
kener 已提交
582

K
kener 已提交
583 584 585
        /**
         * 打包Echarts层的事件附件
         */
K
kener 已提交
586
        _eventPackage: function (target) {
K
kener 已提交
587 588
            if (target) {
                var ecData = require('./util/ecData');
589 590 591 592
                
                var seriesIndex = ecData.get(target, 'seriesIndex');
                var dataIndex = ecData.get(target, 'dataIndex');
                
K
kener 已提交
593
                dataIndex = seriesIndex != -1 && this.component.dataZoom
K
kener 已提交
594
                            ? this.component.dataZoom.getRealDataIndex(
595 596 597
                                seriesIndex,
                                dataIndex
                              )
K
kener 已提交
598
                            : dataIndex;
K
kener 已提交
599
                return {
K
kener 已提交
600
                    seriesIndex: seriesIndex,
K
kener 已提交
601
                    seriesName: (ecData.get(target, 'series') || {}).name,
K
kener 已提交
602 603 604 605 606
                    dataIndex: dataIndex,
                    data: ecData.get(target, 'data'),
                    name: ecData.get(target, 'name'),
                    value: ecData.get(target, 'value'),
                    special: ecData.get(target, 'special')
K
kener 已提交
607 608 609
                };
            }
            return;
K
kener 已提交
610
        },
K
kener 已提交
611

K
Kener 已提交
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
        _noDataCheck: function(magicOption) {
            var series = magicOption.series;
            for (var i = 0, l = series.length; i < l; i++) {
                if ((series[i].data && series[i].data.length > 0)
                    || (series[i].markPoint && series[i].markPoint.data && series[i].markPoint.data.length > 0)
                    || (series[i].markLine && series[i].markLine.data && series[i].markLine.data.length > 0)
                    || (series[i].nodes && series[i].nodes.length > 0)
                    || (series[i].links && series[i].links.length > 0)
                    || (series[i].matrix && series[i].matrix.length > 0)
                    || (series[i].eventList && series[i].eventList.length > 0)
                ) {
                    return false;   // 存在任意数据则为非空数据
                }
            }
            // 空数据
            this.clear();
            var loadOption = this._themeConfig.noDataLoadingOption || {
                text: this._themeConfig.noDataText,
                effect: this._themeConfig.noDataEffect
            };
            this.showLoading(loadOption);
            return true;
        },

K
kener 已提交
636 637 638
        /**
         * 图表渲染 
         */
K
kener 已提交
639
        _render: function (magicOption) {
K
kener 已提交
640
            this._mergeGlobalConifg(magicOption);
E
erik 已提交
641

K
Kener 已提交
642 643 644 645
            if (this._noDataCheck(magicOption)) {
                return;
            }

E
erik 已提交
646
            var bgColor = magicOption.backgroundColor;
E
erik 已提交
647
            if (bgColor) {
K
kener 已提交
648
                if (!_canvasSupported 
E
erik 已提交
649
                    && bgColor.indexOf('rgba') != -1
K
kener 已提交
650 651
                ) {
                    // IE6~8对RGBA的处理,filter会带来其他颜色的影响
E
erik 已提交
652
                    var cList = bgColor.split(',');
K
kener 已提交
653
                    this.dom.style.filter = 'alpha(opacity=' +
K
kener 已提交
654 655 656 657
                        cList[3].substring(0, cList[3].lastIndexOf(')')) * 100
                        + ')';
                    cList.length = 3;
                    cList[0] = cList[0].replace('a', '');
K
kener 已提交
658
                    this.dom.style.backgroundColor = cList.join(',') + ')';
K
kener 已提交
659 660
                }
                else {
E
erik 已提交
661
                    this.dom.style.backgroundColor = bgColor;
K
kener 已提交
662 663 664
                }
            }
            
K
kener 已提交
665
            this._zr.clearAnimation();
K
kener 已提交
666
            this._chartList = [];
K
kener 已提交
667 668 669

            var chartLibrary = require('./chart');
            var componentLibrary = require('./component');
670 671
            
            if (magicOption.xAxis || magicOption.yAxis) {
K
kener 已提交
672 673
                magicOption.grid = magicOption.grid || {};
                magicOption.dataZoom = magicOption.dataZoom || {};
674 675 676
            }
            
            var componentList = [
677
                'title', 'legend', 'tooltip', 'dataRange', 'roamController',
678 679 680 681 682 683 684 685
                'grid', 'dataZoom', 'xAxis', 'yAxis', 'polar'
            ];
            
            var ComponentClass;
            var componentType;
            var component;
            for (var i = 0, l = componentList.length; i < l; i++) {
                componentType = componentList[i];
E
erik 已提交
686 687
                component = this.component[componentType];

688
                if (magicOption[componentType]) {
E
erik 已提交
689 690
                    if (component) {
                        component.refresh && component.refresh(magicOption);
691 692 693
                    }
                    else {
                        ComponentClass = componentLibrary.get(
E
erik 已提交
694
                            /^[xy]Axis$/.test(componentType) ? 'axis' : componentType
695 696 697 698 699 700 701
                        );
                        component = new ComponentClass(
                            this._themeConfig, this._messageCenter, this._zr,
                            magicOption, this, componentType
                        );
                        this.component[componentType] = component;
                    }
E
erik 已提交
702
                    this._chartList.push(component);
703
                }
E
erik 已提交
704 705
                else if (component) {
                    component.dispose();
K
kener 已提交
706
                    this.component[componentType] = null;
K
jshint  
kener 已提交
707
                    delete this.component[componentType];
K
kener 已提交
708 709
                }
            }
K
kener 已提交
710 711 712 713

            var ChartClass;
            var chartType;
            var chart;
K
kener 已提交
714
            var chartMap = {};      // 记录已经初始化的图表
K
kener 已提交
715 716 717
            for (var i = 0, l = magicOption.series.length; i < l; i++) {
                chartType = magicOption.series[i].type;
                if (!chartType) {
718
                    console.error('series[' + i + '] chart type has not been defined.');
K
kener 已提交
719 720
                    continue;
                }
E
erik 已提交
721

K
kener 已提交
722 723 724 725
                if (!chartMap[chartType]) {
                    chartMap[chartType] = true;
                    ChartClass = chartLibrary.get(chartType);
                    if (ChartClass) {
K
kener 已提交
726 727 728 729 730 731 732
                        if (this.chart[chartType]) {
                            chart = this.chart[chartType];
                            chart.refresh(magicOption);
                        }
                        else {
                            chart = new ChartClass(
                                this._themeConfig, this._messageCenter, this._zr,
733
                                magicOption, this
K
kener 已提交
734 735
                            );
                        }
K
kener 已提交
736 737
                        this._chartList.push(chart);
                        this.chart[chartType] = chart;
K
kener 已提交
738
                    }
K
kener 已提交
739 740 741
                    else {
                        console.error(chartType + ' has not been required.');
                    }
742
                }
K
kener 已提交
743
            }
744
            
K
kener 已提交
745 746 747 748 749 750 751 752
            // 已有实例但新option不带这类图表的实例释放
            for (chartType in this.chart) {
                if (chartType != ecConfig.CHART_TYPE_ISLAND  && !chartMap[chartType]) {
                    this.chart[chartType].dispose();
                    this.chart[chartType] = null;
                    delete this.chart[chartType];
                }
            }
K
kener 已提交
753 754
            
            this.component.grid && this.component.grid.refixAxisShape(this.component);
K
kener 已提交
755

K
kener 已提交
756 757
            this._island.refresh(magicOption);
            this._toolbox.refresh(magicOption);
K
kener 已提交
758
            
K
kener 已提交
759 760
            magicOption.animation && !magicOption.renderAsImage
                ? this._zr.refresh()
K
jshint  
kener 已提交
761
                : this._zr.render();
K
kener 已提交
762
            
K
kener 已提交
763
            var imgId = 'IMG' + this.id;
K
kener 已提交
764
            var img = document.getElementById(imgId);
K
kener 已提交
765
            if (magicOption.renderAsImage && _canvasSupported) {
K
kener 已提交
766 767
                // IE8- 不支持图片渲染形式
                if (img) {
K
kener 已提交
768
                    // 已经渲染过则更新显示
K
kener 已提交
769
                    img.src = this.getDataURL(magicOption.renderAsImage);
K
kener 已提交
770 771 772
                }
                else {
                    // 没有渲染过插入img dom
K
kener 已提交
773
                    img = this.getImage(magicOption.renderAsImage);
K
kener 已提交
774 775 776 777
                    img.id = imgId;
                    img.style.position = 'absolute';
                    img.style.left = 0;
                    img.style.top = 0;
K
kener 已提交
778
                    this.dom.firstChild.appendChild(img);
K
kener 已提交
779
                }
K
kener 已提交
780 781 782 783
                this.un();
                this._zr.un();
                this._disposeChartList();
                this._zr.clear();
K
kener 已提交
784 785 786 787 788 789
            }
            else if (img) {
                // 删除可能存在的img
                img.parentNode.removeChild(img);
            }
            img = null;
790 791
            
            this._option = magicOption;
K
kener 已提交
792
        },
K
kener 已提交
793

K
kener 已提交
794 795 796
        /**
         * 还原 
         */
K
kener 已提交
797
        restore: function () {
K
kener 已提交
798
            this._clearEffect();
K
kener 已提交
799
            this._option = zrUtil.clone(this._optionRestore);
K
kener 已提交
800
            this._disposeChartList();
K
kener 已提交
801
            this._island.clear();
K
kener 已提交
802
            this._toolbox.reset(this._option, true);
K
kener 已提交
803 804
            this._render(this._option);
        },
K
kener 已提交
805 806 807

        /**
         * 刷新 
K
kener 已提交
808
         * @param {Object=} param,可选参数,用于附带option,内部同步用,外部不建议带入数据修改,无法同步 
K
kener 已提交
809
         */
K
kener 已提交
810
        refresh: function (param) {
K
kener 已提交
811
            this._clearEffect();
K
kener 已提交
812
            param = param || {};
K
kener 已提交
813 814 815
            var magicOption = param.option;
            
            // 外部调用的refresh且有option带入
E
erik 已提交
816
            if (!this._refreshInside && magicOption) {
K
kener 已提交
817 818 819
                // 做简单的差异合并去同步内部持有的数据克隆,不建议带入数据
                // 开启数据区域缩放、拖拽重计算、数据视图可编辑模式情况下,当用户产生了数据变化后无法同步
                // 如有带入option存在数据变化,请重新setOption
820
                magicOption = this.getOption();
K
kener 已提交
821
                zrUtil.merge(magicOption, param.option, true);
K
kener 已提交
822
                zrUtil.merge(this._optionRestore, param.option, true);
K
kener 已提交
823
                this._toolbox.reset(magicOption);
K
kener 已提交
824 825
            }
            
K
kener 已提交
826 827 828
            this._island.refresh(magicOption);
            this._toolbox.refresh(magicOption);
            
K
kener 已提交
829
            // 停止动画
K
kener 已提交
830
            this._zr.clearAnimation();
K
kener 已提交
831
            // 先来后到,安顺序刷新各种图表,图表内部refresh优化检查magicOption,无需更新则不更新~
K
kener 已提交
832 833
            for (var i = 0, l = this._chartList.length; i < l; i++) {
                this._chartList[i].refresh && this._chartList[i].refresh(magicOption);
K
kener 已提交
834
            }
K
kener 已提交
835
            this.component.grid && this.component.grid.refixAxisShape(this.component);
K
kener 已提交
836 837
            this._zr.refresh();
        },
K
kener 已提交
838

K
kener 已提交
839 840 841
        /**
         * 释放图表实例
         */
K
kener 已提交
842
        _disposeChartList: function () {
K
kener 已提交
843
            this._clearEffect();
E
erik 已提交
844

K
kener 已提交
845
            // 停止动画
K
kener 已提交
846
            this._zr.clearAnimation();
E
erik 已提交
847

K
kener 已提交
848
            var len = this._chartList.length;
K
kener 已提交
849
            while (len--) {
E
erik 已提交
850 851 852 853 854 855 856
                var chart = this._chartList[len];

                if (chart) {
                    var chartType = chart.type;
                    this.chart[chartType] && delete this.chart[chartType];
                    this.component[chartType] && delete this.component[chartType];
                    chart.dispose && chart.dispose();
857
                }
K
kener 已提交
858
            }
E
erik 已提交
859

K
kener 已提交
860
            this._chartList = [];
K
kener 已提交
861
        },
K
kener 已提交
862 863

        /**
864
         * 非图表全局属性merge~~ 
K
kener 已提交
865
         */
K
kener 已提交
866
        _mergeGlobalConifg: function (magicOption) {
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886
            var mergeList = [
                // 背景颜色
                'backgroundColor',
                
                // 拖拽重计算相关
                'calculable', 'calculableColor', 'calculableHolderColor',
                
                // 孤岛显示连接符
                'nameConnector', 'valueConnector',
                
                // 动画相关
                'animation', 'animationThreshold', 'animationDuration',
                'animationEasing', 'addDataAnimation',
                
                // 默认标志图形类型列表
                'symbolList',
                
                // 降低图表内元素拖拽敏感度,单位ms,不建议外部干预
                'DRAG_ENABLE_TIME'
            ];
E
erik 已提交
887

K
jshint  
kener 已提交
888
            var len = mergeList.length;
889
            while (len--) {
E
erik 已提交
890 891 892
                var mergeItem = mergeList[len];
                if (magicOption[mergeItem] == null) {
                    magicOption[mergeItem] = this._themeConfig[mergeItem];
893
                }
894
            }
K
kener 已提交
895
            
896
            // 数值系列的颜色列表,不传则采用内置颜色,可配数组,借用zrender实例注入,会有冲突风险,先这样
E
erik 已提交
897 898 899 900
            var themeColor = magicOption.color;
            if (!(themeColor && themeColor.length)) {
                themeColor = this._themeConfig.color;
            }
901 902 903 904 905 906 907
            
            if (!_canvasSupported) {
                // 不支持Canvas的强制关闭动画
                magicOption.animation = false;
                magicOption.addDataAnimation = false;
            }
            
K
kener 已提交
908 909 910 911 912
            this._zr.getColor = function (idx) {
                var zrColor = require('zrender/tool/color');
                return zrColor.getColor(idx, themeColor);
            };
        },
913 914 915 916 917 918 919
        
        /**
         * 万能接口,配置图表实例任何可配置选项,多次调用时option选项做merge处理
         * @param {Object} option
         * @param {boolean=} notMerge 多次调用时option选项是默认是合并(merge)的,
         *                   如果不需求,可以通过notMerger参数为true阻止与上次option的合并
         */
K
kener 已提交
920
        setOption: function (option, notMerge) {
K
kener 已提交
921 922 923 924 925 926 927 928 929 930 931 932 933 934
            if (!option.timeline) {
                return this._setOption(option, notMerge);
            }
            else {
                return this._setTimelineOption(option);
            }
        },
        
        /**
         * 万能接口,配置图表实例任何可配置选项,多次调用时option选项做merge处理
         * @param {Object} option
         * @param {boolean=} notMerge 多次调用时option选项是默认是合并(merge)的,
         *                   如果不需求,可以通过notMerger参数为true阻止与上次option的合并
         */
K
kener 已提交
935
        _setOption: function (option, notMerge) {
936
            if (!notMerge && this._option) {
K
kener 已提交
937 938
                this._option = zrUtil.merge(
                    this.getOption(),
939
                    zrUtil.clone(option),
K
kener 已提交
940
                    true
941 942 943
                );
            }
            else {
K
kener 已提交
944
                this._option = zrUtil.clone(option);
945 946
            }

K
kener 已提交
947 948
            this._optionRestore = zrUtil.clone(this._option);
            
K
kener 已提交
949
            if (!this._option.series || this._option.series.length === 0) {
K
kener 已提交
950
                this._zr.clear();
951 952 953
                return;
            }

K
kener 已提交
954 955 956 957 958 959 960 961 962
            if (this.component.dataZoom                         // 存在dataZoom控件
                && (this._option.dataZoom                       // 并且新option也存在
                    || (this._option.toolbox
                        && this._option.toolbox.feature
                        && this._option.toolbox.feature.dataZoom
                        && this._option.toolbox.feature.dataZoom.show
                    )
                )
            ) {
K
kener 已提交
963 964 965
                // dataZoom同步数据
                this.component.dataZoom.syncOption(this._option);
            }
K
kener 已提交
966 967 968 969
            this._toolbox.reset(this._option);
            this._render(this._option);
            return this;
        },
K
kener 已提交
970

K
kener 已提交
971 972 973
        /**
         * 返回内部持有的当前显示option克隆 
         */
K
kener 已提交
974
        getOption: function () {
975 976
            var magicOption = zrUtil.clone(this._option);
            
E
erik 已提交
977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
            var self = this;
            function restoreOption(prop) {
                var restoreSource = self._optionRestore[prop];

                if (restoreSource) {
                    if (restoreSource instanceof Array) {
                        var len = restoreSource.length;
                        while (len--) {
                            magicOption[prop][len].data = zrUtil.clone(
                                restoreSource[len].data
                            );
                        }
                    }
                    else {
                        magicOption[prop].data = zrUtil.clone(restoreSource.data);
992 993
                    }
                }
K
kener 已提交
994
            }
E
erik 已提交
995 996 997

            // 横轴数据还原
            restoreOption('xAxis');
998 999
            
            // 纵轴数据还原
E
erik 已提交
1000
            restoreOption('yAxis');
K
kener 已提交
1001
            
1002
            // 系列数据还原
E
erik 已提交
1003
            restoreOption('series');
1004 1005
            
            return magicOption;
K
kener 已提交
1006
        },
K
kener 已提交
1007

K
kener 已提交
1008 1009 1010 1011 1012 1013
        /**
         * 数据设置快捷接口
         * @param {Array} series
         * @param {boolean=} notMerge 多次调用时option选项是默认是合并(merge)的,
         *                   如果不需求,可以通过notMerger参数为true阻止与上次option的合并。
         */
K
kener 已提交
1014
        setSeries: function (series, notMerge) {
K
kener 已提交
1015
            if (!notMerge) {
K
kener 已提交
1016
                this.setOption({series: series});
K
kener 已提交
1017 1018
            }
            else {
K
kener 已提交
1019 1020
                this._option.series = series;
                this.setOption(this._option, notMerge);
K
kener 已提交
1021
            }
K
kener 已提交
1022 1023
            return this;
        },
K
kener 已提交
1024 1025 1026 1027

        /**
         * 返回内部持有的当前显示series克隆 
         */
K
kener 已提交
1028
        getSeries: function () {
K
kener 已提交
1029 1030
            return this.getOption().series;
        },
K
kener 已提交
1031
        
K
kener 已提交
1032 1033 1034 1035
        /**
         * timelineOption接口,配置图表实例任何可配置选项
         * @param {Object} option
         */
K
kener 已提交
1036
        _setTimelineOption: function(option) {
K
kener 已提交
1037 1038
            this._timeline && this._timeline.dispose();
            var Timeline = require('./component/timeline');
K
kener 已提交
1039 1040 1041 1042
            var timeline = new Timeline(
                this._themeConfig, this._messageCenter, this._zr, option, this
            );
            this._timeline = timeline;
1043 1044
            this.component.timeline = this._timeline;
            
K
kener 已提交
1045
            return this;
K
kener 已提交
1046 1047
        },
        
K
kener 已提交
1048
        /**
K
kener 已提交
1049
         * 动态数据添加
1050
         * 形参为单组数据参数,多组时为数据,内容同[seriesIdx, data, isShift, additionData]
K
kener 已提交
1051 1052 1053 1054
         * @param {number} seriesIdx 系列索引
         * @param {number | Object} data 增加数据
         * @param {boolean=} isHead 是否队头加入,默认,不指定或false时为队尾插入
         * @param {boolean=} dataGrow 是否增长数据队列长度,默认,不指定或false时移出目标数组对位数据
1055
         * @param {string=} additionData 是否增加类目轴(饼图为图例)数据,附加操作同isHead和dataGrow
K
kener 已提交
1056
         */
K
kener 已提交
1057
        addData: function (seriesIdx, data, isHead, dataGrow, additionData) {
K
kener 已提交
1058
            var params = seriesIdx instanceof Array
E
erik 已提交
1059 1060 1061
                ? seriesIdx
                : [[seriesIdx, data, isHead, dataGrow, additionData]];

1062
            //this._optionRestore 和 magicOption 都要同步
E
erik 已提交
1063 1064
            var magicOption = this.getOption();
            var optionRestore = this._optionRestore;
K
kener 已提交
1065 1066 1067 1068 1069
            for (var i = 0, l = params.length; i < l; i++) {
                seriesIdx = params[i][0];
                data = params[i][1];
                isHead = params[i][2];
                dataGrow = params[i][3];
1070
                additionData = params[i][4];
E
erik 已提交
1071 1072 1073 1074 1075 1076 1077

                
                var seriesItem = optionRestore.series[seriesIdx];
                var inMethod = isHead ? 'unshift' : 'push';
                var outMethod = isHead ? 'pop' : 'shift';
                if (seriesItem) {
                    var seriesItemData = seriesItem.data;
E
erik 已提交
1078
                    var mSeriesItemData = magicOption.series[seriesIdx].data;
E
erik 已提交
1079 1080 1081 1082 1083 1084

                    seriesItemData[inMethod](data);
                    mSeriesItemData[inMethod](data);
                    if (!dataGrow) {
                        seriesItemData[outMethod]();
                        data = mSeriesItemData[outMethod]();
K
kener 已提交
1085 1086
                    }
                    
E
erik 已提交
1087 1088 1089 1090
                    
                    if (additionData != null) {
                        var legend;
                        var legendData;
E
erik 已提交
1091

K
kener 已提交
1092
                        if (seriesItem.type === ecConfig.CHART_TYPE_PIE
E
erik 已提交
1093 1094
                            && (legend = optionRestore.legend) 
                            && (legendData = legend.data)
K
kener 已提交
1095
                        ) {
E
erik 已提交
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
                            var mLegendData = magicOption.legend.data;
                            legendData[inMethod](additionData);
                            mLegendData[inMethod](additionData);

                            if (!dataGrow) {
                                var legendDataIdx = zrUtil.indexOf(legendData, data.name);
                                legendDataIdx != -1 && legendData.splice(legendDataIdx, 1);
                                
                                legendDataIdx = zrUtil.indexOf(mLegendData, data.name);
                                legendDataIdx != -1 && mLegendData.splice(legendDataIdx, 1);
K
kener 已提交
1106 1107
                            }
                        }
E
erik 已提交
1108 1109 1110 1111 1112 1113
                        else if (optionRestore.xAxis != null && optionRestore.yAxis != null) {
                            // x轴类目
                            var axisData;
                            var mAxisData;
                            var axisIdx = seriesItem.xAxisIndex || 0;

K
kener 已提交
1114 1115
                            if (optionRestore.xAxis[axisIdx].type == null
                                || optionRestore.xAxis[axisIdx].type === 'category'
E
erik 已提交
1116 1117 1118 1119 1120 1121
                            ) {
                                axisData = optionRestore.xAxis[axisIdx].data;
                                mAxisData = magicOption.xAxis[axisIdx].data;

                                axisData[inMethod](additionData);
                                mAxisData[inMethod](additionData);
1122
                                if (!dataGrow) {
E
erik 已提交
1123 1124
                                    axisData[outMethod]();
                                    mAxisData[outMethod]();
1125
                                }
K
kener 已提交
1126
                            }
E
erik 已提交
1127 1128 1129
                            
                            // y轴类目
                            axisIdx = seriesItem.yAxisIndex || 0;
K
kener 已提交
1130
                            if (optionRestore.yAxis[axisIdx].type === 'category') {
E
erik 已提交
1131 1132
                                axisData = optionRestore.yAxis[axisIdx].data;
                                mAxisData = magicOption.yAxis[axisIdx].data;
E
erik 已提交
1133

E
erik 已提交
1134 1135
                                axisData[inMethod](additionData);
                                mAxisData[inMethod](additionData);
1136
                                if (!dataGrow) {
E
erik 已提交
1137 1138
                                    axisData[outMethod]();
                                    mAxisData[outMethod]();
1139
                                }
K
kener 已提交
1140 1141 1142
                            }
                        }
                    }
E
erik 已提交
1143

1144 1145
                    // 同步图表内状态,动画需要
                    this._option.series[seriesIdx].data = magicOption.series[seriesIdx].data;
K
kener 已提交
1146 1147
                }
            }
K
kener 已提交
1148 1149
            
            this._zr.clearAnimation();
E
erik 已提交
1150 1151 1152 1153
            var chartList = this._chartList;
            for (var i = 0, l = chartList.length; i < l; i++) {
                if (magicOption.addDataAnimation && chartList[i].addDataAnimation) {
                    chartList[i].addDataAnimation(params);
1154 1155
                }
            }
E
erik 已提交
1156

1157 1158 1159 1160
            // dataZoom同步数据
            this.component.dataZoom && this.component.dataZoom.syncOption(magicOption);
            
            this._option = magicOption;
K
kener 已提交
1161
            var self = this;
K
kener 已提交
1162
            setTimeout(function (){
1163 1164 1165
                if (!self._zr) {
                    return; // 已经被释放
                }
K
kener 已提交
1166
                self._zr.clearAnimation();
E
erik 已提交
1167
                for (var i = 0, l = chartList.length; i < l; i++) {
1168
                    // 有addData动画就去掉过渡动画
E
erik 已提交
1169 1170
                    chartList[i].motionlessOnce = 
                        magicOption.addDataAnimation && chartList[i].addDataAnimation;
K
kener 已提交
1171
                }
K
kener 已提交
1172
                self._messageCenter.dispatch(
1173
                    ecConfig.EVENT.REFRESH,
K
kener 已提交
1174 1175 1176
                    null,
                    {option: magicOption},
                    self
1177
                );
K
kener 已提交
1178
            }, magicOption.addDataAnimation ? 500 : 0);
K
kener 已提交
1179 1180
            return this;
        },
K
kener 已提交
1181

K
kener 已提交
1182 1183 1184 1185 1186
        /**
         * 动态[标注 | 标线]添加
         * @param {number} seriesIdx 系列索引
         * @param {Object} markData [标注 | 标线]对象,支持多个
         */
K
kener 已提交
1187
        addMarkPoint: function (seriesIdx, markData) {
K
kener 已提交
1188 1189 1190
            return this._addMark(seriesIdx, markData, 'markPoint');
        },
        
K
kener 已提交
1191
        addMarkLine: function (seriesIdx, markData) {
K
kener 已提交
1192 1193 1194
            return this._addMark(seriesIdx, markData, 'markLine');
        },
        
K
kener 已提交
1195
        _addMark: function (seriesIdx, markData, markType) {
E
erik 已提交
1196 1197 1198 1199 1200 1201 1202 1203 1204
            var series = this._option.series;
            var seriesItem;

            if (series && (seriesItem = series[seriesIdx])) {
                var seriesR = this._optionRestore.series;
                var seriesRItem = seriesR[seriesIdx];
                var markOpt = seriesItem[markType];
                var markOptR = seriesRItem[markType];

K
kener 已提交
1205 1206
                markOpt = seriesItem[markType] = markOpt || {data: []};
                markOptR = seriesRItem[markType] = markOptR || {data: []};
E
erik 已提交
1207 1208

                for (var key in markData) {
K
kener 已提交
1209
                    if (key === 'data') {
E
erik 已提交
1210 1211 1212 1213
                        // 数据concat
                        markOpt.data = markOpt.data.concat(markData.data);
                        markOptR.data = markOptR.data.concat(markData.data);
                    }
K
kener 已提交
1214
                    else if (typeof markData[key] != 'object' || markOpt[key] == null) {
E
erik 已提交
1215 1216 1217 1218 1219 1220 1221 1222
                        // 简单类型或新值直接赋值
                        markOpt[key] = markOptR[key] = markData[key];
                    }
                    else {
                        // 非数据的复杂对象merge
                        zrUtil.merge(markOpt[key], markData[key], true);
                        zrUtil.merge(markOptR[key], markData[key], true);
                    }
K
kener 已提交
1223
                }
E
erik 已提交
1224 1225 1226
                
                var chart = this.chart[seriesItem.type];
                chart && chart.addMark(seriesIdx, markData, markType);
K
kener 已提交
1227
            }
E
erik 已提交
1228

K
kener 已提交
1229 1230 1231
            return this;
        },
        
K
kener 已提交
1232 1233 1234 1235 1236
        /**
         * 动态[标注 | 标线]删除
         * @param {number} seriesIdx 系列索引
         * @param {string} markName [标注 | 标线]名称
         */
K
kener 已提交
1237
        delMarkPoint: function (seriesIdx, markName) {
K
kener 已提交
1238 1239 1240
            return this._delMark(seriesIdx, markName, 'markPoint');
        },
        
K
kener 已提交
1241
        delMarkLine: function (seriesIdx, markName) {
K
kener 已提交
1242 1243 1244
            return this._delMark(seriesIdx, markName, 'markLine');
        },
        
K
kener 已提交
1245
        _delMark: function (seriesIdx, markName, markType) {
E
erik 已提交
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
            var series = this._option.series;
            var seriesItem;
            var mark;
            var dataArray;

            if (!(
                    series 
                    && (seriesItem = series[seriesIdx]) 
                    && (mark = seriesItem[markType])
                    && (dataArray = mark.data)
                )
K
kener 已提交
1257 1258 1259
            ) {
                return this;
            }
E
erik 已提交
1260

K
kener 已提交
1261 1262
            markName = markName.split(' > ');
            var targetIndex = -1;
E
erik 已提交
1263
            
K
kener 已提交
1264
            for (var i = 0, l = dataArray.length; i < l; i++) {
E
erik 已提交
1265 1266
                var dataItem = dataArray[i];
                if (dataItem instanceof Array) {
K
kener 已提交
1267 1268
                    if (dataItem[0].name === markName[0]
                        && dataItem[1].name === markName[1]
E
erik 已提交
1269 1270 1271 1272
                    ) {
                        targetIndex = i;
                        break;
                    }
K
kener 已提交
1273
                }
K
kener 已提交
1274
                else if (dataItem.name === markName[0]) {
E
erik 已提交
1275
                    targetIndex = i;
K
kener 已提交
1276 1277 1278 1279
                    break;
                }
            }
            
E
erik 已提交
1280
            if (targetIndex > -1) {
E
erik 已提交
1281
                dataArray.splice(targetIndex, 1);
K
kener 已提交
1282
                this._optionRestore.series[seriesIdx][markType].data.splice(targetIndex, 1);
E
erik 已提交
1283

E
erik 已提交
1284
                var chart = this.chart[seriesItem.type];
K
kener 已提交
1285 1286 1287 1288 1289 1290
                chart && chart.delMark(seriesIdx, markName.join(' > '), markType);
            }
            
            return this;
        },
        
1291 1292 1293
        /**
         * 获取当前dom 
         */
K
kener 已提交
1294
        getDom: function () {
K
kener 已提交
1295 1296
            return this.dom;
        },
1297
        
K
kener 已提交
1298 1299 1300
        /**
         * 获取当前zrender实例,可用于添加额为的shape和深度控制 
         */
K
kener 已提交
1301
        getZrender: function () {
K
kener 已提交
1302 1303
            return this._zr;
        },
K
kener 已提交
1304

K
kener 已提交
1305 1306 1307 1308 1309
        /**
         * 获取Base64图片dataURL
         * @param {string} imgType 图片类型,支持png|jpeg,默认为png
         * @return imgDataURL
         */
K
kener 已提交
1310
        getDataURL: function (imgType) {
K
kener 已提交
1311
            if (!_canvasSupported) {
K
kener 已提交
1312 1313
                return '';
            }
E
erik 已提交
1314

K
kener 已提交
1315
            if (this._chartList.length === 0) {
K
kener 已提交
1316
                // 渲染为图片
K
kener 已提交
1317
                var imgId = 'IMG' + this.id;
K
kener 已提交
1318 1319 1320 1321 1322
                var img = document.getElementById(imgId);
                if (img) {
                    return img.src;
                }
            }
E
erik 已提交
1323

1324
            // 清除可能存在的tooltip元素
E
erik 已提交
1325 1326
            var tooltip = this.component.tooltip;
            tooltip && tooltip.hideTip();
1327
                
E
erik 已提交
1328 1329 1330
            switch (imgType) {
                case 'jpeg':
                    break;
E
erik 已提交
1331
                default:
E
erik 已提交
1332
                    imgType = 'png';
K
kener 已提交
1333
            }
E
erik 已提交
1334 1335

            var bgColor = this._option.backgroundColor;
K
kener 已提交
1336
            if (bgColor && bgColor.replace(' ','') === 'rgba(0,0,0,0)') {
E
erik 已提交
1337 1338 1339
                bgColor = '#fff';
            }

K
kener 已提交
1340 1341
            return this._zr.toDataURL('image/' + imgType, bgColor); 
        },
K
kener 已提交
1342 1343 1344 1345 1346 1347

        /**
         * 获取img
         * @param {string} imgType 图片类型,支持png|jpeg,默认为png
         * @return img dom
         */
K
kener 已提交
1348
        getImage: function (imgType) {
E
erik 已提交
1349
            var title = this._optionRestore.title;
K
kener 已提交
1350
            var imgDom = document.createElement('img');
K
kener 已提交
1351
            imgDom.src = this.getDataURL(imgType);
E
erik 已提交
1352
            imgDom.title = (title && title.text) || 'ECharts';
K
kener 已提交
1353
            return imgDom;
K
kener 已提交
1354
        },
1355 1356 1357 1358 1359 1360
        
        /**
         * 获取多图联动的Base64图片dataURL
         * @param {string} imgType 图片类型,支持png|jpeg,默认为png
         * @return imgDataURL
         */
K
kener 已提交
1361
        getConnectedDataURL: function (imgType) {
K
kener 已提交
1362 1363
            if (!this.isConnected()) {
                return this.getDataURL(imgType);
1364 1365
            }
            
E
erik 已提交
1366
            var tempDom = this.dom;
1367
            var imgList = {
K
kener 已提交
1368 1369 1370 1371 1372 1373
                'self': {
                    img: this.getDataURL(imgType),
                    left: tempDom.offsetLeft,
                    top: tempDom.offsetTop,
                    right: tempDom.offsetLeft + tempDom.offsetWidth,
                    bottom: tempDom.offsetTop + tempDom.offsetHeight
1374 1375
                }
            };
E
erik 已提交
1376

1377 1378 1379 1380
            var minLeft = imgList.self.left;
            var minTop = imgList.self.top;
            var maxRight = imgList.self.right;
            var maxBottom = imgList.self.bottom;
E
erik 已提交
1381

K
kener 已提交
1382 1383
            for (var c in this._connected) {
                tempDom = this._connected[c].getDom();
1384
                imgList[c] = {
K
kener 已提交
1385 1386 1387 1388 1389
                    img: this._connected[c].getDataURL(imgType),
                    left: tempDom.offsetLeft,
                    top: tempDom.offsetTop,
                    right: tempDom.offsetLeft + tempDom.offsetWidth,
                    bottom: tempDom.offsetTop + tempDom.offsetHeight
K
kener 已提交
1390
                };
E
erik 已提交
1391

1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
                minLeft = Math.min(minLeft, imgList[c].left);
                minTop = Math.min(minTop, imgList[c].top);
                maxRight = Math.max(maxRight, imgList[c].right);
                maxBottom = Math.max(maxBottom, imgList[c].bottom);
            }
            
            var zrDom = document.createElement('div');
            zrDom.style.position = 'absolute';
            zrDom.style.left = '-4000px';
            zrDom.style.width = (maxRight - minLeft) + 'px';
            zrDom.style.height = (maxBottom - minTop) + 'px';
            document.body.appendChild(zrDom);
            
            var zrImg = require('zrender').init(zrDom);
            
K
kener 已提交
1407
            var ImageShape = require('zrender/shape/Image');
1408
            for (var c in imgList) {
K
kener 已提交
1409
                zrImg.addShape(new ImageShape({
K
kener 已提交
1410 1411 1412 1413
                    style: {
                        x: imgList[c].left - minLeft,
                        y: imgList[c].top - minTop,
                        image: imgList[c].img
1414
                    }
K
kener 已提交
1415
                }));
1416 1417 1418
            }
            
            zrImg.render();
E
erik 已提交
1419
            var bgColor = this._option.backgroundColor;
K
kener 已提交
1420
            if (bgColor && bgColor.replace(/ /g, '') === 'rgba(0,0,0,0)') {
E
erik 已提交
1421 1422 1423
                bgColor = '#fff';
            }
            
1424 1425
            var image = zrImg.toDataURL('image/png', bgColor);
            
K
kener 已提交
1426
            setTimeout(function () {
1427 1428 1429
                zrImg.dispose();
                zrDom.parentNode.removeChild(zrDom);
                zrDom = null;
E
erik 已提交
1430
            }, 100);
1431 1432
            
            return image;
K
kener 已提交
1433
        },
1434 1435 1436 1437 1438 1439
        
        /**
         * 获取多图联动的img
         * @param {string} imgType 图片类型,支持png|jpeg,默认为png
         * @return img dom
         */
K
kener 已提交
1440
        getConnectedImage: function (imgType) {
E
erik 已提交
1441
            var title = this._optionRestore.title;
1442
            var imgDom = document.createElement('img');
K
kener 已提交
1443
            imgDom.src = this.getConnectedDataURL(imgType);
E
erik 已提交
1444
            imgDom.title = (title && title.text) || 'ECharts';
1445
            return imgDom;
K
kener 已提交
1446
        },
K
kener 已提交
1447

K
kener 已提交
1448
        /**
K
kener 已提交
1449
         * 外部接口绑定事件
K
kener 已提交
1450 1451 1452
         * @param {Object} eventName 事件名称
         * @param {Object} eventListener 事件响应函数
         */
K
kener 已提交
1453
        on: function (eventName, eventListener) {
L
lang 已提交
1454
            this._messageCenterOutSide.bind(eventName, eventListener, this);
K
kener 已提交
1455 1456
            return this;
        },
K
kener 已提交
1457

K
kener 已提交
1458
        /**
K
kener 已提交
1459
         * 外部接口解除事件绑定
K
kener 已提交
1460 1461 1462
         * @param {Object} eventName 事件名称
         * @param {Object} eventListener 事件响应函数
         */
K
kener 已提交
1463
        un: function (eventName, eventListener) {
K
kener 已提交
1464
            this._messageCenterOutSide.unbind(eventName, eventListener);
K
kener 已提交
1465 1466
            return this;
        },
K
kener 已提交
1467
        
K
kener 已提交
1468 1469 1470 1471
        /**
         * 多图联动 
         * @param connectTarget{ECharts | Array <ECharts>} connectTarget 联动目标
         */
K
kener 已提交
1472
        connect: function (connectTarget) {
K
kener 已提交
1473
            if (!connectTarget) {
K
kener 已提交
1474
                return this;
K
kener 已提交
1475 1476
            }
            
K
kener 已提交
1477
            if (!this._connected) {
K
kener 已提交
1478
                this._connected = {};
K
kener 已提交
1479 1480 1481 1482
            }
            
            if (connectTarget instanceof Array) {
                for (var i = 0, l = connectTarget.length; i < l; i++) {
K
kener 已提交
1483
                    this._connected[connectTarget[i].id] = connectTarget[i];
K
kener 已提交
1484 1485 1486
                }
            }
            else {
K
kener 已提交
1487
                this._connected[connectTarget.id] = connectTarget;
K
kener 已提交
1488 1489
            }
            
K
kener 已提交
1490 1491
            return this;
        },
K
kener 已提交
1492 1493 1494 1495 1496
        
        /**
         * 解除多图联动 
         * @param connectTarget{ECharts | Array <ECharts>} connectTarget 解除联动目标
         */
K
kener 已提交
1497
        disConnect: function (connectTarget) {
K
kener 已提交
1498 1499
            if (!connectTarget || !this._connected) {
                return this;
K
kener 已提交
1500 1501 1502 1503
            }
            
            if (connectTarget instanceof Array) {
                for (var i = 0, l = connectTarget.length; i < l; i++) {
K
kener 已提交
1504
                    delete this._connected[connectTarget[i].id];
K
kener 已提交
1505 1506 1507
                }
            }
            else {
K
kener 已提交
1508
                delete this._connected[connectTarget.id];
K
kener 已提交
1509 1510
            }
            
K
kener 已提交
1511 1512
            for (var k in this._connected) {
                return k, this; // 非空
K
kener 已提交
1513 1514 1515
            }
            
            // 空,转为标志位
K
kener 已提交
1516 1517 1518
            this._connected = false;
            return this;
        },
K
kener 已提交
1519 1520 1521 1522
        
        /**
         * 联动事件响应 
         */
K
kener 已提交
1523
        connectedEventHandler: function (param) {
K
kener 已提交
1524
            if (param.__echartsId != this.id) {
K
kener 已提交
1525
                // 来自其他联动图表的事件
K
kener 已提交
1526
                this._onevent(param);
K
kener 已提交
1527
            }
K
kener 已提交
1528
        },
K
kener 已提交
1529
        
1530 1531 1532
        /**
         * 是否存在多图联动 
         */
K
kener 已提交
1533
        isConnected: function () {
K
kener 已提交
1534 1535
            return !!this._connected;
        },
1536
        
K
kener 已提交
1537 1538 1539 1540
        /**
         * 显示loading过渡 
         * @param {Object} loadingOption
         */
K
kener 已提交
1541
        showLoading: function (loadingOption) {
K
kener 已提交
1542
            var effectList = {
K
kener 已提交
1543 1544 1545 1546 1547 1548
                bar: require('zrender/loadingEffect/Bar'),
                bubble: require('zrender/loadingEffect/Bubble'),
                dynamicLine: require('zrender/loadingEffect/DynamicLine'),
                ring: require('zrender/loadingEffect/Ring'),
                spin: require('zrender/loadingEffect/Spin'),
                whirling: require('zrender/loadingEffect/Whirling')
E
erik 已提交
1549
            };
K
kener 已提交
1550
            this._toolbox.hideDataView();
K
kener 已提交
1551

K
kener 已提交
1552
            loadingOption = loadingOption || {};
E
erik 已提交
1553

K
kener 已提交
1554
            var textStyle = loadingOption.textStyle || {};
E
erik 已提交
1555
            loadingOption.textStyle = textStyle;
K
kener 已提交
1556 1557

            var finalTextStyle = zrUtil.merge(
E
erik 已提交
1558
                zrUtil.clone(textStyle),
K
kener 已提交
1559
                this._themeConfig.textStyle
K
kener 已提交
1560
            );
E
erik 已提交
1561 1562 1563 1564
            textStyle.textFont = finalTextStyle.fontStyle + ' '
                                 + finalTextStyle.fontWeight + ' '
                                 + finalTextStyle.fontSize + 'px '
                                 + finalTextStyle.fontFamily;
K
kener 已提交
1565

E
erik 已提交
1566
            textStyle.text = loadingOption.text || this._themeConfig.loadingText;
K
kener 已提交
1567

1568
            if (loadingOption.x != null) {
E
erik 已提交
1569
                textStyle.x = loadingOption.x;
K
kener 已提交
1570
            }
1571
            if (loadingOption.y != null) {
E
erik 已提交
1572
                textStyle.y = loadingOption.y;
K
kener 已提交
1573
            }
K
kener 已提交
1574
            
K
kener 已提交
1575
            loadingOption.effectOption = loadingOption.effectOption || {};
E
erik 已提交
1576
            loadingOption.effectOption.textStyle = textStyle;
K
kener 已提交
1577
            
K
jshint  
kener 已提交
1578
            var Effect = loadingOption.effect;
K
kener 已提交
1579
            if (typeof Effect === 'string' || Effect == null) {
K
Kener 已提交
1580
                Effect =  effectList[loadingOption.effect || this._themeConfig.loadingEffect];
K
kener 已提交
1581
            }
K
jshint  
kener 已提交
1582
            this._zr.showLoading(new Effect(loadingOption.effectOption));
K
kener 已提交
1583 1584
            return this;
        },
K
kener 已提交
1585

K
kener 已提交
1586 1587 1588
        /**
         * 隐藏loading过渡 
         */
K
kener 已提交
1589
        hideLoading: function () {
K
kener 已提交
1590 1591 1592
            this._zr.hideLoading();
            return this;
        },
K
kener 已提交
1593 1594 1595 1596
        
        /**
         * 主题设置 
         */
K
kener 已提交
1597
        setTheme: function (theme) {
K
kener 已提交
1598 1599 1600 1601
            if (theme) {
               if (typeof theme === 'string') {
                    // 默认主题
                    switch (theme) {
E
erik 已提交
1602 1603
                        // case 'themename':
                        //     theme = require('./theme/themename');
K
kener 已提交
1604 1605 1606 1607 1608
                        default:
                            theme = require('./theme/default');
                    }
                }
                else {
K
kener 已提交
1609
                    theme = theme || {};
K
kener 已提交
1610 1611
                }
                
E
erik 已提交
1612 1613
                // 复位默认配置
                // this._themeConfig会被别的对象引用持有
K
kener 已提交
1614
                // 所以不能改成this._themeConfig = {};
K
kener 已提交
1615 1616
                for (var key in this._themeConfig) {
                    delete this._themeConfig[key];
K
kener 已提交
1617 1618
                }
                for (var key in ecConfig) {
K
kener 已提交
1619
                    this._themeConfig[key] = zrUtil.clone(ecConfig[key]);
K
kener 已提交
1620
                }
1621
                
1622
                // 颜色数组随theme,不merge
K
kener 已提交
1623
                theme.color && (this._themeConfig.color = []);
1624 1625
                
                // 默认标志图形类型列表,不merge
K
kener 已提交
1626
                theme.symbolList && (this._themeConfig.symbolList = []);
1627
                
K
kener 已提交
1628
                // 应用新主题
1629
                zrUtil.merge(this._themeConfig, zrUtil.clone(theme), true);
K
kener 已提交
1630 1631
            }
            
K
kener 已提交
1632
            if (!_canvasSupported) {   // IE8-
1633
                this._themeConfig.textStyle.fontFamily = this._themeConfig.textStyle.fontFamily2;
K
kener 已提交
1634
            }
K
kener 已提交
1635
            
K
kener 已提交
1636
            this._timeline && this._timeline.setTheme(true);
K
kener 已提交
1637 1638
            this._optionRestore && this.restore();
        },
K
kener 已提交
1639

K
kener 已提交
1640 1641 1642
        /**
         * 视图区域大小变化更新,不默认绑定,供使用方按需调用 
         */
K
kener 已提交
1643
        resize: function () {
K
kener 已提交
1644 1645
            var self = this;
            return function(){
K
kener 已提交
1646
                self._clearEffect();
K
kener 已提交
1647
                self._zr.resize();
L
lang 已提交
1648
                if (self._option && self._option.renderAsImage && _canvasSupported) {
K
kener 已提交
1649 1650 1651 1652 1653 1654 1655 1656
                    // 渲染为图片重走render模式
                    self._render(self._option);
                    return self;
                }
                // 停止动画
                self._zr.clearAnimation();
                self._island.resize();
                self._toolbox.resize();
K
kener 已提交
1657
                self._timeline && self._timeline.resize();
K
kener 已提交
1658 1659 1660 1661 1662
                // 先来后到,不能仅刷新自己,也不能在上一个循环中刷新,如坐标系数据改变会影响其他图表的大小
                // 所以安顺序刷新各种图表,图表内部refresh优化无需更新则不更新~
                for (var i = 0, l = self._chartList.length; i < l; i++) {
                    self._chartList[i].resize && self._chartList[i].resize();
                }
K
kener 已提交
1663
                self.component.grid && self.component.grid.refixAxisShape(self.component);
K
kener 已提交
1664
                self._zr.refresh();
K
kener 已提交
1665
                self._messageCenter.dispatch(ecConfig.EVENT.RESIZE, null, null, self);
K
kener 已提交
1666
                return self;
K
jshint  
kener 已提交
1667
            };
K
kener 已提交
1668
        },
K
kener 已提交
1669
        
K
kener 已提交
1670 1671
        _clearEffect: function() {
            this._zr.modLayer(ecConfig.EFFECT_ZLEVEL, { motionBlur: false });
K
kener 已提交
1672 1673 1674
            this._zr.painter.clearLayer(ecConfig.EFFECT_ZLEVEL);
        },
        
K
kener 已提交
1675
        /**
K
kener 已提交
1676
         * 清除已渲染内容 ,clear后echarts实例可用
K
kener 已提交
1677
         */
K
kener 已提交
1678
        clear: function () {
K
kener 已提交
1679 1680
            this._disposeChartList();
            this._zr.clear();
K
kener 已提交
1681 1682
            this._option = {};
            this._optionRestore = {};
K
kener 已提交
1683
            this.dom.style.backgroundColor = null;
K
kener 已提交
1684 1685
            return this;
        },
K
kener 已提交
1686

K
kener 已提交
1687 1688 1689
        /**
         * 释放,dispose后echarts实例不可用
         */
K
kener 已提交
1690
        dispose: function () {
K
kener 已提交
1691
            var key = this.dom.getAttribute(DOM_ATTRIBUTE_KEY);
K
kener 已提交
1692 1693
            key && delete _instances[key];
        
K
kener 已提交
1694 1695
            this._island.dispose();
            this._toolbox.dispose();
K
kener 已提交
1696
            this._timeline && this._timeline.dispose();
K
kener 已提交
1697 1698 1699 1700
            this._messageCenter.unbind();
            this.clear();
            this._zr.dispose();
            this._zr = null;
K
kener 已提交
1701
        }
K
kener 已提交
1702
    };
K
kener 已提交
1703 1704 1705

    return self;
});