dataZoom.js 41.2 KB
Newer Older
K
kener 已提交
1 2 3 4 5 6 7 8
/**
 * echarts组件:数据区域缩放
 *
 * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, linzhifeng@baidu.com)
 *
 */
define(function (require) {
K
kener 已提交
9 10 11
    var Base = require('./base');
    
    // 图形依赖
K
kener 已提交
12 13 14 15
    var RectangleShape = require('zrender/shape/Rectangle');
    var PolygonShape = require('zrender/shape/Polygon');
    var IconShape = require('../util/shape/Icon');
    
K
kener 已提交
16 17 18
    var ecConfig = require('../config');
    var zrUtil = require('zrender/tool/util');

K
kener 已提交
19 20 21 22 23 24 25
    /**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} option 图表参数
     * @param {Object} component 组件
     */
K
kener 已提交
26 27
    function DataZoom(ecTheme, messageCenter, zr, option, component) {
        Base.call(this, ecTheme, zr, option);
K
kener 已提交
28

K
kener 已提交
29 30
        this.messageCenter = messageCenter;
        this.component = component;
K
kener 已提交
31

K
kener 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
        var self = this;
        /**
         * 拖拽范围控制
         */
        self._ondrift = function (dx, dy) {
            var e = this;
            if (self.zoomOption.zoomLock) {
                // zoomLock时把handle转成filler的拖拽
                e = this._fillerShae;
            }
            
            var detailSize = e._type == 'filler' ? self._handleSize : 0;
            if (self.zoomOption.orient == 'horizontal') {
                if (e.style.x + dx - detailSize <= self._location.x) {
                    e.style.x = self._location.x + detailSize;
                }
                else if (e.style.x + dx + e.style.width + detailSize
                         >= self._location.x + self._location.width
                ) {
                    e.style.x = self._location.x + self._location.width
                                - e.style.width - detailSize;
                }
                else {
                    e.style.x += dx;
                }
            }
            else {
                if (e.style.y + dy - detailSize <= self._location.y) {
                    e.style.y = self._location.y + detailSize;
                }
                else if (e.style.y + dy + e.style.height + detailSize
                         >= self._location.y + self._location.height
                ) {
                    e.style.y = self._location.y + self._location.height
                                - e.style.height - detailSize;
                }
                else {
                    e.style.y += dy;
                }
            }
K
kener 已提交
72

K
kener 已提交
73 74 75 76 77 78
            if (e._type == 'filler') {
                self._syncHandleShape();
            }
            else {
                self._syncFillerShape();
            }
K
kener 已提交
79

K
kener 已提交
80 81 82 83 84 85 86 87 88
            if (self.zoomOption.realtime) {
                self._syncData();
            }
            else {
                clearTimeout(self._syncTicket);
                self._syncTicket = setTimeout(function (){
                    self._syncData()
                }, 200);
            }
K
kener 已提交
89

K
kener 已提交
90 91 92 93 94 95
            return true;
        };
        
        self._ondragend = function () {
            self.isDragend = true;
        };
K
kener 已提交
96

K
kener 已提交
97 98 99 100 101 102 103 104 105 106
        self.init(option);
    }
    
    DataZoom.prototype = {
        type : ecConfig.COMPONENT_TYPE_DATAZOOM,
        _buildShape : function () {
            this._buildBackground();
            this._buildFiller();
            this._buildHandle();
            this._buildFrame();
K
kener 已提交
107

K
kener 已提交
108 109
            for (var i = 0, l = this.shapeList.length; i < l; i++) {
                this.zr.addShape(this.shapeList[i]);
K
kener 已提交
110
            }
K
kener 已提交
111 112
            this._syncFrameShape();
        },
K
kener 已提交
113 114 115 116

        /**
         * 根据选项计算实体的位置坐标
         */
K
kener 已提交
117
        _getLocation : function () {
K
kener 已提交
118 119 120 121
            var x;
            var y;
            var width;
            var height;
K
kener 已提交
122
            var grid = this.component.grid;
K
kener 已提交
123 124

            // 不指定则根据grid适配
K
kener 已提交
125
            if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
126
                // 水平布局
K
kener 已提交
127 128 129 130 131 132
                width = this.zoomOption.width || grid.getWidth();
                height = this.zoomOption.height || this._fillerSize;
                x = typeof this.zoomOption.x != 'undefined'
                    ? this.zoomOption.x : grid.getX();
                y = typeof this.zoomOption.y != 'undefined'
                    ? this.zoomOption.y : (this.zr.getHeight() - height - 2);
K
kener 已提交
133 134 135
            }
            else {
                // 垂直布局
K
kener 已提交
136 137 138 139 140 141
                width = this.zoomOption.width || this._fillerSize;
                height = this.zoomOption.height || grid.getHeight();
                x = typeof this.zoomOption.x != 'undefined'
                    ? this.zoomOption.x : 2;
                y = typeof this.zoomOption.y != 'undefined'
                    ? this.zoomOption.y : grid.getY();
K
kener 已提交
142 143 144 145 146 147 148 149
            }

            return {
                x : x,
                y : y,
                width : width,
                height : height
            };
K
kener 已提交
150
        },
K
kener 已提交
151 152 153 154 155

        /**
         * 计算缩放参数
         * 修正单坐标轴只传对象为数组。
         */
K
kener 已提交
156 157 158
        _getZoom : function () {
            var series = this.option.series;
            var xAxis = this.option.xAxis;
K
kener 已提交
159 160
            if (xAxis && !(xAxis instanceof Array)) {
                xAxis = [xAxis];
K
kener 已提交
161
                this.option.xAxis = xAxis;
K
kener 已提交
162
            }
K
kener 已提交
163
            var yAxis = this.option.yAxis;
K
kener 已提交
164 165
            if (yAxis && !(yAxis instanceof Array)) {
                yAxis = [yAxis];
K
kener 已提交
166
                this.option.yAxis = yAxis;
K
kener 已提交
167 168 169 170 171 172
            }

            var zoomSeriesIndex = [];
            var xAxisIndex;
            var yAxisIndex;

K
kener 已提交
173
            var zOptIdx = this.zoomOption.xAxisIndex;
K
kener 已提交
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
            if (xAxis && typeof zOptIdx == 'undefined') {
                xAxisIndex = [];
                for (var i = 0, l = xAxis.length; i < l; i++) {
                    // 横纵默认为类目轴
                    if (xAxis[i].type == 'category'
                        || typeof xAxis[i].type == 'undefined'
                    ) {
                        xAxisIndex.push(i);
                    }
                }
            }
            else {
                if (zOptIdx instanceof Array) {
                    xAxisIndex = zOptIdx;
                }
                else if (typeof zOptIdx != 'undefined') {
                    xAxisIndex = [zOptIdx];
                }
                else {
                    xAxisIndex = [];
                }
            }

K
kener 已提交
197
            zOptIdx = this.zoomOption.yAxisIndex;
K
kener 已提交
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
            if (yAxis && typeof zOptIdx == 'undefined') {
                yAxisIndex = [];
                for (var i = 0, l = yAxis.length; i < l; i++) {
                    if (yAxis[i].type == 'category') {
                        yAxisIndex.push(i);
                    }
                }
            }
            else {
                if (zOptIdx instanceof Array) {
                    yAxisIndex = zOptIdx;
                }
                else if (typeof zOptIdx != 'undefined') {
                    yAxisIndex = [zOptIdx];
                }
                else {
                    yAxisIndex = [];
                }
            }

            // 找到缩放控制的所有series
            for (var i = 0, l = series.length; i < l; i++) {
K
kener 已提交
220 221 222 223 224 225 226
                if (series[i].type != ecConfig.CHART_TYPE_LINE
                    && series[i].type != ecConfig.CHART_TYPE_BAR
                    && series[i].type != ecConfig.CHART_TYPE_SCATTER
                    && series[i].type != ecConfig.CHART_TYPE_K
                ) {
                    continue;
                }
K
kener 已提交
227 228 229 230 231 232 233 234 235 236 237 238
                for (var j = 0, k = xAxisIndex.length; j < k; j++) {
                    if (xAxisIndex[j] == (series[i].xAxisIndex || 0)) {
                        zoomSeriesIndex.push(i);
                        break;
                    }
                }
                for (var j = 0, k = yAxisIndex.length; j < k; j++) {
                    if (yAxisIndex[j] == (series[i].yAxisIndex || 0)) {
                        zoomSeriesIndex.push(i);
                        break;
                    }
                }
K
kener 已提交
239 240
                // 不指定接管坐标轴,则散点图被纳入接管范围
                if (series[i].type == ecConfig.CHART_TYPE_SCATTER
K
kener 已提交
241 242
                    && typeof this.zoomOption.xAxisIndex == 'undefined'
                    && typeof this.zoomOption.yAxisIndex == 'undefined'
K
kener 已提交
243 244 245
                ) {
                    zoomSeriesIndex.push(i);
                }
K
kener 已提交
246 247
            }

K
kener 已提交
248 249 250 251 252 253 254 255
            var start = typeof this.zoomOption.start != 'undefined'
                        && this.zoomOption.start >= 0
                        && this.zoomOption.start <= 100
                        ? this.zoomOption.start : 0;
            var end = typeof this.zoomOption.end != 'undefined'
                      && this.zoomOption.end >= 0
                      && this.zoomOption.end <= 100
                      ? this.zoomOption.end : 100;
K
kener 已提交
256 257 258 259 260 261 262 263
            if (start > end) {
                // 大小颠倒自动翻转
                start = start + end;
                end = start - end;
                start = start - end;
            }
            var size = Math.round(
                           (end - start) / 100
K
kener 已提交
264 265
                           * (this.zoomOption.orient == 'horizontal'
                             ? this._location.width : this._location.height)
K
kener 已提交
266 267 268 269
                       );
            return {
                start : start,
                end : end,
K
kener 已提交
270 271
                start2 : 0,
                end2 : 100,
K
kener 已提交
272 273 274 275 276
                size : size,
                xAxisIndex : xAxisIndex,
                yAxisIndex : yAxisIndex,
                seriesIndex : zoomSeriesIndex
            };
K
kener 已提交
277
        },
K
kener 已提交
278

K
kener 已提交
279 280
        _backupData : function () {
            this._originalData = {
K
kener 已提交
281 282 283 284
                xAxis : {},
                yAxis : {},
                series : {}
            };
K
kener 已提交
285 286
            var xAxis = this.option.xAxis;
            var xAxisIndex = this._zoom.xAxisIndex;
K
kener 已提交
287
            for (var i = 0, l = xAxisIndex.length; i < l; i++) {
K
kener 已提交
288
                this._originalData.xAxis[xAxisIndex[i]] = xAxis[xAxisIndex[i]].data;
K
kener 已提交
289 290
            }

K
kener 已提交
291 292
            var yAxis = this.option.yAxis;
            var yAxisIndex = this._zoom.yAxisIndex;
K
kener 已提交
293
            for (var i = 0, l = yAxisIndex.length; i < l; i++) {
K
kener 已提交
294
                this._originalData.yAxis[yAxisIndex[i]] = yAxis[yAxisIndex[i]].data;
K
kener 已提交
295 296
            }

K
kener 已提交
297 298
            var series = this.option.series;
            var seriesIndex = this._zoom.seriesIndex;
K
kener 已提交
299
            var serie;
K
kener 已提交
300
            for (var i = 0, l = seriesIndex.length; i < l; i++) {
K
kener 已提交
301
                serie = series[seriesIndex[i]];
K
kener 已提交
302
                this._originalData.series[seriesIndex[i]] = serie.data;
K
kener 已提交
303
                if (serie.type == ecConfig.CHART_TYPE_SCATTER) {
K
kener 已提交
304
                    this._calculScatterMap(seriesIndex[i]);
K
kener 已提交
305
                }
K
kener 已提交
306
            }
K
kener 已提交
307
        },
K
kener 已提交
308
        
K
kener 已提交
309 310 311
        _calculScatterMap : function (seriesIndex) {
            this._zoom.scatterMap = this._zoom.scatterMap || {};
            this._zoom.scatterMap[seriesIndex] = this._zoom.scatterMap[seriesIndex] || {};
K
kener 已提交
312
            var componentLibrary = require('../component');
K
kener 已提交
313
            var zrUtil = require('zrender/tool/util');
K
kener 已提交
314 315
            // x轴极值
            var Axis = componentLibrary.get('axis');
K
kener 已提交
316
            var axisOption = zrUtil.clone(this.option.xAxis);
K
kener 已提交
317 318 319 320 321 322 323
            if (axisOption instanceof Array) {
                axisOption[0].type = 'value';
                axisOption[1] && (axisOption[1].type = 'value');
            }
            else {
                axisOption.type = 'value';
            }
K
kener 已提交
324
            var vAxis = new Axis(
K
kener 已提交
325
                this.ecTheme,
K
kener 已提交
326
                null,   // messageCenter
K
kener 已提交
327
                false,  // this.zr
K
kener 已提交
328
                {
K
kener 已提交
329
                    xAxis: axisOption,
K
kener 已提交
330
                    series : this.option.series
K
kener 已提交
331
                }, 
K
kener 已提交
332
                this.component,
K
kener 已提交
333 334
                'xAxis'
            );
K
kener 已提交
335 336
            var axisIndex = this.option.series[seriesIndex].xAxisIndex || 0;
            this._zoom.scatterMap[seriesIndex].x = 
K
kener 已提交
337
                vAxis.getAxis(axisIndex).getExtremum();
K
kener 已提交
338
            vAxis.dispose();
K
kener 已提交
339 340
            
            // y轴极值
K
kener 已提交
341
            axisOption = zrUtil.clone(this.option.yAxis);
K
kener 已提交
342 343 344 345 346 347 348
            if (axisOption instanceof Array) {
                axisOption[0].type = 'value';
                axisOption[1] && (axisOption[1].type = 'value');
            }
            else {
                axisOption.type = 'value';
            }
K
kener 已提交
349
            vAxis = new Axis(
K
kener 已提交
350
                this.ecTheme,
K
kener 已提交
351
                null,   // messageCenter
K
kener 已提交
352
                false,  // this.zr
K
kener 已提交
353
                {
K
kener 已提交
354
                    yAxis: axisOption,
K
kener 已提交
355
                    series : this.option.series
K
kener 已提交
356
                }, 
K
kener 已提交
357
                this.component,
K
kener 已提交
358 359
                'yAxis'
            );
K
kener 已提交
360 361
            axisIndex = this.option.series[seriesIndex].yAxisIndex || 0;
            this._zoom.scatterMap[seriesIndex].y = 
K
kener 已提交
362
                vAxis.getAxis(axisIndex).getExtremum();
K
kener 已提交
363
            vAxis.dispose();
K
kener 已提交
364 365
            // console.log(this._zoom.scatterMap);
        },
K
kener 已提交
366

K
kener 已提交
367
        _buildBackground : function () {
K
kener 已提交
368
            // 背景
K
kener 已提交
369 370
            this.shapeList.push(new RectangleShape({
                zlevel : this._zlevelBase,
K
kener 已提交
371 372
                hoverable :false,
                style : {
K
kener 已提交
373 374 375 376 377
                    x : this._location.x,
                    y : this._location.y,
                    width : this._location.width,
                    height : this._location.height,
                    color : this.zoomOption.backgroundColor
K
kener 已提交
378
                }
K
kener 已提交
379
            }));
K
kener 已提交
380 381
            
            // 数据阴影
K
kener 已提交
382
            var maxLength = 0;
K
kener 已提交
383 384
            var xAxis = this._originalData.xAxis;
            var xAxisIndex = this._zoom.xAxisIndex;
K
kener 已提交
385 386
            for (var i = 0, l = xAxisIndex.length; i < l; i++) {
                maxLength = Math.max(
K
kener 已提交
387
                    maxLength, xAxis[xAxisIndex[i]].length
K
kener 已提交
388 389
                );
            }
K
kener 已提交
390 391
            var yAxis = this._originalData.yAxis;
            var yAxisIndex = this._zoom.yAxisIndex;
K
kener 已提交
392 393
            for (var i = 0, l = yAxisIndex.length; i < l; i++) {
                maxLength = Math.max(
K
kener 已提交
394
                    maxLength, yAxis[yAxisIndex[i]].length
K
kener 已提交
395 396 397
                );
            }

K
kener 已提交
398 399
            var seriesIndex = this._zoom.seriesIndex[0];
            var data = this._originalData.series[seriesIndex];
K
kener 已提交
400 401 402 403 404 405 406 407
            var maxValue = Number.MIN_VALUE;
            var minValue = Number.MAX_VALUE;
            var value;
            for (var i = 0, l = data.length; i < l; i++) {
                value = typeof data[i] != 'undefined'
                        ? (typeof data[i].value != 'undefined'
                          ? data[i].value : data[i])
                        : 0;
K
kener 已提交
408
                if (this.option.series[seriesIndex].type == ecConfig.CHART_TYPE_K) {
K
kener 已提交
409 410
                    value = value[1];   // 收盘价
                }
K
kener 已提交
411 412 413 414 415 416 417 418
                if (isNaN(value)) {
                    value = 0;
                }
                maxValue = Math.max(maxValue, value);
                minValue = Math.min(minValue, value);
            }

            var pointList = [];
K
kener 已提交
419 420
            var x = this._location.width / (maxLength - (maxLength > 1 ? 1 : 0));
            var y = this._location.height / (maxLength - (maxLength > 1 ? 1 : 0));
K
kener 已提交
421 422 423 424 425
            for (var i = 0, l = maxLength; i < l; i++) {
                value = typeof data[i] != 'undefined'
                        ? (typeof data[i].value != 'undefined'
                          ? data[i].value : data[i])
                        : 0;
K
kener 已提交
426
                if (this.option.series[seriesIndex].type == ecConfig.CHART_TYPE_K) {
K
kener 已提交
427 428
                    value = value[1];   // 收盘价
                }
K
kener 已提交
429 430 431
                if (isNaN(value)) {
                    value = 0;
                }
K
kener 已提交
432
                if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
433
                    pointList.push([
K
kener 已提交
434 435
                        this._location.x + x * i,
                        this._location.y + this._location.height - 5 - Math.round(
K
kener 已提交
436 437
                            (value - minValue)
                            / (maxValue - minValue)
K
kener 已提交
438
                            * (this._location.height - 10)
K
kener 已提交
439 440 441 442 443
                        )
                    ]);
                }
                else {
                    pointList.push([
K
kener 已提交
444
                        this._location.x + 5 + Math.round(
K
kener 已提交
445 446
                            (value - minValue)
                            / (maxValue - minValue)
K
kener 已提交
447
                            * (this._location.width - 10)
K
kener 已提交
448
                        ),
K
kener 已提交
449
                        this._location.y + y * i
K
kener 已提交
450 451 452
                    ]);
                }
            }
K
kener 已提交
453
            if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
454
                 pointList.push([
K
kener 已提交
455 456
                    this._location.x + this._location.width,
                    this._location.y + this._location.height
K
kener 已提交
457 458
                ]);
                pointList.push([
K
kener 已提交
459
                    this._location.x, this._location.y + this._location.height
K
kener 已提交
460 461 462 463
                ]);
            }
            else {
                pointList.push([
K
kener 已提交
464
                    this._location.x, this._location.y + this._location.height
K
kener 已提交
465 466
                ]);
                pointList.push([
K
kener 已提交
467
                    this._location.x, this._location.y
K
kener 已提交
468 469 470
                ]);
            }

K
kener 已提交
471 472
            this.shapeList.push(new PolygonShape({
                zlevel : this._zlevelBase,
K
kener 已提交
473 474
                style : {
                    pointList : pointList,
K
kener 已提交
475
                    color : this.zoomOption.dataBackgroundColor
K
kener 已提交
476 477
                },
                hoverable : false
K
kener 已提交
478
            }));
K
kener 已提交
479
        },
K
kener 已提交
480 481 482 483

        /**
         * 构建填充物
         */
K
kener 已提交
484 485 486
        _buildFiller : function () {
            this._fillerShae = {
                zlevel : this._zlevelBase,
K
kener 已提交
487
                draggable : true,
K
kener 已提交
488 489
                ondrift : this._ondrift,
                ondragend : this._ondragend,
K
kener 已提交
490 491 492
                _type : 'filler'
            };

K
kener 已提交
493
            if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
494
                // 横向
K
kener 已提交
495 496 497 498 499 500 501 502 503
                this._fillerShae.style = {
                    x : this._location.x
                        + Math.round(this._zoom.start / 100 * this._location.width)
                        + this._handleSize,
                    y : this._location.y,
                    width : this._zoom.size - this._handleSize * 2,
                    height : this._location.height,
                    color : this.zoomOption.fillerColor,
                    // strokeColor : '#fff', // this.zoomOption.handleColor,
K
kener 已提交
504
                    // lineWidth: 2,
K
kener 已提交
505 506 507 508 509
                    text : ':::',
                    textPosition : 'inside'
                };
            }
            else {
K
kener 已提交
510
                // 纵向
K
kener 已提交
511 512 513 514 515 516 517 518 519
                this._fillerShae.style ={
                    x : this._location.x,
                    y : this._location.y
                        + Math.round(this._zoom.start / 100 * this._location.height)
                        + this._handleSize,
                    width :  this._location.width,
                    height : this._zoom.size - this._handleSize * 2,
                    color : this.zoomOption.fillerColor,
                    // strokeColor : '#fff', // this.zoomOption.handleColor,
K
kener 已提交
520 521
                    // lineWidth: 2,
                    text : '::',
K
kener 已提交
522 523 524
                    textPosition : 'inside'
                };
            }
K
kener 已提交
525
            
K
kener 已提交
526
            this._fillerShae.highlightStyle = {
K
kener 已提交
527 528 529 530
                brushType: 'fill',
                color : 'rgba(0,0,0,0)'
                /*
                color : require('zrender/tool/color').alpha(
K
kener 已提交
531
                            this._fillerShae.style.color, 0
K
kener 已提交
532 533 534
                        )
                */
            };
K
kener 已提交
535 536 537
            this._fillerShae = new RectangleShape(this._fillerShae);
            this.shapeList.push(this._fillerShae);
        },
K
kener 已提交
538 539 540 541

        /**
         * 构建拖拽手柄
         */
K
kener 已提交
542
        _buildHandle : function () {
K
kener 已提交
543
            var zrUtil = require('zrender/tool/util');
K
kener 已提交
544 545
            this._startShape = {
                zlevel : this._zlevelBase,
K
kener 已提交
546 547 548
                draggable : true,
                style : {
                    iconType: 'rectangle',
K
kener 已提交
549 550 551 552 553
                    x : this._location.x,
                    y : this._location.y,
                    width : this._handleSize,
                    height : this._handleSize,
                    color : this.zoomOption.handleColor,
K
kener 已提交
554
                    text : '=',
K
kener 已提交
555
                    textPosition : 'inside'
K
kener 已提交
556 557 558 559
                },
                highlightStyle : {
                    brushType: 'fill'
                },
K
kener 已提交
560 561
                ondrift : this._ondrift,
                ondragend : this._ondragend
K
kener 已提交
562 563
            };
            
K
kener 已提交
564 565 566
            if (this.zoomOption.orient == 'horizontal') {
                this._startShape.style.height = this._location.height;
                this._endShape = zrUtil.clone(this._startShape);
K
kener 已提交
567
                
K
kener 已提交
568 569 570
                this._startShape.style.x = this._fillerShae.style.x - this._handleSize,
                this._endShape.style.x = this._fillerShae.style.x  
                                    + this._fillerShae.style.width;
K
kener 已提交
571 572
            }
            else {
K
kener 已提交
573 574
                this._startShape.style.width = this._location.width;
                this._endShape = zrUtil.clone(this._startShape);
K
kener 已提交
575
                
K
kener 已提交
576 577 578 579 580 581 582 583 584
                this._startShape.style.y = this._fillerShae.style.y - this._handleSize;
                this._endShape.style.y = this._fillerShae.style.y 
                                    + this._fillerShae.style.height;
            }
            this._startShape = new IconShape(this._startShape);
            this._endShape = new IconShape(this._endShape);
            this.shapeList.push(this._startShape);
            this.shapeList.push(this._endShape);
        },
K
kener 已提交
585

K
kener 已提交
586 587 588
        /**
         * 构建特效边框
         */
K
kener 已提交
589
        _buildFrame : function () {
K
kener 已提交
590 591
            var zrUtil = require('zrender/tool/util');
            // 特效框线,亚像素优化
K
kener 已提交
592 593 594 595
            var x = this.subPixelOptimize(this._location.x, 1);
            var y = this.subPixelOptimize(this._location.y, 1);
            this._startFrameShape = {
                zlevel : this._zlevelBase,
K
kener 已提交
596 597 598 599
                hoverable :false,
                style : {
                    x : x,
                    y : y,
K
kener 已提交
600 601
                    width : this._location.width - (x > this._location.x ? 1 : 0),
                    height : this._location.height - (y > this._location.y ? 1 : 0),
K
kener 已提交
602 603
                    lineWidth: 1,
                    brushType: 'stroke',
K
kener 已提交
604
                    strokeColor : this.zoomOption.handleColor
K
kener 已提交
605 606
                }
            };
K
kener 已提交
607
            this._endFrameShape = zrUtil.clone(this._startFrameShape);
K
kener 已提交
608
            
K
kener 已提交
609 610 611 612
            this._startFrameShape = new RectangleShape(this._startFrameShape);
            this._endFrameShape = new RectangleShape(this._endFrameShape);
            this.shapeList.push(this._startFrameShape);
            this.shapeList.push();
K
kener 已提交
613
            return;
K
kener 已提交
614
        },
K
kener 已提交
615
        
K
kener 已提交
616 617 618 619 620
        _syncHandleShape : function () {
            if (this.zoomOption.orient == 'horizontal') {
                this._startShape.style.x = this._fillerShae.style.x - this._handleSize;
                this._endShape.style.x = this._fillerShae.style.x
                                    + this._fillerShae.style.width;
K
kener 已提交
621
                
K
kener 已提交
622 623 624
                this._zoom.start = Math.floor(
                    (this._startShape.style.x - this._location.x)
                    / this._location.width * 100
K
kener 已提交
625
                );
K
kener 已提交
626 627 628
                this._zoom.end = Math.ceil(
                    (this._endShape.style.x + this._handleSize - this._location.x)
                    / this._location.width * 100
K
kener 已提交
629 630 631
                );
            }
            else {
K
kener 已提交
632 633 634 635 636 637
                this._startShape.style.y = this._fillerShae.style.y - this._handleSize;
                this._endShape.style.y = this._fillerShae.style.y
                                    + this._fillerShae.style.height;
                this._zoom.start = Math.floor(
                    (this._startShape.style.y - this._location.y)
                    / this._location.height * 100
K
kener 已提交
638
                );
K
kener 已提交
639 640 641
                this._zoom.end = Math.ceil(
                    (this._endShape.style.y + this._handleSize - this._location.y)
                    / this._location.height * 100
K
kener 已提交
642 643 644
                );
            }

K
kener 已提交
645 646
            this.zr.modShape(this._startShape.id, this._startShape);
            this.zr.modShape(this._endShape.id, this._endShape);
K
kener 已提交
647 648
            
            // 同步边框
K
kener 已提交
649
            this._syncFrameShape();
K
kener 已提交
650
            
K
kener 已提交
651 652
            this.zr.refresh();
        },
K
kener 已提交
653

K
kener 已提交
654
        _syncFillerShape : function () {
K
kener 已提交
655 656
            var a;
            var b;
K
kener 已提交
657 658 659 660 661 662 663 664
            if (this.zoomOption.orient == 'horizontal') {
                a = this._startShape.style.x;
                b = this._endShape.style.x;
                this._fillerShae.style.x = Math.min(a, b) + this._handleSize;
                this._fillerShae.style.width = Math.abs(a - b) - this._handleSize;
                this._zoom.start = Math.floor(
                    (Math.min(a, b) - this._location.x)
                    / this._location.width * 100
K
kener 已提交
665
                );
K
kener 已提交
666 667 668
                this._zoom.end = Math.ceil(
                    (Math.max(a, b) + this._handleSize - this._location.x)
                    / this._location.width * 100
K
kener 已提交
669 670 671
                );
            }
            else {
K
kener 已提交
672 673 674 675 676 677 678
                a = this._startShape.style.y;
                b = this._endShape.style.y;
                this._fillerShae.style.y = Math.min(a, b) + this._handleSize;
                this._fillerShae.style.height = Math.abs(a - b) - this._handleSize;
                this._zoom.start = Math.floor(
                    (Math.min(a, b) - this._location.y)
                    / this._location.height * 100
K
kener 已提交
679
                );
K
kener 已提交
680 681 682
                this._zoom.end = Math.ceil(
                    (Math.max(a, b) + this._handleSize - this._location.y)
                    / this._location.height * 100
K
kener 已提交
683 684 685
                );
            }

K
kener 已提交
686
            this.zr.modShape(this._fillerShae.id, this._fillerShae);
K
kener 已提交
687 688
            
            // 同步边框
K
kener 已提交
689
            this._syncFrameShape();
K
kener 已提交
690
            
K
kener 已提交
691 692
            this.zr.refresh();
        },
693
        
K
kener 已提交
694 695 696 697 698 699 700 701
        _syncFrameShape : function () {
            if (this.zoomOption.orient == 'horizontal') {
                this._startFrameShape.style.width = 
                    this._fillerShae.style.x - this._location.x;
                this._endFrameShape.style.x = 
                    this._fillerShae.style.x + this._fillerShae.style.width;
                this._endFrameShape.style.width = 
                    this._location.x + this._location.width - this._endFrameShape.style.x;
K
kener 已提交
702 703
            }
            else {
K
kener 已提交
704 705 706 707 708 709
                this._startFrameShape.style.height = 
                    this._fillerShae.style.y - this._location.y;
                this._endFrameShape.style.y = 
                    this._fillerShae.style.y + this._fillerShae.style.height;
                this._endFrameShape.style.height = 
                    this._location.y + this._location.height - this._endFrameShape.style.y;
K
kener 已提交
710 711
            }
                    
K
kener 已提交
712 713 714
            this.zr.modShape(this._startFrameShape.id, this._startFrameShape);
            this.zr.modShape(this._endFrameShape.id, this._endFrameShape);
        },
K
kener 已提交
715
        
K
kener 已提交
716 717
        _syncShape : function () {
            if (!this.zoomOption.show) {
K
kener 已提交
718 719 720
                // 没有伸缩控件
                return;
            }
K
kener 已提交
721 722 723 724 725 726
            if (this.zoomOption.orient == 'horizontal') {
                this._startShape.style.x = this._location.x 
                                      + this._zoom.start / 100 * this._location.width;
                this._endShape.style.x = this._location.x 
                                    + this._zoom.end / 100 * this._location.width
                                    - this._handleSize;
727
                    
K
kener 已提交
728 729 730 731
                this._fillerShae.style.x = this._startShape.style.x + this._handleSize;
                this._fillerShae.style.width = this._endShape.style.x 
                                          - this._startShape.style.x
                                          - this._handleSize;
732 733
            }
            else {
K
kener 已提交
734 735 736 737 738
                this._startShape.style.y = this._location.y 
                                      + this._zoom.start / 100 * this._location.height;
                this._endShape.style.y = this._location.y 
                                    + this._zoom.end / 100 * this._location.height
                                    - this._handleSize;
739
                    
K
kener 已提交
740 741 742 743
                this._fillerShae.style.y = this._startShape.style.y + this._handleSize;
                this._fillerShae.style.height = this._endShape.style.y 
                                          - this._startShape.style.y
                                          - this._handleSize;
744 745
            }
            
K
kener 已提交
746 747 748
            this.zr.modShape(this._startShape.id, this._startShape);
            this.zr.modShape(this._endShape.id, this._endShape);
            this.zr.modShape(this._fillerShae.id, this._fillerShae);
K
kener 已提交
749
            // 同步边框
K
kener 已提交
750 751 752 753 754
            this._syncFrameShape();
            this.zr.refresh();
        },
        
         _syncData : function (dispatchNow) {
K
kener 已提交
755 756 757 758 759
            var target;
            var start;
            var end;
            var length;
            var data;
K
kener 已提交
760 761
            for (var key in this._originalData) {
                target = this._originalData[key];
K
kener 已提交
762 763 764
                for (var idx in target) {
                    data = target[idx];
                    length = data.length;
K
kener 已提交
765 766 767 768
                    start = Math.floor(this._zoom.start / 100 * length);
                    end = Math.ceil(this._zoom.end / 100 * length);
                    if (this.option[key][idx].type != ecConfig.CHART_TYPE_SCATTER) {
                        this.option[key][idx].data = data.slice(start, end);
K
kener 已提交
769 770 771
                    }
                    else {
                        // 散点图特殊处理
K
kener 已提交
772
                        this.option[key][idx].data = _synScatterData(idx, data);
K
kener 已提交
773
                    }
K
kener 已提交
774 775 776
                }
            }

K
kener 已提交
777 778
            if (!this._isSilence && (this.zoomOption.realtime || dispatchNow)) {
                this.messageCenter.dispatch(
K
kener 已提交
779 780
                    ecConfig.EVENT.DATA_ZOOM,
                    null,
K
kener 已提交
781
                    {zoom: this._zoom}
K
kener 已提交
782
                );
K
kener 已提交
783 784
            }

K
kener 已提交
785 786 787
            this.zoomOption.start = this._zoom.start;
            this.zoomOption.end = this._zoom.end;
        },
K
kener 已提交
788
        
K
kener 已提交
789
        _synScatterData : function (seriesIndex, data) {
K
kener 已提交
790
            var newData = [];
K
kener 已提交
791
            var scale = this._zoom.scatterMap[seriesIndex];
K
kener 已提交
792 793 794 795 796 797
            var total;
            var xStart;
            var xEnd;
            var yStart;
            var yEnd;
            
K
kener 已提交
798
            if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
799
                total = scale.x.max - scale.x.min;
K
kener 已提交
800 801
                xStart = this._zoom.start / 100 * total + scale.x.min;
                xEnd = this._zoom.end / 100 * total + scale.x.min;
K
kener 已提交
802 803
                
                total = scale.y.max - scale.y.min;
K
kener 已提交
804 805
                yStart = this._zoom.start2 / 100 * total + scale.y.min;
                yEnd = this._zoom.end2 / 100 * total + scale.y.min;
K
kener 已提交
806 807 808
            }
            else {
                total = scale.x.max - scale.x.min;
K
kener 已提交
809 810
                xStart = this._zoom.start2 / 100 * total + scale.x.min;
                xEnd = this._zoom.end2 / 100 * total + scale.x.min;
K
kener 已提交
811 812
                
                total = scale.y.max - scale.y.min;
K
kener 已提交
813 814
                yStart = this._zoom.start / 100 * total + scale.y.min;
                yEnd = this._zoom.end / 100 * total + scale.y.min;
K
kener 已提交
815 816 817
            }
            
            // console.log(xStart,xEnd,yStart,yEnd);
K
kener 已提交
818
            var value;
K
kener 已提交
819
            for (var i = 0, l = data.length; i < l; i++) {
K
kener 已提交
820 821 822 823 824
                value = data[i].value || data[i];
                if (value[0] >= xStart 
                    && value[0] <= xEnd
                    && value[1] >= yStart
                    && value[1] <= yEnd
K
kener 已提交
825 826 827 828 829 830
                ) {
                    newData.push(data[i]);
                }
            }
            
            return newData;
K
kener 已提交
831
        },
K
kener 已提交
832 833 834 835

        /**
         * 数据项被拖拽出去
         */
K
kener 已提交
836 837
        ondragend : function (param, status) {
            if (!this.isDragend || !param.target) {
K
kener 已提交
838 839 840 841
                // 没有在当前实例上发生拖拽行为则直接返回
                return;
            }

K
kener 已提交
842
             this._syncData();
K
kener 已提交
843 844 845 846

            // 别status = {}赋值啊!!
            status.dragOut = true;
            status.dragIn = true;
K
kener 已提交
847 848
            if (!this._isSilence && !this.zoomOption.realtime) {
                this.messageCenter.dispatch(
K
kener 已提交
849 850
                    ecConfig.EVENT.DATA_ZOOM,
                    null,
K
kener 已提交
851
                    {zoom: this._zoom}
K
kener 已提交
852
                );
K
kener 已提交
853 854 855
            }
            status.needRefresh = false; // 会有消息触发fresh,不用再刷一遍
            // 处理完拖拽事件后复位
K
kener 已提交
856
            this.isDragend = false;
K
kener 已提交
857 858

            return;
K
kener 已提交
859
        },
K
kener 已提交
860

K
kener 已提交
861
        ondataZoom : function (param, status) {
K
kener 已提交
862 863
            status.needRefresh = true;
            return;
K
kener 已提交
864
        },
865
        
K
kener 已提交
866 867 868 869 870 871 872 873
        absoluteZoom : function (param) {
            this.zoomOption.start = this._zoom.start = param.start;
            this.zoomOption.end = this._zoom.end = param.end;
            this.zoomOption.start2 = this._zoom.start2 = param.start2;
            this.zoomOption.end2 = this._zoom.end2 = param.end2;
            //console.log(rect,gridArea,this._zoom,total)
            this._syncShape();
            this._syncData(true);
K
kener 已提交
874
            return;
K
kener 已提交
875
        },
K
kener 已提交
876
        
K
kener 已提交
877
        rectZoom : function (param) {
878 879
            if (!param) {
                // 重置拖拽
K
kener 已提交
880 881 882 883
                this.zoomOption.start = 
                this.zoomOption.start2 = 
                this._zoom.start = 
                this._zoom.start2 = 0;
K
kener 已提交
884
                    
K
kener 已提交
885 886 887 888
                this.zoomOption.end =
                this.zoomOption.end2 = 
                this._zoom.end = 
                this._zoom.end2 = 100;
K
kener 已提交
889
                
K
kener 已提交
890 891 892
                this._syncShape();
                this._syncData(true);
                return this._zoom;
893
            }
K
kener 已提交
894
            var gridArea = this.component.grid.getArea();
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
            var rect = {
                x : param.x,
                y : param.y,
                width : param.width,
                height : param.height
            };
            // 修正方向框选
            if (rect.width < 0) {
                rect.x += rect.width;
                rect.width = -rect.width;
            }
            if (rect.height < 0) {
                rect.y += rect.height;
                rect.height = -rect.height;
            }
K
kener 已提交
910
            // console.log(rect,this._zoom);
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
            
            // 剔除无效缩放
            if (rect.x > gridArea.x + gridArea.width
                || rect.y > gridArea.y + gridArea.height
            ) {
                return false; // 无效缩放
            }
            
            // 修正框选超出
            if (rect.x < gridArea.x) {
                rect.x = gridArea.x;
            }
            if (rect.x + rect.width > gridArea.x + gridArea.width) {
                rect.width = gridArea.x + gridArea.width - rect.x;
            }
            if (rect.y + rect.height > gridArea.y + gridArea.height) {
                rect.height = gridArea.y + gridArea.height - rect.y;
            }
            
K
kener 已提交
930 931
            var total;
            var sdx = (rect.x - gridArea.x) / gridArea.width;
K
kener 已提交
932 933
            var edx = 1 - (rect.x + rect.width - gridArea.x) / gridArea.width;
            var sdy = 1 - (rect.y + rect.height - gridArea.y) / gridArea.height;
K
kener 已提交
934
            var edy = (rect.y - gridArea.y) / gridArea.height;
K
kener 已提交
935 936 937 938 939
            //console.log('this',sdy,edy,this._zoom.start,this._zoom.end)
            if (this.zoomOption.orient == 'horizontal') {
                total = this._zoom.end - this._zoom.start;
                this._zoom.start += total * sdx;
                this._zoom.end -= total * edx;
K
kener 已提交
940
                
K
kener 已提交
941 942 943
                total = this._zoom.end2 - this._zoom.start2;
                this._zoom.start2 += total * sdy;
                this._zoom.end2 -= total * edy;
K
kener 已提交
944 945
            }
            else {
K
kener 已提交
946 947 948
                total = this._zoom.end - this._zoom.start;
                this._zoom.start += total * sdy;
                this._zoom.end -= total * edy;
K
kener 已提交
949
                
K
kener 已提交
950 951 952 953 954 955 956 957 958 959 960 961 962 963
                total = this._zoom.end2 - this._zoom.start2;
                this._zoom.start2 += total * sdx;
                this._zoom.end2 -= total * edx;
            }
            //console.log(this._zoom.start,this._zoom.end,this._zoom.start2,this._zoom.end2)
            this.zoomOption.start = this._zoom.start;
            this.zoomOption.end = this._zoom.end;
            this.zoomOption.start2 = this._zoom.start2;
            this.zoomOption.end2 = this._zoom.end2;
            //console.log(rect,gridArea,this._zoom,total)
            this._syncShape();
            this._syncData(true);
            return this._zoom;
        },
K
kener 已提交
964
        
K
kener 已提交
965
        syncBackupData : function (curOption, optionBackup) {
K
kener 已提交
966
            var start;
K
kener 已提交
967
            var target = this._originalData['series'];
K
kener 已提交
968 969 970 971 972 973
            var curSeries = curOption.series;
            var curData;
            for (var i = 0, l = curSeries.length; i < l; i++) {
                curData = curSeries[i].data;
                if (target[i]) {
                    // dataZoom接管的
K
kener 已提交
974
                    start = Math.floor(this._zoom.start / 100 * target[i].length);
K
kener 已提交
975 976 977 978 979 980
                }
                else {
                    // 非dataZoom接管
                    start = 0;
                }
                for (var j = 0, k = curData.length; j < k; j++) {
K
kener 已提交
981 982 983 984 985
                    optionBackup.series[i].data[j + start] = curData[j];
                    if (target[i]) {
                        // 同步内部备份
                        target[i][j + start] 
                            = curData[j];
K
kener 已提交
986 987 988
                    }
                }
            }
K
kener 已提交
989
        },
990
        
K
kener 已提交
991 992 993
        silence : function (s) {
            this._isSilence = s;
        },
994
        
K
kener 已提交
995 996
        getRealDataIndex : function (sIdx, dIdx) {
            if (!this._originalData) {
K
kener 已提交
997 998
                return dIdx;
            }
K
kener 已提交
999
            var sreies = this._originalData.series;
1000
            if (sreies[sIdx]) {
K
kener 已提交
1001
                return Math.floor(this._zoom.start / 100 * sreies[sIdx].length) 
1002 1003 1004
                       + dIdx;
            }
            return -1;
K
kener 已提交
1005
        },
K
kener 已提交
1006

K
kener 已提交
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
        init : function (newOption) {
            this._fillerSize = 28;       // 控件大小,水平布局为高,纵向布局为宽
            this._handleSize = 8;        // 手柄大小
            // this._fillerShae;            // 填充
            // this._startShape;            // 起始手柄
            // this._endShape;              // 结束手柄
            // this._startFrameShape;       // 起始特效边框
            // this._endFrameShape;         // 结束特效边框
            // this._syncTicket;
            this._isSilence = false;
            // this._originalData;
        
            this.option = newOption;
            this.option.dataZoom = this.reformOption(this.option.dataZoom);
            this.zoomOption = this.option.dataZoom;
K
kener 已提交
1022

K
kener 已提交
1023
            this.clear();
1024 1025
            
            // 自己show 或者 toolbox启用且dataZoom有效
K
kener 已提交
1026
            if (this.option.dataZoom.show
1027
                || (
K
kener 已提交
1028 1029
                    this.query(this.option, 'toolbox.show')
                    && this.query(this.option, 'toolbox.feature.dataZoom.show')
1030 1031
                )
            ) {
K
kener 已提交
1032 1033 1034 1035 1036
                // 位置参数,通过计算所得x, y, width, height
                this._location = this._getLocation();
                // 缩放参数
                this._zoom =  this._getZoom();
                this._backupData();
1037 1038
            }
            
K
kener 已提交
1039 1040 1041
            if (this.option.dataZoom.show) {
                this._buildShape();
                this._syncData();
K
kener 已提交
1042
            }
K
kener 已提交
1043
        },
K
kener 已提交
1044 1045 1046 1047

        /**
         * 避免dataZoom带来两次refresh,不设refresh接口,resize重复一下buildshape逻辑 
         */
K
kener 已提交
1048 1049
        resize : function () {
            this.clear();
K
kener 已提交
1050 1051
            
            // 自己show 或者 toolbox启用且dataZoom有效
K
kener 已提交
1052
            if (this.option.dataZoom.show
K
kener 已提交
1053
                || (
K
kener 已提交
1054 1055
                    this.query(this.option, 'toolbox.show')
                    && this.query(this.option, 'toolbox.feature.dataZoom.show')
K
kener 已提交
1056 1057
                )
            ) {
K
kener 已提交
1058 1059
                this._location = this._getLocation();
                this._zoom =  this._getZoom();
K
kener 已提交
1060 1061
            }
            
K
kener 已提交
1062 1063
            if (this.option.dataZoom.show) {
                this._buildShape();
K
kener 已提交
1064 1065
            }
        }
K
kener 已提交
1066 1067 1068 1069
    };
    
    zrUtil.inherits(DataZoom, Base);
    
1070 1071
    require('../component').define('dataZoom', DataZoom);
    
K
kener 已提交
1072 1073
    return DataZoom;
});