dataZoom.js 41.5 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, myChart) {
        Base.call(this, ecTheme, messageCenter, zr, option, myChart);
K
kener 已提交
28

K
kener 已提交
29 30
        var self = this;
        self._ondrift = function (dx, dy) {
K
kener 已提交
31
            return self.__ondrift(this, dx, dy);
K
kener 已提交
32 33
        };
        self._ondragend = function () {
K
kener 已提交
34
            return self.__ondragend();
K
kener 已提交
35
        };
K
kener 已提交
36

K
kener 已提交
37 38 39 40 41 42 43 44 45
        this._fillerSize = 28;       // 控件大小,水平布局为高,纵向布局为宽
        this._handleSize = 8;        // 手柄大小
        // this._fillerShae;            // 填充
        // this._startShape;            // 起始手柄
        // this._endShape;              // 结束手柄
        // this._startFrameShape;       // 起始特效边框
        // this._endFrameShape;         // 结束特效边框
        // this._syncTicket;
        this._isSilence = false;
K
kener 已提交
46
        this._zoom = {};
K
kener 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
        // this._originalData;
        
        this.option.dataZoom = this.reformOption(this.option.dataZoom);
        this.zoomOption = this.option.dataZoom;

        // 位置参数,通过计算所得x, y, width, height
        this._location = this._getLocation();
        // 缩放参数
        this._zoom =  this._getZoom();
        this._backupData();
        
        if (this.option.dataZoom.show) {
            this._buildShape();
        }
        this._syncData();
K
kener 已提交
62 63 64 65 66 67 68 69 70
    }
    
    DataZoom.prototype = {
        type : ecConfig.COMPONENT_TYPE_DATAZOOM,
        _buildShape : function () {
            this._buildBackground();
            this._buildFiller();
            this._buildHandle();
            this._buildFrame();
K
kener 已提交
71

K
kener 已提交
72 73
            for (var i = 0, l = this.shapeList.length; i < l; i++) {
                this.zr.addShape(this.shapeList[i]);
K
kener 已提交
74
            }
K
kener 已提交
75 76
            this._syncFrameShape();
        },
K
kener 已提交
77 78 79 80

        /**
         * 根据选项计算实体的位置坐标
         */
K
kener 已提交
81
        _getLocation : function () {
K
kener 已提交
82 83 84 85
            var x;
            var y;
            var width;
            var height;
K
kener 已提交
86
            var grid = this.component.grid;
K
kener 已提交
87 88

            // 不指定则根据grid适配
K
kener 已提交
89
            if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
90
                // 水平布局
K
kener 已提交
91 92 93 94 95 96
                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 已提交
97 98 99
            }
            else {
                // 垂直布局
K
kener 已提交
100 101 102 103 104 105
                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 已提交
106 107 108 109 110 111 112 113
            }

            return {
                x : x,
                y : y,
                width : width,
                height : height
            };
K
kener 已提交
114
        },
K
kener 已提交
115 116 117 118 119

        /**
         * 计算缩放参数
         * 修正单坐标轴只传对象为数组。
         */
K
kener 已提交
120 121 122
        _getZoom : function () {
            var series = this.option.series;
            var xAxis = this.option.xAxis;
K
kener 已提交
123 124
            if (xAxis && !(xAxis instanceof Array)) {
                xAxis = [xAxis];
K
kener 已提交
125
                this.option.xAxis = xAxis;
K
kener 已提交
126
            }
K
kener 已提交
127
            var yAxis = this.option.yAxis;
K
kener 已提交
128 129
            if (yAxis && !(yAxis instanceof Array)) {
                yAxis = [yAxis];
K
kener 已提交
130
                this.option.yAxis = yAxis;
K
kener 已提交
131 132 133 134 135 136
            }

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

K
kener 已提交
137
            var zOptIdx = this.zoomOption.xAxisIndex;
K
kener 已提交
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
            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 已提交
161
            zOptIdx = this.zoomOption.yAxisIndex;
K
kener 已提交
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
            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 已提交
184 185 186 187 188 189 190
                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 已提交
191 192 193 194 195 196 197 198 199 200 201 202
                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 已提交
203 204
                // 不指定接管坐标轴,则散点图被纳入接管范围
                if (series[i].type == ecConfig.CHART_TYPE_SCATTER
K
kener 已提交
205 206
                    && typeof this.zoomOption.xAxisIndex == 'undefined'
                    && typeof this.zoomOption.yAxisIndex == 'undefined'
K
kener 已提交
207 208 209
                ) {
                    zoomSeriesIndex.push(i);
                }
K
kener 已提交
210 211
            }

K
kener 已提交
212 213 214 215 216 217 218
            var start = typeof this._zoom.start != 'undefined'
                        ? this._zoom.start
                        : (typeof this.zoomOption.start != 'undefined' ? this.zoomOption.start : 0);
            var end = typeof this._zoom.end != 'undefined'
                      ? this._zoom.end
                      : (typeof this.zoomOption.end != 'undefined' ? this.zoomOption.end : 100);
            /*
K
kener 已提交
219 220 221 222 223 224 225 226
            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 已提交
227
            */
K
kener 已提交
228 229 230 231 232 233 234 235
            if (start > end) {
                // 大小颠倒自动翻转
                start = start + end;
                end = start - end;
                start = start - end;
            }
            var size = Math.round(
                           (end - start) / 100
K
kener 已提交
236 237
                           * (this.zoomOption.orient == 'horizontal'
                             ? this._location.width : this._location.height)
K
kener 已提交
238 239 240 241
                       );
            return {
                start : start,
                end : end,
K
kener 已提交
242 243
                start2 : 0,
                end2 : 100,
K
kener 已提交
244 245 246 247 248
                size : size,
                xAxisIndex : xAxisIndex,
                yAxisIndex : yAxisIndex,
                seriesIndex : zoomSeriesIndex
            };
K
kener 已提交
249
        },
K
kener 已提交
250

K
kener 已提交
251 252
        _backupData : function () {
            this._originalData = {
K
kener 已提交
253 254 255 256
                xAxis : {},
                yAxis : {},
                series : {}
            };
K
kener 已提交
257 258
            var xAxis = this.option.xAxis;
            var xAxisIndex = this._zoom.xAxisIndex;
K
kener 已提交
259
            for (var i = 0, l = xAxisIndex.length; i < l; i++) {
K
kener 已提交
260
                this._originalData.xAxis[xAxisIndex[i]] = xAxis[xAxisIndex[i]].data;
K
kener 已提交
261 262
            }

K
kener 已提交
263 264
            var yAxis = this.option.yAxis;
            var yAxisIndex = this._zoom.yAxisIndex;
K
kener 已提交
265
            for (var i = 0, l = yAxisIndex.length; i < l; i++) {
K
kener 已提交
266
                this._originalData.yAxis[yAxisIndex[i]] = yAxis[yAxisIndex[i]].data;
K
kener 已提交
267 268
            }

K
kener 已提交
269 270
            var series = this.option.series;
            var seriesIndex = this._zoom.seriesIndex;
K
kener 已提交
271
            var serie;
K
kener 已提交
272
            for (var i = 0, l = seriesIndex.length; i < l; i++) {
K
kener 已提交
273
                serie = series[seriesIndex[i]];
K
kener 已提交
274
                this._originalData.series[seriesIndex[i]] = serie.data;
K
kener 已提交
275
                if (serie.type == ecConfig.CHART_TYPE_SCATTER) {
K
kener 已提交
276
                    this._calculScatterMap(seriesIndex[i]);
K
kener 已提交
277
                }
K
kener 已提交
278
            }
K
kener 已提交
279
        },
K
kener 已提交
280
        
K
kener 已提交
281 282 283
        _calculScatterMap : function (seriesIndex) {
            this._zoom.scatterMap = this._zoom.scatterMap || {};
            this._zoom.scatterMap[seriesIndex] = this._zoom.scatterMap[seriesIndex] || {};
K
kener 已提交
284 285 286
            var componentLibrary = require('../component');
            // x轴极值
            var Axis = componentLibrary.get('axis');
K
kener 已提交
287
            var axisOption = zrUtil.clone(this.option.xAxis);
K
kener 已提交
288 289 290 291 292 293 294
            if (axisOption instanceof Array) {
                axisOption[0].type = 'value';
                axisOption[1] && (axisOption[1].type = 'value');
            }
            else {
                axisOption.type = 'value';
            }
K
kener 已提交
295
            var vAxis = new Axis(
K
kener 已提交
296
                this.ecTheme,
K
kener 已提交
297
                null,   // messageCenter
K
kener 已提交
298
                false,  // this.zr
K
kener 已提交
299
                {
K
kener 已提交
300
                    xAxis: axisOption,
K
kener 已提交
301
                    series : this.option.series
K
kener 已提交
302
                }, 
K
kener 已提交
303
                this,
K
kener 已提交
304 305
                'xAxis'
            );
K
kener 已提交
306
            var axisIndex = this.option.series[seriesIndex].xAxisIndex || 0;
K
kener 已提交
307
            this._zoom.scatterMap[seriesIndex].x = vAxis.getAxis(axisIndex).getExtremum();
K
kener 已提交
308
            vAxis.dispose();
K
kener 已提交
309 310
            
            // y轴极值
K
kener 已提交
311
            axisOption = zrUtil.clone(this.option.yAxis);
K
kener 已提交
312 313 314 315 316 317 318
            if (axisOption instanceof Array) {
                axisOption[0].type = 'value';
                axisOption[1] && (axisOption[1].type = 'value');
            }
            else {
                axisOption.type = 'value';
            }
K
kener 已提交
319
            vAxis = new Axis(
K
kener 已提交
320
                this.ecTheme,
K
kener 已提交
321
                null,   // messageCenter
K
kener 已提交
322
                false,  // this.zr
K
kener 已提交
323
                {
K
kener 已提交
324
                    yAxis: axisOption,
K
kener 已提交
325
                    series : this.option.series
K
kener 已提交
326
                }, 
K
kener 已提交
327
                this,
K
kener 已提交
328 329
                'yAxis'
            );
K
kener 已提交
330
            axisIndex = this.option.series[seriesIndex].yAxisIndex || 0;
K
kener 已提交
331
            this._zoom.scatterMap[seriesIndex].y = vAxis.getAxis(axisIndex).getExtremum();
K
kener 已提交
332
            vAxis.dispose();
K
kener 已提交
333 334
            // console.log(this._zoom.scatterMap);
        },
K
kener 已提交
335

K
kener 已提交
336
        _buildBackground : function () {
K
kener 已提交
337 338 339
            var width = this._location.width;
            var height = this._location.height;
            
K
kener 已提交
340
            // 背景
K
kener 已提交
341 342
            this.shapeList.push(new RectangleShape({
                zlevel : this._zlevelBase,
K
kener 已提交
343 344
                hoverable :false,
                style : {
K
kener 已提交
345 346
                    x : this._location.x,
                    y : this._location.y,
K
kener 已提交
347 348
                    width : width,
                    height : height,
K
kener 已提交
349
                    color : this.zoomOption.backgroundColor
K
kener 已提交
350
                }
K
kener 已提交
351
            }));
K
kener 已提交
352 353
            
            // 数据阴影
K
kener 已提交
354
            var maxLength = 0;
K
kener 已提交
355 356
            var xAxis = this._originalData.xAxis;
            var xAxisIndex = this._zoom.xAxisIndex;
K
kener 已提交
357 358
            for (var i = 0, l = xAxisIndex.length; i < l; i++) {
                maxLength = Math.max(
K
kener 已提交
359
                    maxLength, xAxis[xAxisIndex[i]].length
K
kener 已提交
360 361
                );
            }
K
kener 已提交
362 363
            var yAxis = this._originalData.yAxis;
            var yAxisIndex = this._zoom.yAxisIndex;
K
kener 已提交
364 365
            for (var i = 0, l = yAxisIndex.length; i < l; i++) {
                maxLength = Math.max(
K
kener 已提交
366
                    maxLength, yAxis[yAxisIndex[i]].length
K
kener 已提交
367 368 369
                );
            }

K
kener 已提交
370 371
            var seriesIndex = this._zoom.seriesIndex[0];
            var data = this._originalData.series[seriesIndex];
K
kener 已提交
372 373 374 375 376
            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'
K
kener 已提交
377
                        ? (typeof data[i].value != 'undefined' ? data[i].value : data[i])
K
kener 已提交
378
                        : 0;
K
kener 已提交
379
                if (this.option.series[seriesIndex].type == ecConfig.CHART_TYPE_K) {
K
kener 已提交
380 381
                    value = value[1];   // 收盘价
                }
K
kener 已提交
382 383 384 385 386 387
                if (isNaN(value)) {
                    value = 0;
                }
                maxValue = Math.max(maxValue, value);
                minValue = Math.min(minValue, value);
            }
K
kener 已提交
388
            var valueRange = maxValue - minValue;
K
kener 已提交
389 390

            var pointList = [];
K
kener 已提交
391 392 393 394 395 396 397 398 399 400 401
            var x = width / (maxLength - (maxLength > 1 ? 1 : 0));
            var y = height / (maxLength - (maxLength > 1 ? 1 : 0));
            var step = 1;
            if (this.zoomOption.orient == 'horizontal' && x < 1) {
                step = Math.floor(maxLength * 3 / width);
            }
            else if (this.zoomOption.orient == 'vertical' && y < 1){
                step = Math.floor(maxLength * 3 / height);
            }
            
            for (var i = 0, l = maxLength; i < l; i += step) {
K
kener 已提交
402 403 404 405
                value = typeof data[i] != 'undefined'
                        ? (typeof data[i].value != 'undefined'
                          ? data[i].value : data[i])
                        : 0;
K
kener 已提交
406
                if (this.option.series[seriesIndex].type == ecConfig.CHART_TYPE_K) {
K
kener 已提交
407 408
                    value = value[1];   // 收盘价
                }
K
kener 已提交
409 410 411
                if (isNaN(value)) {
                    value = 0;
                }
K
kener 已提交
412
                if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
413
                    pointList.push([
K
kener 已提交
414
                        this._location.x + x * i,
K
kener 已提交
415 416
                        this._location.y + height - 5 - Math.round(
                            (value - minValue) / valueRange * (height - 10)
K
kener 已提交
417 418 419 420 421
                        )
                    ]);
                }
                else {
                    pointList.push([
K
kener 已提交
422
                        this._location.x + 5 + Math.round(
K
kener 已提交
423
                            (value - minValue) / valueRange * (width - 10)
K
kener 已提交
424
                        ),
K
kener 已提交
425
                        this._location.y + y * i
K
kener 已提交
426 427 428
                    ]);
                }
            }
K
kener 已提交
429
            if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
430
                 pointList.push([
K
kener 已提交
431 432
                    this._location.x + width,
                    this._location.y + height
K
kener 已提交
433 434
                ]);
                pointList.push([
K
kener 已提交
435
                    this._location.x, this._location.y + height
K
kener 已提交
436 437 438 439
                ]);
            }
            else {
                pointList.push([
K
kener 已提交
440
                    this._location.x, this._location.y + height
K
kener 已提交
441 442
                ]);
                pointList.push([
K
kener 已提交
443
                    this._location.x, this._location.y
K
kener 已提交
444 445 446
                ]);
            }

K
kener 已提交
447 448
            this.shapeList.push(new PolygonShape({
                zlevel : this._zlevelBase,
K
kener 已提交
449 450
                style : {
                    pointList : pointList,
K
kener 已提交
451
                    color : this.zoomOption.dataBackgroundColor
K
kener 已提交
452 453
                },
                hoverable : false
K
kener 已提交
454
            }));
K
kener 已提交
455
        },
K
kener 已提交
456 457 458 459

        /**
         * 构建填充物
         */
K
kener 已提交
460 461 462
        _buildFiller : function () {
            this._fillerShae = {
                zlevel : this._zlevelBase,
K
kener 已提交
463
                draggable : true,
K
kener 已提交
464 465
                ondrift : this._ondrift,
                ondragend : this._ondragend,
K
kener 已提交
466 467 468
                _type : 'filler'
            };

K
kener 已提交
469
            if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
470
                // 横向
K
kener 已提交
471 472 473 474 475 476 477 478 479
                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 已提交
480
                    // lineWidth: 2,
K
kener 已提交
481 482 483 484 485
                    text : ':::',
                    textPosition : 'inside'
                };
            }
            else {
K
kener 已提交
486
                // 纵向
K
kener 已提交
487 488 489 490 491 492 493 494 495
                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 已提交
496 497
                    // lineWidth: 2,
                    text : '::',
K
kener 已提交
498 499 500
                    textPosition : 'inside'
                };
            }
K
kener 已提交
501
            
K
kener 已提交
502
            this._fillerShae.highlightStyle = {
K
kener 已提交
503 504 505 506
                brushType: 'fill',
                color : 'rgba(0,0,0,0)'
                /*
                color : require('zrender/tool/color').alpha(
K
kener 已提交
507
                            this._fillerShae.style.color, 0
K
kener 已提交
508 509 510
                        )
                */
            };
K
kener 已提交
511 512 513
            this._fillerShae = new RectangleShape(this._fillerShae);
            this.shapeList.push(this._fillerShae);
        },
K
kener 已提交
514 515 516 517

        /**
         * 构建拖拽手柄
         */
K
kener 已提交
518 519 520
        _buildHandle : function () {
            this._startShape = {
                zlevel : this._zlevelBase,
K
kener 已提交
521 522 523
                draggable : true,
                style : {
                    iconType: 'rectangle',
K
kener 已提交
524 525 526 527 528
                    x : this._location.x,
                    y : this._location.y,
                    width : this._handleSize,
                    height : this._handleSize,
                    color : this.zoomOption.handleColor,
K
kener 已提交
529
                    text : '=',
K
kener 已提交
530
                    textPosition : 'inside'
K
kener 已提交
531 532 533 534
                },
                highlightStyle : {
                    brushType: 'fill'
                },
K
kener 已提交
535 536
                ondrift : this._ondrift,
                ondragend : this._ondragend
K
kener 已提交
537 538
            };
            
K
kener 已提交
539 540 541
            if (this.zoomOption.orient == 'horizontal') {
                this._startShape.style.height = this._location.height;
                this._endShape = zrUtil.clone(this._startShape);
K
kener 已提交
542
                
K
kener 已提交
543 544 545
                this._startShape.style.x = this._fillerShae.style.x - this._handleSize,
                this._endShape.style.x = this._fillerShae.style.x  
                                    + this._fillerShae.style.width;
K
kener 已提交
546 547
            }
            else {
K
kener 已提交
548 549
                this._startShape.style.width = this._location.width;
                this._endShape = zrUtil.clone(this._startShape);
K
kener 已提交
550
                
K
kener 已提交
551 552 553 554 555 556 557 558 559
                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 已提交
560

K
kener 已提交
561 562 563
        /**
         * 构建特效边框
         */
K
kener 已提交
564
        _buildFrame : function () {
K
kener 已提交
565
            // 特效框线,亚像素优化
K
kener 已提交
566 567 568 569
            var x = this.subPixelOptimize(this._location.x, 1);
            var y = this.subPixelOptimize(this._location.y, 1);
            this._startFrameShape = {
                zlevel : this._zlevelBase,
K
kener 已提交
570 571 572 573
                hoverable :false,
                style : {
                    x : x,
                    y : y,
K
kener 已提交
574 575
                    width : this._location.width - (x > this._location.x ? 1 : 0),
                    height : this._location.height - (y > this._location.y ? 1 : 0),
K
kener 已提交
576 577
                    lineWidth: 1,
                    brushType: 'stroke',
K
kener 已提交
578
                    strokeColor : this.zoomOption.handleColor
K
kener 已提交
579 580
                }
            };
K
kener 已提交
581
            this._endFrameShape = zrUtil.clone(this._startFrameShape);
K
kener 已提交
582
            
K
kener 已提交
583 584 585 586
            this._startFrameShape = new RectangleShape(this._startFrameShape);
            this._endFrameShape = new RectangleShape(this._endFrameShape);
            this.shapeList.push(this._startFrameShape);
            this.shapeList.push();
K
kener 已提交
587
            return;
K
kener 已提交
588
        },
K
kener 已提交
589
        
K
kener 已提交
590 591 592 593 594
        _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 已提交
595
                
K
kener 已提交
596 597 598
                this._zoom.start = Math.floor(
                    (this._startShape.style.x - this._location.x)
                    / this._location.width * 100
K
kener 已提交
599
                );
K
kener 已提交
600 601 602
                this._zoom.end = Math.ceil(
                    (this._endShape.style.x + this._handleSize - this._location.x)
                    / this._location.width * 100
K
kener 已提交
603 604 605
                );
            }
            else {
K
kener 已提交
606 607 608 609 610 611
                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 已提交
612
                );
K
kener 已提交
613 614 615
                this._zoom.end = Math.ceil(
                    (this._endShape.style.y + this._handleSize - this._location.y)
                    / this._location.height * 100
K
kener 已提交
616 617 618
                );
            }

K
kener 已提交
619 620
            this.zr.modShape(this._startShape.id);
            this.zr.modShape(this._endShape.id);
K
kener 已提交
621 622
            
            // 同步边框
K
kener 已提交
623
            this._syncFrameShape();
K
kener 已提交
624
            
K
kener 已提交
625 626
            this.zr.refresh();
        },
K
kener 已提交
627

K
kener 已提交
628
        _syncFillerShape : function () {
K
kener 已提交
629 630
            var a;
            var b;
K
kener 已提交
631 632 633 634 635 636 637 638
            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 已提交
639
                );
K
kener 已提交
640 641 642
                this._zoom.end = Math.ceil(
                    (Math.max(a, b) + this._handleSize - this._location.x)
                    / this._location.width * 100
K
kener 已提交
643 644 645
                );
            }
            else {
K
kener 已提交
646 647 648 649 650 651 652
                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 已提交
653
                );
K
kener 已提交
654 655 656
                this._zoom.end = Math.ceil(
                    (Math.max(a, b) + this._handleSize - this._location.y)
                    / this._location.height * 100
K
kener 已提交
657 658 659
                );
            }

K
kener 已提交
660
            this.zr.modShape(this._fillerShae.id);
K
kener 已提交
661 662
            
            // 同步边框
K
kener 已提交
663
            this._syncFrameShape();
K
kener 已提交
664
            
K
kener 已提交
665 666
            this.zr.refresh();
        },
667
        
K
kener 已提交
668 669 670 671 672 673 674 675
        _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 已提交
676 677
            }
            else {
K
kener 已提交
678 679 680 681 682 683
                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 已提交
684 685
            }
                    
K
kener 已提交
686 687
            this.zr.modShape(this._startFrameShape.id);
            this.zr.modShape(this._endFrameShape.id);
K
kener 已提交
688
        },
K
kener 已提交
689
        
K
kener 已提交
690 691
        _syncShape : function () {
            if (!this.zoomOption.show) {
K
kener 已提交
692 693 694
                // 没有伸缩控件
                return;
            }
K
kener 已提交
695 696 697 698 699 700
            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;
701
                    
K
kener 已提交
702 703 704 705
                this._fillerShae.style.x = this._startShape.style.x + this._handleSize;
                this._fillerShae.style.width = this._endShape.style.x 
                                          - this._startShape.style.x
                                          - this._handleSize;
706 707
            }
            else {
K
kener 已提交
708 709 710 711 712
                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;
713
                    
K
kener 已提交
714 715 716 717
                this._fillerShae.style.y = this._startShape.style.y + this._handleSize;
                this._fillerShae.style.height = this._endShape.style.y 
                                          - this._startShape.style.y
                                          - this._handleSize;
718 719
            }
            
K
kener 已提交
720 721 722
            this.zr.modShape(this._startShape.id);
            this.zr.modShape(this._endShape.id);
            this.zr.modShape(this._fillerShae.id);
K
kener 已提交
723
            // 同步边框
K
kener 已提交
724 725 726 727 728
            this._syncFrameShape();
            this.zr.refresh();
        },
        
         _syncData : function (dispatchNow) {
K
kener 已提交
729 730 731 732 733
            var target;
            var start;
            var end;
            var length;
            var data;
K
kener 已提交
734
            
K
kener 已提交
735 736 737 738 739 740 741 742 743 744 745 746 747
            for (var key in this._originalData) {
                target = this._originalData[key];
                for (var idx in target) {
                    data = target[idx];
                    length = data.length;
                    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);
                    }
                    else {
                        // 散点图特殊处理
                        this.option[key][idx].data = this._synScatterData(idx, data);
K
kener 已提交
748
                    }
K
kener 已提交
749 750 751
                }
            }

K
kener 已提交
752 753
            if (!this._isSilence && (this.zoomOption.realtime || dispatchNow)) {
                this.messageCenter.dispatch(
K
kener 已提交
754 755
                    ecConfig.EVENT.DATA_ZOOM,
                    null,
K
kener 已提交
756
                    {zoom: this._zoom}
K
kener 已提交
757
                );
K
kener 已提交
758 759
            }

K
kener 已提交
760 761
            //this.zoomOption.start = this._zoom.start;
            //this.zoomOption.end = this._zoom.end;
K
kener 已提交
762
        },
K
kener 已提交
763
        
K
kener 已提交
764
        _synScatterData : function (seriesIndex, data) {
K
kener 已提交
765 766 767 768 769 770 771
            if (this._zoom.start == 0 
                && this._zoom.end == 100
                && this._zoom.start2 == 0 
                && this._zoom.end2 == 100
            ) {
                return data;
            }
K
kener 已提交
772
            var newData = [];
K
kener 已提交
773
            var scale = this._zoom.scatterMap[seriesIndex];
K
kener 已提交
774 775 776 777 778 779
            var total;
            var xStart;
            var xEnd;
            var yStart;
            var yEnd;
            
K
kener 已提交
780
            if (this.zoomOption.orient == 'horizontal') {
K
kener 已提交
781
                total = scale.x.max - scale.x.min;
K
kener 已提交
782 783
                xStart = this._zoom.start / 100 * total + scale.x.min;
                xEnd = this._zoom.end / 100 * total + scale.x.min;
K
kener 已提交
784 785
                
                total = scale.y.max - scale.y.min;
K
kener 已提交
786 787
                yStart = this._zoom.start2 / 100 * total + scale.y.min;
                yEnd = this._zoom.end2 / 100 * total + scale.y.min;
K
kener 已提交
788 789 790
            }
            else {
                total = scale.x.max - scale.x.min;
K
kener 已提交
791 792
                xStart = this._zoom.start2 / 100 * total + scale.x.min;
                xEnd = this._zoom.end2 / 100 * total + scale.x.min;
K
kener 已提交
793 794
                
                total = scale.y.max - scale.y.min;
K
kener 已提交
795 796
                yStart = this._zoom.start / 100 * total + scale.y.min;
                yEnd = this._zoom.end / 100 * total + scale.y.min;
K
kener 已提交
797 798 799
            }
            
            // console.log(xStart,xEnd,yStart,yEnd);
K
kener 已提交
800
            var value;
K
kener 已提交
801
            for (var i = 0, l = data.length; i < l; i++) {
K
kener 已提交
802 803 804 805 806
                value = data[i].value || data[i];
                if (value[0] >= xStart 
                    && value[0] <= xEnd
                    && value[1] >= yStart
                    && value[1] <= yEnd
K
kener 已提交
807 808 809 810 811 812
                ) {
                    newData.push(data[i]);
                }
            }
            
            return newData;
K
kener 已提交
813
        },
K
kener 已提交
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
        /**
         * 拖拽范围控制
         */
        __ondrift : function (shape, dx, dy) {
            if (this.zoomOption.zoomLock) {
                // zoomLock时把handle转成filler的拖拽
                shape = this._fillerShae;
            }
            
            var detailSize = shape._type == 'filler' ? this._handleSize : 0;
            if (this.zoomOption.orient == 'horizontal') {
                if (shape.style.x + dx - detailSize <= this._location.x) {
                    shape.style.x = this._location.x + detailSize;
                }
                else if (shape.style.x + dx + shape.style.width + detailSize
                         >= this._location.x + this._location.width
                ) {
                    shape.style.x = this._location.x + this._location.width
                                - shape.style.width - detailSize;
                }
                else {
                    shape.style.x += dx;
                }
            }
            else {
                if (shape.style.y + dy - detailSize <= this._location.y) {
                    shape.style.y = this._location.y + detailSize;
                }
                else if (shape.style.y + dy + shape.style.height + detailSize
                         >= this._location.y + this._location.height
                ) {
                    shape.style.y = this._location.y + this._location.height
                                - shape.style.height - detailSize;
                }
                else {
                    shape.style.y += dy;
                }
            }
K
kener 已提交
852

K
kener 已提交
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
            if (shape._type == 'filler') {
                this._syncHandleShape();
            }
            else {
                this._syncFillerShape();
            }

            if (this.zoomOption.realtime) {
                this._syncData();
            }

            return true;
        },
        
        __ondragend : function () {
            this.isDragend = true;
        },
        
K
kener 已提交
871 872 873
        /**
         * 数据项被拖拽出去
         */
K
kener 已提交
874 875
        ondragend : function (param, status) {
            if (!this.isDragend || !param.target) {
K
kener 已提交
876 877 878 879
                // 没有在当前实例上发生拖拽行为则直接返回
                return;
            }

K
kener 已提交
880
            !this.zoomOption.realtime && this._syncData();
K
kener 已提交
881 882 883 884

            // 别status = {}赋值啊!!
            status.dragOut = true;
            status.dragIn = true;
K
kener 已提交
885 886
            if (!this._isSilence && !this.zoomOption.realtime) {
                this.messageCenter.dispatch(
K
kener 已提交
887 888
                    ecConfig.EVENT.DATA_ZOOM,
                    null,
K
kener 已提交
889
                    {zoom: this._zoom}
K
kener 已提交
890
                );
K
kener 已提交
891 892 893
            }
            status.needRefresh = false; // 会有消息触发fresh,不用再刷一遍
            // 处理完拖拽事件后复位
K
kener 已提交
894
            this.isDragend = false;
K
kener 已提交
895 896

            return;
K
kener 已提交
897
        },
K
kener 已提交
898

K
kener 已提交
899
        ondataZoom : function (param, status) {
K
kener 已提交
900 901
            status.needRefresh = true;
            return;
K
kener 已提交
902
        },
903
        
K
kener 已提交
904
        absoluteZoom : function (param) {
K
kener 已提交
905 906 907 908 909 910 911 912
            //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;
K
kener 已提交
913 914
            this._syncShape();
            this._syncData(true);
K
kener 已提交
915
            return;
K
kener 已提交
916
        },
K
kener 已提交
917
        
K
kener 已提交
918
        rectZoom : function (param) {
919 920
            if (!param) {
                // 重置拖拽
K
kener 已提交
921 922
                //this.zoomOption.start = 
                //this.zoomOption.start2 = 
K
kener 已提交
923 924
                this._zoom.start = 
                this._zoom.start2 = 0;
K
kener 已提交
925
                    
K
kener 已提交
926 927
                //this.zoomOption.end =
                //this.zoomOption.end2 = 
K
kener 已提交
928 929
                this._zoom.end = 
                this._zoom.end2 = 100;
K
kener 已提交
930
                
K
kener 已提交
931 932 933
                this._syncShape();
                this._syncData(true);
                return this._zoom;
934
            }
K
kener 已提交
935
            var gridArea = this.component.grid.getArea();
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950
            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 已提交
951
            // console.log(rect,this._zoom);
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
            
            // 剔除无效缩放
            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 已提交
971 972
            var total;
            var sdx = (rect.x - gridArea.x) / gridArea.width;
K
kener 已提交
973 974
            var edx = 1 - (rect.x + rect.width - gridArea.x) / gridArea.width;
            var sdy = 1 - (rect.y + rect.height - gridArea.y) / gridArea.height;
K
kener 已提交
975
            var edy = (rect.y - gridArea.y) / gridArea.height;
K
kener 已提交
976 977 978 979 980
            //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 已提交
981
                
K
kener 已提交
982 983 984
                total = this._zoom.end2 - this._zoom.start2;
                this._zoom.start2 += total * sdy;
                this._zoom.end2 -= total * edy;
K
kener 已提交
985 986
            }
            else {
K
kener 已提交
987 988 989
                total = this._zoom.end - this._zoom.start;
                this._zoom.start += total * sdy;
                this._zoom.end -= total * edy;
K
kener 已提交
990
                
K
kener 已提交
991 992 993 994 995
                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)
K
kener 已提交
996 997 998 999
            //this.zoomOption.start = this._zoom.start;
            //this.zoomOption.end = this._zoom.end;
            //this.zoomOption.start2 = this._zoom.start2;
            //this.zoomOption.end2 = this._zoom.end2;
K
kener 已提交
1000 1001 1002 1003 1004
            //console.log(rect,gridArea,this._zoom,total)
            this._syncShape();
            this._syncData(true);
            return this._zoom;
        },
K
kener 已提交
1005
        
K
kener 已提交
1006
        syncBackupData : function (curOption) {
K
kener 已提交
1007
            var start;
K
kener 已提交
1008
            var target = this._originalData['series'];
K
kener 已提交
1009 1010 1011 1012 1013 1014
            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 已提交
1015
                    start = Math.floor(this._zoom.start / 100 * target[i].length);
K
kener 已提交
1016 1017 1018 1019 1020 1021
                }
                else {
                    // 非dataZoom接管
                    start = 0;
                }
                for (var j = 0, k = curData.length; j < k; j++) {
K
kener 已提交
1022
                    //optionBackup.series[i].data[j + start] = curData[j];
K
kener 已提交
1023 1024
                    if (target[i]) {
                        // 同步内部备份
K
kener 已提交
1025
                        target[i][j + start] = curData[j];
K
kener 已提交
1026 1027 1028
                    }
                }
            }
K
kener 已提交
1029
        },
1030
        
K
kener 已提交
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
        syncOption : function(magicOption) {
            this.silence(true);
            this.option = magicOption;
            
            this.clear();
            this._backupData();
            // 位置参数,通过计算所得x, y, width, height
            this._location = this._getLocation();
            // 缩放参数
            this._zoom =  this._getZoom();
K
kener 已提交
1041
            if (this.option.dataZoom && this.option.dataZoom.show) {
K
kener 已提交
1042 1043 1044 1045 1046 1047 1048
                this._buildShape();
            }
            this._syncData();
            
            this.silence(false);
        },
        
K
kener 已提交
1049 1050 1051
        silence : function (s) {
            this._isSilence = s;
        },
1052
        
K
kener 已提交
1053
        getRealDataIndex : function (sIdx, dIdx) {
K
kener 已提交
1054
            if (!this._originalData || (this._zoom.start == 0 && this._zoom.end == 100)) {
K
kener 已提交
1055 1056
                return dIdx;
            }
K
kener 已提交
1057
            var sreies = this._originalData.series;
1058
            if (sreies[sIdx]) {
K
kener 已提交
1059
                return Math.floor(this._zoom.start / 100 * sreies[sIdx].length) + dIdx;
1060 1061
            }
            return -1;
K
kener 已提交
1062
        },
K
kener 已提交
1063

K
kener 已提交
1064 1065 1066
        /**
         * 避免dataZoom带来两次refresh,不设refresh接口,resize重复一下buildshape逻辑 
         */
K
kener 已提交
1067 1068
        resize : function () {
            this.clear();
K
kener 已提交
1069
            
K
kener 已提交
1070 1071 1072 1073
            // 位置参数,通过计算所得x, y, width, height
            this._location = this._getLocation();
            // 缩放参数
            this._zoom =  this._getZoom();
K
kener 已提交
1074
            
K
kener 已提交
1075 1076
            if (this.option.dataZoom.show) {
                this._buildShape();
K
kener 已提交
1077 1078
            }
        }
K
kener 已提交
1079 1080 1081 1082
    };
    
    zrUtil.inherits(DataZoom, Base);
    
1083 1084
    require('../component').define('dataZoom', DataZoom);
    
K
kener 已提交
1085 1086
    return DataZoom;
});