bar.js 41.2 KB
Newer Older
K
kener 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/**
 * echarts图表类:柱形图
 *
 * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, linzhifeng@baidu.com)
 *
 */
define(function(require) {
    /**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} series 数据
     * @param {Object} component 组件
     */
K
kener 已提交
16
    function Bar(ecConfig, messageCenter, zr, option, component){
K
kener 已提交
17 18
        // 基类装饰
        var ComponentBase = require('../component/base');
K
kener 已提交
19
        ComponentBase.call(this, ecConfig, zr);
K
kener 已提交
20 21 22 23 24
        // 可计算特性装饰
        var CalculableBase = require('./calculableBase');
        CalculableBase.call(this, zr, option);

        var ecData = require('../util/ecData');
K
kener 已提交
25
        
K
kener 已提交
26
        var zrColor = require('zrender/tool/color');
K
kener 已提交
27 28 29 30 31 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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

        var self = this;
        self.type = ecConfig.CHART_TYPE_BAR;

        var series;                 // 共享数据源,不要修改跟自己无关的项

        var _zlevelBase = self.getZlevelBase();

        var _sIndex2colorMap = {};  // series默认颜色索引,seriesIndex索引到color

        function _buildShape() {
            self.selectedMap = {};

            // 水平垂直双向series索引 ,position索引到seriesIndex
            var _position2sIndexMap = {
                top : [],
                bottom : [],
                left : [],
                right : []
            };
            var xAxisIndex;
            var yAxisIndex;
            var xAxis;
            var yAxis;
            for (var i = 0, l = series.length; i < l; i++) {
                if (series[i].type == ecConfig.CHART_TYPE_BAR) {
                    series[i] = self.reformOption(series[i]);
                    xAxisIndex = series[i].xAxisIndex;
                    yAxisIndex = series[i].yAxisIndex;
                    xAxis = component.xAxis.getAxis(xAxisIndex);
                    yAxis = component.yAxis.getAxis(yAxisIndex);
                    if (xAxis.type == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
                    ) {
                        _position2sIndexMap[xAxis.getPosition()].push(i);
                    }
                    else if (yAxis.type == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
                    ) {
                        _position2sIndexMap[yAxis.getPosition()].push(i);
                    }
                }
            }
            // console.log(_position2sIndexMap)
            for (var position in _position2sIndexMap) {
                if (_position2sIndexMap[position].length > 0) {
                    _buildSinglePosition(
                        position, _position2sIndexMap[position]
                    );
                }
            }

            for (var i = 0, l = self.shapeList.length; i < l; i++) {
                self.shapeList[i].id = zr.newShapeId(self.type);
                zr.addShape(self.shapeList[i]);
            }
        }

        /**
         * 构建单个方向上的柱形图
         *
         * @param {number} seriesIndex 系列索引
         */
        function _buildSinglePosition(position, seriesArray) {
            var mapData = _mapData(seriesArray);
            var locationMap = mapData.locationMap;
            var maxDataLength = mapData.maxDataLength;

            if (maxDataLength === 0 || locationMap.length === 0) {
                return;
            }

            switch (position) {
                case 'bottom' :
                case 'top' :
K
kener 已提交
100
                    _buildHorizontal(maxDataLength, locationMap, seriesArray);
K
kener 已提交
101 102 103
                    break;
                case 'left' :
                case 'right' :
K
kener 已提交
104
                    _buildVertical(maxDataLength, locationMap, seriesArray);
K
kener 已提交
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
                    break;
            }
        }


        /**
         * 数据整形
         * 数组位置映射到系列索引
         */
        function _mapData(seriesArray) {
            var serie;                              // 临时映射变量
            var dataIndex = 0;                      // 堆叠数据所在位置映射
            var stackMap = {};                      // 堆叠数据位置映射,堆叠组在二维中的第几项
            var magicStackKey = '__kener__stack__'; // 堆叠命名,非堆叠数据安单一堆叠处理
            var stackKey;                           // 临时映射变量
            var serieName;                          // 临时映射变量
            var legend = component.legend;
            var locationMap = [];                   // 需要返回的东西:数组位置映射到系列索引
            var maxDataLength = 0;                  // 需要返回的东西:最大数据长度
K
kener 已提交
124
            var iconShape;
K
kener 已提交
125 126 127 128 129 130 131 132
            // 计算需要显示的个数和分配位置并记在下面这个结构里
            for (var i = 0, l = seriesArray.length; i < l; i++) {
                serie = series[seriesArray[i]];
                serieName = serie.name;
                if (legend){
                    self.selectedMap[serieName] = legend.isSelected(serieName);
                    _sIndex2colorMap[seriesArray[i]] =
                        legend.getColor(serieName);
K
kener 已提交
133 134 135 136 137 138 139 140 141
                    
                    iconShape = legend.getItemShape(serieName);
                    if (iconShape) {
                        // 回调legend,换一个更形象的icon
                        iconShape.style.strokeColor = 
                            serie.itemStyle.normal.borderColor;
                        iconShape.style.brushType = 'both';
                        legend.setItemShape(serieName, iconShape);
                    }
K
kener 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
                } else {
                    self.selectedMap[serieName] = true;
                    _sIndex2colorMap[seriesArray[i]] =
                        zr.getColor(seriesArray[i]);
                }

                if (self.selectedMap[serieName]) {
                    stackKey = serie.stack || (magicStackKey + seriesArray[i]);
                    if (typeof stackMap[stackKey] == 'undefined') {
                        stackMap[stackKey] = dataIndex;
                        locationMap[dataIndex] = [seriesArray[i]];
                        dataIndex++;
                    }
                    else {
                        // 已经分配了位置就推进去就行
                        locationMap[stackMap[stackKey]].push(seriesArray[i]);
                    }
                }
                // 兼职帮算一下最大长度
                maxDataLength = Math.max(maxDataLength, serie.data.length);
            }

            /* 调试输出
            var s = '';
            for (var i = 0, l = maxDataLength; i < l; i++) {
                s = '[';
                for (var j = 0, k = locationMap.length; j < k; j++) {
                    s +='['
                    for (var m = 0, n = locationMap[j].length - 1; m < n; m++) {
                        s += series[locationMap[j][m]].data[i] + ','
                    }
                    s += series[locationMap[j][locationMap[j].length - 1]]
                         .data[i];
                    s += ']'
                }
                s += ']';
                console.log(s);
            }
            console.log(locationMap)
            */

            return {
                locationMap : locationMap,
                maxDataLength : maxDataLength
            };
        }

        /**
         * 构建类目轴为水平方向的柱形图系列
         */
K
kener 已提交
192
        function _buildHorizontal(maxDataLength, locationMap, seriesArray) {
K
kener 已提交
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
            // 确定类目轴和数值轴,同一方向随便找一个即可
            var seriesIndex = locationMap[0][0];
            var serie = series[seriesIndex];
            var xAxisIndex = serie.xAxisIndex;
            var categoryAxis = component.xAxis.getAxis(xAxisIndex);
            var yAxisIndex; // 数值轴各异
            var valueAxis;  // 数值轴各异

            var size = _mapSize(categoryAxis, locationMap);
            var gap = size.gap;
            var barGap = size.barGap;
            var barWidthMap = size.barWidthMap;
            var barWidth = size.barWidth;                   // 自适应宽度
            var barMinHeightMap = size.barMinHeightMap;
            var barHeight;

K
kener 已提交
209
            var xMarkMap = {}; // 为标注记录一个横向偏移
K
kener 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
            var x;
            var y;
            var lastYP; // 正向堆叠处理
            var baseYP;
            var lastYN; // 负向堆叠处理
            var baseYN;
            var barShape;
            var data;
            var value;
            for (var i = 0, l = maxDataLength; i < l; i++) {
                if (typeof categoryAxis.getNameByIndex(i) == 'undefined') {
                    // 系列数据超出类目轴长度
                    break;
                }
                x = categoryAxis.getCoordByIndex(i) - gap / 2;
                for (var j = 0, k = locationMap.length; j < k; j++) {
                    // 堆叠数据用第一条valueAxis
                    yAxisIndex = series[locationMap[j][0]].yAxisIndex || 0;
                    valueAxis = component.yAxis.getAxis(yAxisIndex);
K
kener 已提交
229
                    baseYP = lastYP = baseYN = lastYN = valueAxis.getCoord(0);
K
kener 已提交
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
                    for (var m = 0, n = locationMap[j].length; m < n; m++) {
                        seriesIndex = locationMap[j][m];
                        serie = series[seriesIndex];
                        data = serie.data[i];
                        value = typeof data != 'undefined'
                                ? (typeof data.value != 'undefined'
                                  ? data.value
                                  : data)
                                : '-';
                        if (value == '-') {
                            // 空数据在做完后补充拖拽提示框
                            continue;
                        }
                        y = valueAxis.getCoord(value);
                        if (value > 0) {
                            // 正向堆叠
                            barHeight = baseYP - y;
                            // 非堆叠数据最小高度有效
                            if (n == 1
                                && barMinHeightMap[seriesIndex] > barHeight
                            ) {
                                barHeight = barMinHeightMap[seriesIndex];
                            }
                            lastYP -= barHeight;
                            y = lastYP;
                        }
                        else if (value < 0){
                            // 负向堆叠
                            barHeight = y - baseYN;
                            // 非堆叠数据最小高度有效
                            if (n == 1
                                && barMinHeightMap[seriesIndex] > barHeight
                            ) {
                                barHeight = barMinHeightMap[seriesIndex];
                            }
                            y = lastYN;
                            lastYN += barHeight;
                        }
                        else {
                            // 0值
                            barHeight = baseYP - y;
                            // 最小高度无效
                            lastYP -= barHeight;
                            y = lastYP;
                        }

                        barShape = _getBarItem(
                            seriesIndex, i,
                            categoryAxis.getNameByIndex(i),
                            x, y,
                            barWidthMap[seriesIndex] || barWidth,
K
kener 已提交
281 282
                            barHeight,
                            'vertical'
K
kener 已提交
283
                        );
K
kener 已提交
284 285 286 287
                        
                        xMarkMap[seriesIndex] = xMarkMap[seriesIndex] || {};
                        xMarkMap[seriesIndex][i] = 
                            x + (barWidthMap[seriesIndex] || barWidth) / 2;
K
kener 已提交
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310

                        self.shapeList.push(barShape);
                    }

                    // 补充空数据的拖拽提示框
                    for (var m = 0, n = locationMap[j].length; m < n; m++) {
                        seriesIndex = locationMap[j][m];
                        serie = series[seriesIndex];
                        data = serie.data[i];
                        value = typeof data != 'undefined'
                                ? (typeof data.value != 'undefined'
                                  ? data.value
                                  : data)
                                : '-';
                        if (value != '-') {
                            // 只关心空数据
                            continue;
                        }

                        if (self.deepQuery(
                                [data, serie, option], 'calculable'
                            )
                        ) {
K
kener 已提交
311
                            lastYP -= ecConfig.island.r;
K
kener 已提交
312 313 314 315 316
                            y = lastYP;

                            barShape = _getBarItem(
                                seriesIndex, i,
                                categoryAxis.getNameByIndex(i),
K
kener 已提交
317 318 319
                                x + 0.5, y + 0.5,
                                (barWidthMap[seriesIndex] || barWidth) - 1,
                                ecConfig.island.r - 1,
K
kener 已提交
320
                                'vertical'
K
kener 已提交
321 322 323
                            );
                            barShape.hoverable = false;
                            barShape.draggable = false;
K
kener 已提交
324
                            barShape.style.lineWidth = 1;
K
kener 已提交
325 326 327 328 329 330 331 332 333 334 335 336
                            barShape.style.brushType = 'stroke';
                            barShape.style.strokeColor =
                                    serie.calculableHolderColor
                                    || ecConfig.calculableHolderColor;

                            self.shapeList.push(barShape);
                        }
                    }

                    x += ((barWidthMap[seriesIndex] || barWidth) + barGap);
                }
            }
K
kener 已提交
337
            _buildMark(seriesArray, xMarkMap, true);
K
kener 已提交
338 339 340 341 342
        }

        /**
         * 构建类目轴为垂直方向的柱形图系列
         */
K
kener 已提交
343
        function _buildVertical(maxDataLength, locationMap, seriesArray) {
K
kener 已提交
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
            // 确定类目轴和数值轴,同一方向随便找一个即可
            var seriesIndex = locationMap[0][0];
            var serie = series[seriesIndex];
            var yAxisIndex = serie.yAxisIndex;
            var categoryAxis = component.yAxis.getAxis(yAxisIndex);
            var xAxisIndex; // 数值轴各异
            var valueAxis;  // 数值轴各异

            var size = _mapSize(categoryAxis, locationMap);
            var gap = size.gap;
            var barGap = size.barGap;
            var barWidthMap = size.barWidthMap;
            var barWidth = size.barWidth;                   // 自适应宽度
            var barMinHeightMap = size.barMinHeightMap;
            var barHeight;

K
kener 已提交
360
            var xMarkMap = {}; // 为标注记录一个横向偏移
K
kener 已提交
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
            var x;
            var y;
            var lastXP; // 正向堆叠处理
            var baseXP;
            var lastXN; // 负向堆叠处理
            var baseXN;
            var barShape;
            var data;
            var value;
            for (var i = 0, l = maxDataLength; i < l; i++) {
                if (typeof categoryAxis.getNameByIndex(i) == 'undefined') {
                    // 系列数据超出类目轴长度
                    break;
                }
                y = categoryAxis.getCoordByIndex(i) + gap / 2;
                for (var j = 0, k = locationMap.length; j < k; j++) {
                    // 堆叠数据用第一条valueAxis
                    xAxisIndex = series[locationMap[j][0]].xAxisIndex || 0;
                    valueAxis = component.xAxis.getAxis(xAxisIndex);
K
kener 已提交
380
                    baseXP = lastXP = baseXN = lastXN = valueAxis.getCoord(0);
K
kener 已提交
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
                    for (var m = 0, n = locationMap[j].length; m < n; m++) {
                        seriesIndex = locationMap[j][m];
                        serie = series[seriesIndex];
                        data = serie.data[i];
                        value = typeof data != 'undefined'
                                ? (typeof data.value != 'undefined'
                                  ? data.value
                                  : data)
                                : '-';
                        if (value == '-') {
                            // 空数据在做完后补充拖拽提示框
                            continue;
                        }
                        x = valueAxis.getCoord(value);
                        if (value > 0) {
                            // 正向堆叠
                            barHeight = x - baseXP;
                            // 非堆叠数据最小高度有效
                            if (n == 1
                                && barMinHeightMap[seriesIndex] > barHeight
                            ) {
                                barHeight = barMinHeightMap[seriesIndex];
                            }
                            x = lastXP;
                            lastXP += barHeight;
                        }
                        else if (value < 0){
                            // 负向堆叠
                            barHeight = baseXN - x;
                            // 非堆叠数据最小高度有效
                            if (n == 1
                                && barMinHeightMap[seriesIndex] > barHeight
                            ) {
                                barHeight = barMinHeightMap[seriesIndex];
                            }
                            lastXN -= barHeight;
                            x = lastXN;
                        }
                        else {
                            // 0值
                            barHeight = x - baseXP;
                            // 最小高度无效
                            x = lastXP;
                            lastXP += barHeight;
                        }

                        barShape = _getBarItem(
                            seriesIndex, i,
                            categoryAxis.getNameByIndex(i),
                            x, y - (barWidthMap[seriesIndex] || barWidth),
                            barHeight,
K
kener 已提交
432 433
                            barWidthMap[seriesIndex] || barWidth,
                            'horizontal'
K
kener 已提交
434
                        );
K
kener 已提交
435 436 437 438
                        
                        xMarkMap[seriesIndex] = xMarkMap[seriesIndex] || {};
                        xMarkMap[seriesIndex][i] = 
                            y - (barWidthMap[seriesIndex] || barWidth) / 2;
K
kener 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462

                        self.shapeList.push(barShape);
                    }

                    // 补充空数据的拖拽提示框
                    for (var m = 0, n = locationMap[j].length; m < n; m++) {
                        seriesIndex = locationMap[j][m];
                        serie = series[seriesIndex];
                        data = serie.data[i];
                        value = typeof data != 'undefined'
                                ? (typeof data.value != 'undefined'
                                  ? data.value
                                  : data)
                                : '-';
                        if (value != '-') {
                            // 只关心空数据
                            continue;
                        }

                        if (self.deepQuery(
                                [data, serie, option], 'calculable'
                            )
                        ) {
                            x = lastXP;
K
kener 已提交
463
                            lastXP += ecConfig.island.r;
K
kener 已提交
464 465 466 467 468

                            barShape = _getBarItem(
                                seriesIndex,
                                i,
                                categoryAxis.getNameByIndex(i),
K
kener 已提交
469 470 471
                                x + 0.5, y + 0.5 - (barWidthMap[seriesIndex] || barWidth),
                                ecConfig.island.r - 1,
                                (barWidthMap[seriesIndex] || barWidth) - 1,
K
kener 已提交
472
                                'horizontal'
K
kener 已提交
473 474 475
                            );
                            barShape.hoverable = false;
                            barShape.draggable = false;
K
kener 已提交
476
                            barShape.style.lineWidth = 1;
K
kener 已提交
477 478 479 480 481 482 483 484 485 486 487 488
                            barShape.style.brushType = 'stroke';
                            barShape.style.strokeColor =
                                    serie.calculableHolderColor
                                    || ecConfig.calculableHolderColor;

                            self.shapeList.push(barShape);
                        }
                    }

                    y -= ((barWidthMap[seriesIndex] || barWidth) + barGap);
                }
            }
K
kener 已提交
489
            _buildMark(seriesArray, xMarkMap, false);
K
kener 已提交
490
        }
K
kener 已提交
491
        
K
kener 已提交
492 493 494 495 496 497 498 499 500 501 502
        /**
         * 我真是自找麻烦啊,为啥要允许系列级个性化最小宽度和高度啊!!!
         * @param {CategoryAxis} categoryAxis 类目坐标轴,需要知道类目间隔大小
         * @param {Array} locationMap 整形数据的系列索引
         */
        function _mapSize(categoryAxis, locationMap, ignoreUserDefined) {
            var barWidthMap = {};
            var barMinHeightMap = {};
            var sBarWidth;
            var sBarWidthCounter = 0;
            var sBarWidthTotal = 0;
K
kener 已提交
503 504
            var barGap;
            var barCategoryGap;
K
kener 已提交
505
            var hasFound;
K
kener 已提交
506
            var queryTarget;
K
kener 已提交
507 508 509 510 511

            for (var j = 0, k = locationMap.length; j < k; j++) {
                hasFound = false;   // 同一堆叠第一个barWidth生效
                for (var m = 0, n = locationMap[j].length; m < n; m++) {
                    seriesIndex = locationMap[j][m];
K
kener 已提交
512
                    queryTarget = series[seriesIndex];
K
kener 已提交
513 514
                    if (!ignoreUserDefined) {
                        if (!hasFound) {
K
kener 已提交
515
                            sBarWidth = self.query(
K
kener 已提交
516
                                queryTarget,
K
kener 已提交
517 518 519 520 521 522 523 524 525 526 527 528 529
                                'barWidth'
                            );
                            if (typeof sBarWidth != 'undefined') {
                                barWidthMap[seriesIndex] = sBarWidth;
                                sBarWidthTotal += sBarWidth;
                                sBarWidthCounter++;
                                hasFound = true;
                            }
                        } else {
                            barWidthMap[seriesIndex] = sBarWidth;   // 用找到的一个
                        }
                    }

K
kener 已提交
530
                    barMinHeightMap[seriesIndex] = self.query(
K
kener 已提交
531
                        queryTarget,
K
kener 已提交
532 533
                        'barMinHeight'
                    );
K
kener 已提交
534 535
                    barGap = typeof barGap != 'undefined' 
                             ? barGap
K
kener 已提交
536
                             : self.query(
K
kener 已提交
537 538 539 540 541
                                   queryTarget,
                                   'barGap'
                               );
                    barCategoryGap = typeof barCategoryGap != 'undefined' 
                                     ? barCategoryGap
K
kener 已提交
542
                                     : self.query(
K
kener 已提交
543 544 545
                                           queryTarget,
                                           'barCategoryGap'
                                       );
K
kener 已提交
546 547 548 549 550 551 552
                }
            }

            var gap;
            var barWidth;
            if (locationMap.length != sBarWidthCounter) {
                // 至少存在一个自适应宽度的柱形图
K
kener 已提交
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
                if (!ignoreUserDefined) {
                    gap = typeof barCategoryGap == 'string' 
                          && barCategoryGap.match(/%$/)
                              // 百分比
                              ? Math.floor(
                                  categoryAxis.getGap() 
                                  * (100 - parseFloat(barCategoryGap)) 
                                  / 100
                                )
                              // 数值
                              : (categoryAxis.getGap() - barCategoryGap);
                    if (typeof barGap == 'string' && barGap.match(/%$/)) {
                        barGap = parseFloat(barGap) / 100;
                        barWidth = Math.floor(
                            (gap - sBarWidthTotal)
                            / ((locationMap.length - 1) * barGap 
                               + locationMap.length - sBarWidthCounter)
                        );
                        barGap = Math.floor(barWidth * barGap);
                    }
                    else {
                        barGap = parseFloat(barGap);
                        barWidth = Math.floor(
                            (gap - sBarWidthTotal 
                                 - barGap * (locationMap.length - 1)
                            )
                            / (locationMap.length - sBarWidthCounter)
                        );
                    }
K
kener 已提交
582
                    // 无法满足用户定义的宽度设计,忽略用户宽度,打回重做
K
kener 已提交
583 584 585 586 587 588 589 590 591 592 593 594 595
                    if (barWidth < 0) {
                        return _mapSize(categoryAxis, locationMap, true);
                    }
                }
                else {
                    // 忽略用户定义的宽度设定
                    gap = categoryAxis.getGap();
                    barGap = 0;
                    barWidth = Math.floor(gap / locationMap.length);
                    // 已经忽略用户定义的宽度设定依然还无法满足显示,只能硬来了;
                    if (barWidth < 0) {
                        barWidth = 1;
                    }
K
kener 已提交
596 597 598
                }
            }
            else {
K
kener 已提交
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
                // 全是自定义宽度,barGap无效,系列间隔决定barGap
                gap = sBarWidthCounter > 1
                      ? (typeof barCategoryGap == 'string' 
                         && barCategoryGap.match(/%$/)
                        )
                          // 百分比
                          ? Math.floor(
                              categoryAxis.getGap() 
                              * (100 - parseFloat(barCategoryGap)) 
                              / 100
                            )
                          // 数值
                          : (categoryAxis.getGap() - barCategoryGap)
                      // 只有一个
                      : sBarWidthTotal;
K
kener 已提交
614
                barWidth = 0;
K
kener 已提交
615 616 617 618 619 620
                barGap = sBarWidthCounter > 1 
                         ? Math.floor(
                               (gap - sBarWidthTotal) / (sBarWidthCounter - 1)
                           )
                         : 0;
                if (barGap < 0) {
K
kener 已提交
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
                    // 无法满足用户定义的宽度设计,忽略用户宽度,打回重做
                    return _mapSize(categoryAxis, locationMap, true);
                }
            }


            return {
                barWidthMap : barWidthMap,
                barMinHeightMap : barMinHeightMap ,
                gap : gap,
                barWidth : barWidth,
                barGap : barGap
            };
        }

        /**
         * 生成最终图形数据
         */
        function _getBarItem(
K
kener 已提交
640
            seriesIndex, dataIndex, name, x, y, width, height, orient
K
kener 已提交
641 642 643 644 645 646
        ) {
            var barShape;
            var serie = series[seriesIndex];
            var data = serie.data[dataIndex];
            // 多级控制
            var defaultColor = _sIndex2colorMap[seriesIndex];
K
kener 已提交
647
            var queryTarget = [data, serie];
K
kener 已提交
648
            var normalColor = self.deepQuery(
K
kener 已提交
649
                queryTarget,
K
kener 已提交
650
                'itemStyle.normal.color'
K
kener 已提交
651
            ) || defaultColor;
K
kener 已提交
652
            var emphasisColor = self.deepQuery(
K
kener 已提交
653
                queryTarget,
K
kener 已提交
654 655
                'itemStyle.emphasis.color'
            );
656
            var normal = self.deepMerge(
K
kener 已提交
657
                queryTarget,
658
                'itemStyle.normal'
K
kener 已提交
659
            );
660 661
            var normalBorderWidth = normal.borderWidth;
            var emphasis = self.deepMerge(
K
kener 已提交
662
                queryTarget,
663
                'itemStyle.emphasis'
K
kener 已提交
664
            );
K
kener 已提交
665 666 667 668 669 670 671 672 673 674
            barShape = {
                shape : 'rectangle',
                zlevel : _zlevelBase,
                clickable: true,
                style : {
                    x : x,
                    y : y,
                    width : width,
                    height : height,
                    brushType : 'both',
K
kener 已提交
675
                    color : self.getItemStyleColor(normalColor, seriesIndex, dataIndex, data),
676 677 678
                    radius : normal.borderRadius,
                    lineWidth : normalBorderWidth,
                    strokeColor : normal.borderColor
K
kener 已提交
679 680
                },
                highlightStyle : {
K
kener 已提交
681
                    color : self.getItemStyleColor(emphasisColor, seriesIndex, dataIndex, data),
682 683 684
                    radius : emphasis.borderRadius,
                    lineWidth : emphasis.borderWidth,
                    strokeColor : emphasis.borderColor
K
kener 已提交
685 686
                },
                _orient : orient
K
kener 已提交
687
            };
K
kener 已提交
688 689 690 691 692
            barShape.highlightStyle.color = barShape.highlightStyle.color
                            || (typeof barShape.style.color == 'string'
                                ? zrColor.lift(barShape.style.color, -0.3)
                                : barShape.style.color
                               );
K
kener 已提交
693
            // 考虑线宽的显示优化
K
kener 已提交
694 695
            if (normalBorderWidth > 0
                && barShape.style.height > normalBorderWidth
696
                && barShape.style.width > normalBorderWidth
K
kener 已提交
697
            ) {
698 699 700 701
                barShape.style.y += normalBorderWidth / 2;
                barShape.style.height -= normalBorderWidth;
                barShape.style.x += normalBorderWidth / 2;
                barShape.style.width -= normalBorderWidth;
K
kener 已提交
702 703
            }
            else {
K
kener 已提交
704
                // 太小了或者线宽小于0,废了边线
K
kener 已提交
705 706 707
                barShape.style.brushType = 'fill';
            }
            
K
kener 已提交
708
            barShape.highlightStyle.textColor = barShape.highlightStyle.color;
K
kener 已提交
709
            
K
kener 已提交
710
            barShape = self.addLabel(barShape, serie, data, name, orient);
K
kener 已提交
711

K
kener 已提交
712
            if (self.deepQuery([data, serie, option],'calculable')) {
K
kener 已提交
713 714 715 716 717 718 719
                self.setCalculable(barShape);
                barShape.draggable = true;
            }

            ecData.pack(
                barShape,
                series[seriesIndex], seriesIndex,
K
kener 已提交
720
                series[seriesIndex].data[dataIndex], dataIndex,
K
kener 已提交
721 722 723 724 725 726
                name
            );

            return barShape;
        }

K
kener 已提交
727 728
        // 添加标注
        function _buildMark(seriesArray, xMarkMap ,isHorizontal) {
K
kener 已提交
729 730 731 732 733 734 735 736
            for (var i = 0, l = seriesArray.length; i < l; i++) {
                self.buildMark(
                    series[seriesArray[i]],
                    seriesArray[i],
                    component,
                    {
                        isHorizontal : isHorizontal,
                        xMarkMap : xMarkMap
K
kener 已提交
737
                    }
K
kener 已提交
738
                );
K
kener 已提交
739 740 741
            }
        }
        
K
kener 已提交
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
        // 位置转换
        function getMarkCoord(serie, seriesIndex, mpData, markCoordParams) {
            var xAxis = component.xAxis.getAxis(serie.xAxisIndex);
            var yAxis = component.yAxis.getAxis(serie.yAxisIndex);
            var dataIndex;
            var pos;
            if (markCoordParams.isHorizontal) {
                // 横向
                dataIndex = typeof mpData.xAxis == 'string'
                            && xAxis.getIndexByName
                            ? xAxis.getIndexByName(mpData.xAxis)
                            : (mpData.xAxis || 0);
                pos = [
                    markCoordParams.xMarkMap[seriesIndex][dataIndex],
                    yAxis.getCoord(mpData.yAxis || 0)
                ];
            }
            else {
                // 纵向
K
kener 已提交
761 762 763 764
                dataIndex = typeof mpData.yAxis == 'string'
                            && yAxis.getIndexByName
                            ? yAxis.getIndexByName(mpData.yAxis)
                            : (mpData.yAxis || 0);
K
kener 已提交
765 766 767 768 769 770 771 772
                pos = [
                    xAxis.getCoord(mpData.xAxis || 0),
                    markCoordParams.xMarkMap[seriesIndex][dataIndex]
                ];
            }
            return pos;
        }
        
K
kener 已提交
773 774 775 776 777 778 779
        /**
         * 构造函数默认执行的初始化方法,也用于创建实例后动态修改
         * @param {Object} newSeries
         * @param {Object} newComponent
         */
        function init(newOption, newComponent) {
            component = newComponent;
K
kener 已提交
780
            refresh(newOption);
K
kener 已提交
781 782 783 784 785
        }

        /**
         * 刷新
         */
K
kener 已提交
786 787 788 789 790
        function refresh(newOption) {
            if (newOption) {
                option = newOption;
                series = option.series;
            }
K
kener 已提交
791 792 793
            self.clear();
            _buildShape();
        }
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824
        
        /**
         * 动态数据增加动画 
         */
        function addDataAnimation(params) {
            var aniMap = {}; // seriesIndex索引参数
            for (var i = 0, l = params.length; i < l; i++) {
                aniMap[params[i][0]] = params[i];
            }
            var x;
            var dx;
            var y;
            var dy;
            var serie;
            var seriesIndex;
            var dataIndex;
            for (var i = self.shapeList.length - 1; i >= 0; i--) {
                seriesIndex = ecData.get(self.shapeList[i], 'seriesIndex');
                if (aniMap[seriesIndex] && !aniMap[seriesIndex][3]) {
                    // 有数据删除才有移动的动画
                    if (self.shapeList[i].shape == 'rectangle') {
                        // 主动画
                        dataIndex = ecData.get(self.shapeList[i], 'dataIndex');
                        serie = series[seriesIndex];
                        if (aniMap[seriesIndex][2] 
                            && dataIndex == serie.data.length - 1
                        ) {
                            // 队头加入删除末尾
                            zr.delShape(self.shapeList[i].id);
                            continue;
                        }
K
kener 已提交
825
                        else if (!aniMap[seriesIndex][2] && dataIndex === 0) {
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 852 853 854 855
                            // 队尾加入删除头部
                            zr.delShape(self.shapeList[i].id);
                            continue;
                        }
                        if (self.shapeList[i]._orient == 'horizontal') {
                            // 条形图
                            dy = component.yAxis.getAxis(
                                    serie.yAxisIndex || 0
                                 ).getGap();
                            y = aniMap[seriesIndex][2] ? -dy : dy;
                            x = 0;
                        }
                        else {
                            // 柱形图
                            dx = component.xAxis.getAxis(
                                    serie.xAxisIndex || 0
                                 ).getGap();
                            x = aniMap[seriesIndex][2] ? dx : -dx;
                            y = 0;
                        }
                        zr.animate(self.shapeList[i].id, '')
                            .when(
                                500,
                                {position : [x, y]}
                            )
                            .start();
                    }
                }
            }
        }
K
kener 已提交
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893

        /**
         * 动画设定
         */
        function animation() {
            var duration;
            var easing;
            var width;
            var height;
            var x;
            var y;
            var serie;
            var dataIndex;
            var value;
            for (var i = 0, l = self.shapeList.length; i < l; i++) {
                if (self.shapeList[i].shape == 'rectangle') {
                    serie = ecData.get(self.shapeList[i], 'series');
                    dataIndex = ecData.get(self.shapeList[i], 'dataIndex');
                    value = ecData.get(self.shapeList[i], 'value');
                    duration = self.deepQuery(
                        [serie, option], 'animationDuration'
                    );
                    easing = self.deepQuery(
                        [serie, option], 'animationEasing'
                    );

                    if (self.shapeList[i]._orient == 'horizontal') {
                        // 条形图
                        width = self.shapeList[i].style.width;
                        x = self.shapeList[i].style.x;
                        if (value < 0) {
                            zr.modShape(
                                self.shapeList[i].id,
                                {
                                    style: {
                                        x : x + width,
                                        width: 0
                                    }
K
kener 已提交
894 895
                                },
                                true
K
kener 已提交
896 897 898 899 900 901 902
                            );
                            zr.animate(self.shapeList[i].id, 'style')
                                .when(
                                    duration + dataIndex * 100,
                                    {
                                        x : x,
                                        width : width
K
kener 已提交
903
                                    }
K
kener 已提交
904
                                )
K
kener 已提交
905
                                .start(easing);
K
kener 已提交
906 907 908 909 910 911 912 913
                        }
                        else {
                            zr.modShape(
                                self.shapeList[i].id,
                                {
                                    style: {
                                        width: 0
                                    }
K
kener 已提交
914 915
                                },
                                true
K
kener 已提交
916 917 918 919 920 921
                            );
                            zr.animate(self.shapeList[i].id, 'style')
                                .when(
                                    duration + dataIndex * 100,
                                    {
                                        width : width
K
kener 已提交
922
                                    }
K
kener 已提交
923
                                )
K
kener 已提交
924
                                .start(easing);
K
kener 已提交
925 926 927 928 929 930 931 932 933 934 935 936 937
                        }
                    }
                    else {
                        // 柱形图
                        height = self.shapeList[i].style.height;
                        y = self.shapeList[i].style.y;
                        if (value < 0) {
                            zr.modShape(
                                self.shapeList[i].id,
                                {
                                    style: {
                                        height: 0
                                    }
K
kener 已提交
938 939
                                },
                                true
K
kener 已提交
940 941 942 943 944 945
                            );
                            zr.animate(self.shapeList[i].id, 'style')
                                .when(
                                    duration + dataIndex * 100,
                                    {
                                        height : height
K
kener 已提交
946
                                    }
K
kener 已提交
947
                                )
K
kener 已提交
948
                                .start(easing);
K
kener 已提交
949 950 951 952 953 954 955 956 957
                        }
                        else {
                            zr.modShape(
                                self.shapeList[i].id,
                                {
                                    style: {
                                        y: y + height,
                                        height: 0
                                    }
K
kener 已提交
958 959
                                },
                                true
K
kener 已提交
960 961 962 963 964 965 966
                            );
                            zr.animate(self.shapeList[i].id, 'style')
                                .when(
                                    duration + dataIndex * 100,
                                    {
                                        y : y,
                                        height : height
K
kener 已提交
967
                                    }
K
kener 已提交
968
                                )
K
kener 已提交
969
                                .start(easing);
K
kener 已提交
970 971 972 973
                        }
                    }
                }
            }
K
kener 已提交
974 975
            
            self.animationMark(duration, easing);
K
kener 已提交
976 977
        }

K
kener 已提交
978 979
        // 重载基类方法
        self.getMarkCoord = getMarkCoord;
K
kener 已提交
980
        self.animation = animation;
K
kener 已提交
981
        
K
kener 已提交
982 983
        self.init = init;
        self.refresh = refresh;
984
        self.addDataAnimation = addDataAnimation;
K
kener 已提交
985 986 987 988

        init(option, component);
    }

989 990 991
    // 图表注册
    require('../chart').define('bar', Bar);
    
K
kener 已提交
992 993
    return Bar;
});