AxisBuilder.js 23.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

S
susiwen 已提交
20
import {retrieve, defaults, extend, each} from 'zrender/src/core/util';
S
sushuang 已提交
21 22 23 24
import * as formatUtil from '../../util/format';
import * as graphic from '../../util/graphic';
import Model from '../../model/Model';
import {isRadianAroundZero, remRadian} from '../../util/number';
O
merge  
Ovilia 已提交
25
import {createSymbol} from '../../util/symbol';
S
sushuang 已提交
26
import * as matrixUtil from 'zrender/src/core/matrix';
S
sushuang 已提交
27
import {applyTransform as v2ApplyTransform} from 'zrender/src/core/vector';
28
import {shouldShowAllLabels} from '../../coord/axisHelper';
S
sushuang 已提交
29

S
sushuang 已提交
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

var PI = Math.PI;

/**
 * A final axis is translated and rotated from a "standard axis".
 * So opt.position and opt.rotation is required.
 *
 * A standard axis is and axis from [0, 0] to [0, axisExtent[1]],
 * for example: (0, 0) ------------> (0, 50)
 *
 * nameDirection or tickDirection or labelDirection is 1 means tick
 * or label is below the standard axis, whereas is -1 means above
 * the standard axis. labelOffset means offset between label and axis,
 * which is useful when 'onZero', where axisLabel is in the grid and
 * label in outside grid.
 *
 * Tips: like always,
 * positive rotation represents anticlockwise, and negative rotation
 * represents clockwise.
 * The direction of position coordinate is the same as the direction
 * of screen coordinate.
 *
 * Do not need to consider axis 'inverse', which is auto processed by
 * axis extent.
 *
 * @param {module:zrender/container/Group} group
 * @param {Object} axisModel
 * @param {Object} opt Standard axis parameters.
 * @param {Array.<number>} opt.position [x, y]
 * @param {number} opt.rotation by radian
 * @param {number} [opt.nameDirection=1] 1 or -1 Used when nameLocation is 'middle' or 'center'.
 * @param {number} [opt.tickDirection=1] 1 or -1
 * @param {number} [opt.labelDirection=1] 1 or -1
 * @param {number} [opt.labelOffset=0] Usefull when onZero.
 * @param {string} [opt.axisLabelShow] default get from axisModel.
 * @param {string} [opt.axisName] default get from axisModel.
 * @param {number} [opt.axisNameAvailableWidth]
 * @param {number} [opt.labelRotate] by degree, default get from axisModel.
 * @param {number} [opt.strokeContainThreshold] Default label interval when label
 * @param {number} [opt.nameTruncateMaxWidth]
 */
var AxisBuilder = function (axisModel, opt) {
L
lang 已提交
72

P
pah100 已提交
73
    /**
S
sushuang 已提交
74
     * @readOnly
P
pah100 已提交
75
     */
S
sushuang 已提交
76
    this.opt = opt;
P
pah100 已提交
77

S
sushuang 已提交
78 79 80 81 82 83
    /**
     * @readOnly
     */
    this.axisModel = axisModel;

    // Default value
S
sushuang 已提交
84
    defaults(
S
sushuang 已提交
85 86 87 88 89 90 91 92 93
        opt,
        {
            labelOffset: 0,
            nameDirection: 1,
            tickDirection: 1,
            labelDirection: 1,
            silent: true
        }
    );
L
lang 已提交
94

S
sushuang 已提交
95 96 97 98
    /**
     * @readOnly
     */
    this.group = new graphic.Group();
L
lang 已提交
99

S
sushuang 已提交
100 101 102 103 104
    // FIXME Not use a seperate text group?
    var dumbGroup = new graphic.Group({
        position: opt.position.slice(),
        rotation: opt.rotation
    });
L
lang 已提交
105

S
sushuang 已提交
106 107
    // this.group.add(dumbGroup);
    // this._dumbGroup = dumbGroup;
L
lang 已提交
108

S
sushuang 已提交
109 110
    dumbGroup.updateTransform();
    this._transform = dumbGroup.transform;
P
pah100 已提交
111

S
sushuang 已提交
112 113
    this._dumbGroup = dumbGroup;
};
P
pah100 已提交
114

S
sushuang 已提交
115
AxisBuilder.prototype = {
P
pah100 已提交
116

S
sushuang 已提交
117
    constructor: AxisBuilder,
P
pah100 已提交
118

S
sushuang 已提交
119 120 121
    hasBuilder: function (name) {
        return !!builders[name];
    },
P
pah100 已提交
122

S
sushuang 已提交
123 124 125
    add: function (name) {
        builders[name].call(this);
    },
P
pah100 已提交
126

S
sushuang 已提交
127 128 129
    getGroup: function () {
        return this.group;
    }
P
pah100 已提交
130

S
sushuang 已提交
131
};
P
pah100 已提交
132

S
sushuang 已提交
133
var builders = {
P
pah100 已提交
134

S
sushuang 已提交
135 136 137 138 139 140
    /**
     * @private
     */
    axisLine: function () {
        var opt = this.opt;
        var axisModel = this.axisModel;
P
pah100 已提交
141

S
sushuang 已提交
142 143 144
        if (!axisModel.get('axisLine.show')) {
            return;
        }
L
lang 已提交
145

S
sushuang 已提交
146
        var extent = this.axisModel.axis.getExtent();
O
Ovilia 已提交
147

S
sushuang 已提交
148 149 150 151 152 153 154
        var matrix = this._transform;
        var pt1 = [extent[0], 0];
        var pt2 = [extent[1], 0];
        if (matrix) {
            v2ApplyTransform(pt1, pt1, matrix);
            v2ApplyTransform(pt2, pt2, matrix);
        }
O
Ovilia 已提交
155

S
sushuang 已提交
156
        var lineStyle = extend(
O
merge  
Ovilia 已提交
157 158 159 160 161
            {
                lineCap: 'round'
            },
            axisModel.getModel('axisLine.lineStyle').getLineStyle()
        );
O
Ovilia 已提交
162

163
        this.group.add(new graphic.Line({
S
sushuang 已提交
164 165
            // Id for animation
            anid: 'line',
166
            subPixelOptimize: true,
S
sushuang 已提交
167 168 169 170 171 172
            shape: {
                x1: pt1[0],
                y1: pt1[1],
                x2: pt2[0],
                y2: pt2[1]
            },
O
merge  
Ovilia 已提交
173
            style: lineStyle,
S
sushuang 已提交
174 175 176
            strokeContainThreshold: opt.strokeContainThreshold || 5,
            silent: true,
            z2: 1
177
        }));
O
merge  
Ovilia 已提交
178 179 180 181

        var arrows = axisModel.get('axisLine.symbol');
        var arrowSize = axisModel.get('axisLine.symbolSize');

O
Ovilia 已提交
182 183 184 185 186
        var arrowOffset = axisModel.get('axisLine.symbolOffset') || 0;
        if (typeof arrowOffset === 'number') {
            arrowOffset = [arrowOffset, arrowOffset];
        }

O
merge  
Ovilia 已提交
187 188 189 190
        if (arrows != null) {
            if (typeof arrows === 'string') {
                // Use the same arrow for start and end point
                arrows = [arrows, arrows];
P
pah100 已提交
191
            }
O
merge  
Ovilia 已提交
192 193 194 195 196
            if (typeof arrowSize === 'string'
                || typeof arrowSize === 'number'
            ) {
                // Use the same size for width and height
                arrowSize = [arrowSize, arrowSize];
P
pah100 已提交
197 198
            }

O
merge  
Ovilia 已提交
199 200 201
            var symbolWidth = arrowSize[0];
            var symbolHeight = arrowSize[1];

202 203 204 205 206 207 208 209 210 211
            each([{
                rotate: opt.rotation + Math.PI / 2,
                offset: arrowOffset[0],
                r: 0
            }, {
                rotate: opt.rotation - Math.PI / 2,
                offset: arrowOffset[1],
                r: Math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0])
                    + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1]))
            }], function (point, index) {
S
sushuang 已提交
212 213 214 215 216 217 218 219 220 221
                if (arrows[index] !== 'none' && arrows[index] != null) {
                    var symbol = createSymbol(
                        arrows[index],
                        -symbolWidth / 2,
                        -symbolHeight / 2,
                        symbolWidth,
                        symbolHeight,
                        lineStyle.stroke,
                        true
                    );
O
Ovilia 已提交
222 223

                    // Calculate arrow position with offset
224 225 226 227 228
                    var r = point.r + point.offset;
                    var pos = [
                        pt1[0] + r * Math.cos(opt.rotation),
                        pt1[1] - r * Math.sin(opt.rotation)
                    ];
O
Ovilia 已提交
229

S
sushuang 已提交
230
                    symbol.attr({
231
                        rotation: point.rotate,
O
Ovilia 已提交
232
                        position: pos,
233 234
                        silent: true,
                        z2: 11
S
sushuang 已提交
235 236 237 238
                    });
                    this.group.add(symbol);
                }
            }, this);
O
merge  
Ovilia 已提交
239
        }
S
sushuang 已提交
240
    },
P
pah100 已提交
241

S
sushuang 已提交
242 243 244 245 246 247
    /**
     * @private
     */
    axisTickLabel: function () {
        var axisModel = this.axisModel;
        var opt = this.opt;
L
lang 已提交
248

P
pissang 已提交
249
        var ticksEls = buildAxisMajorTicks(this, axisModel, opt);
S
sushuang 已提交
250
        var labelEls = buildAxisLabel(this, axisModel, opt);
P
pah100 已提交
251

P
pissang 已提交
252 253
        fixMinMaxLabelShow(axisModel, labelEls, ticksEls);

P
pissang 已提交
254
        buildAxisMinorTicks(this, axisModel, opt);
S
sushuang 已提交
255
    },
P
pah100 已提交
256 257

    /**
S
sushuang 已提交
258
     * @private
P
pah100 已提交
259
     */
S
sushuang 已提交
260 261 262 263 264 265 266
    axisName: function () {
        var opt = this.opt;
        var axisModel = this.axisModel;
        var name = retrieve(opt.axisName, axisModel.get('name'));

        if (!name) {
            return;
P
pah100 已提交
267 268
        }

S
sushuang 已提交
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
        var nameLocation = axisModel.get('nameLocation');
        var nameDirection = opt.nameDirection;
        var textStyleModel = axisModel.getModel('nameTextStyle');
        var gap = axisModel.get('nameGap') || 0;

        var extent = this.axisModel.axis.getExtent();
        var gapSignal = extent[0] > extent[1] ? -1 : 1;
        var pos = [
            nameLocation === 'start'
                ? extent[0] - gapSignal * gap
                : nameLocation === 'end'
                ? extent[1] + gapSignal * gap
                : (extent[0] + extent[1]) / 2, // 'middle'
            // Reuse labelOffset.
            isNameLocationCenter(nameLocation) ? opt.labelOffset + nameDirection * gap : 0
        ];

        var labelLayout;

        var nameRotation = axisModel.get('nameRotate');
        if (nameRotation != null) {
            nameRotation = nameRotation * PI / 180; // To radian.
P
pah100 已提交
291 292
        }

S
sushuang 已提交
293
        var axisNameAvailableWidth;
P
pah100 已提交
294

S
sushuang 已提交
295 296 297 298 299 300
        if (isNameLocationCenter(nameLocation)) {
            labelLayout = innerTextLayout(
                opt.rotation,
                nameRotation != null ? nameRotation : opt.rotation, // Adapt to axis.
                nameDirection
            );
P
pah100 已提交
301 302
        }
        else {
S
sushuang 已提交
303 304 305 306 307 308 309 310 311 312
            labelLayout = endTextLayout(
                opt, nameLocation, nameRotation || 0, extent
            );

            axisNameAvailableWidth = opt.axisNameAvailableWidth;
            if (axisNameAvailableWidth != null) {
                axisNameAvailableWidth = Math.abs(
                    axisNameAvailableWidth / Math.sin(labelLayout.rotation)
                );
                !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null);
P
pah100 已提交
313 314 315
            }
        }

S
sushuang 已提交
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
        var textFont = textStyleModel.getFont();

        var truncateOpt = axisModel.get('nameTruncate', true) || {};
        var ellipsis = truncateOpt.ellipsis;
        var maxWidth = retrieve(
            opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth
        );
        // FIXME
        // truncate rich text? (consider performance)
        var truncatedText = (ellipsis != null && maxWidth != null)
            ? formatUtil.truncateText(
                name, maxWidth, textFont, ellipsis,
                {minChar: 2, placeholder: truncateOpt.placeholder}
            )
            : name;

        var tooltipOpt = axisModel.get('tooltip', true);

        var mainType = axisModel.mainType;
        var formatterParams = {
            componentType: mainType,
            name: name,
            $vars: ['name']
P
pah100 已提交
339
        };
S
sushuang 已提交
340 341 342 343 344 345 346 347 348 349 350
        formatterParams[mainType + 'Index'] = axisModel.componentIndex;

        var textEl = new graphic.Text({
            // Id for animation
            anid: 'name',

            __fullText: name,
            __truncatedText: truncatedText,

            position: pos,
            rotation: labelLayout.rotation,
351
            silent: isLabelSilent(axisModel),
S
sushuang 已提交
352 353
            z2: 1,
            tooltip: (tooltipOpt && tooltipOpt.show)
S
sushuang 已提交
354
                ? extend({
S
sushuang 已提交
355 356 357 358 359 360 361 362
                    content: name,
                    formatter: function () {
                        return name;
                    },
                    formatterParams: formatterParams
                }, tooltipOpt)
                : null
        });
P
pah100 已提交
363

S
sushuang 已提交
364 365 366 367 368
        graphic.setTextStyle(textEl.style, textStyleModel, {
            text: truncatedText,
            textFont: textFont,
            textFill: textStyleModel.getTextColor()
                || axisModel.get('axisLine.lineStyle.color'),
369 370 371 372
            textAlign: textStyleModel.get('align')
                || labelLayout.textAlign,
            textVerticalAlign: textStyleModel.get('verticalAlign')
                || labelLayout.textVerticalAlign
S
sushuang 已提交
373
        });
1
100pah 已提交
374

S
sushuang 已提交
375 376 377 378 379
        if (axisModel.get('triggerEvent')) {
            textEl.eventData = makeAxisEventDataBase(axisModel);
            textEl.eventData.targetType = 'axisName';
            textEl.eventData.name = name;
        }
O
Ovilia 已提交
380

S
sushuang 已提交
381
        // FIXME
S
sushuang 已提交
382 383
        this._dumbGroup.add(textEl);
        textEl.updateTransform();
S
sushuang 已提交
384

S
sushuang 已提交
385
        this.group.add(textEl);
S
sushuang 已提交
386

S
sushuang 已提交
387 388
        textEl.decomposeTransform();
    }
389

S
sushuang 已提交
390 391
};

392 393 394 395 396 397 398 399 400
var makeAxisEventDataBase = AxisBuilder.makeAxisEventDataBase = function (axisModel) {
    var eventData = {
        componentType: axisModel.mainType,
        componentIndex: axisModel.componentIndex
    };
    eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex;
    return eventData;
};

S
sushuang 已提交
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
/**
 * @public
 * @static
 * @param {Object} opt
 * @param {number} axisRotation in radian
 * @param {number} textRotation in radian
 * @param {number} direction
 * @return {Object} {
 *  rotation, // according to axis
 *  textAlign,
 *  textVerticalAlign
 * }
 */
var innerTextLayout = AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) {
    var rotationDiff = remRadian(textRotation - axisRotation);
    var textAlign;
    var textVerticalAlign;

    if (isRadianAroundZero(rotationDiff)) { // Label is parallel with axis line.
        textVerticalAlign = direction > 0 ? 'top' : 'bottom';
        textAlign = 'center';
    }
    else if (isRadianAroundZero(rotationDiff - PI)) { // Label is inverse parallel with axis line.
        textVerticalAlign = direction > 0 ? 'bottom' : 'top';
        textAlign = 'center';
    }
    else {
        textVerticalAlign = 'middle';
O
Ovilia 已提交
429

S
sushuang 已提交
430 431
        if (rotationDiff > 0 && rotationDiff < PI) {
            textAlign = direction > 0 ? 'right' : 'left';
432
        }
S
sushuang 已提交
433 434
        else {
            textAlign = direction > 0 ? 'left' : 'right';
435
        }
S
sushuang 已提交
436
    }
437

S
sushuang 已提交
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
    return {
        rotation: rotationDiff,
        textAlign: textAlign,
        textVerticalAlign: textVerticalAlign
    };
};

function endTextLayout(opt, textPosition, textRotate, extent) {
    var rotationDiff = remRadian(textRotate - opt.rotation);
    var textAlign;
    var textVerticalAlign;
    var inverse = extent[0] > extent[1];
    var onLeft = (textPosition === 'start' && !inverse)
        || (textPosition !== 'start' && inverse);

    if (isRadianAroundZero(rotationDiff - PI / 2)) {
        textVerticalAlign = onLeft ? 'bottom' : 'top';
        textAlign = 'center';
    }
    else if (isRadianAroundZero(rotationDiff - PI * 1.5)) {
        textVerticalAlign = onLeft ? 'top' : 'bottom';
        textAlign = 'center';
    }
    else {
        textVerticalAlign = 'middle';
        if (rotationDiff < PI * 1.5 && rotationDiff > PI / 2) {
            textAlign = onLeft ? 'left' : 'right';
465
        }
S
sushuang 已提交
466 467
        else {
            textAlign = onLeft ? 'right' : 'left';
468 469 470
        }
    }

S
sushuang 已提交
471 472 473 474 475 476 477
    return {
        rotation: rotationDiff,
        textAlign: textAlign,
        textVerticalAlign: textVerticalAlign
    };
}

478
var isLabelSilent = AxisBuilder.isLabelSilent = function (axisModel) {
S
sushuang 已提交
479 480 481 482 483 484
    var tooltipOpt = axisModel.get('tooltip');
    return axisModel.get('silent')
        // Consider mouse cursor, add these restrictions.
        || !(
            axisModel.get('triggerEvent') || (tooltipOpt && tooltipOpt.show)
        );
485
};
S
sushuang 已提交
486 487

function fixMinMaxLabelShow(axisModel, labelEls, tickEls) {
488 489 490 491
    if (shouldShowAllLabels(axisModel.axis)) {
        return;
    }

S
sushuang 已提交
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
    // If min or max are user set, we need to check
    // If the tick on min(max) are overlap on their neighbour tick
    // If they are overlapped, we need to hide the min(max) tick label
    var showMinLabel = axisModel.get('axisLabel.showMinLabel');
    var showMaxLabel = axisModel.get('axisLabel.showMaxLabel');

    // FIXME
    // Have not consider onBand yet, where tick els is more than label els.

    labelEls = labelEls || [];
    tickEls = tickEls || [];

    var firstLabel = labelEls[0];
    var nextLabel = labelEls[1];
    var lastLabel = labelEls[labelEls.length - 1];
    var prevLabel = labelEls[labelEls.length - 2];

    var firstTick = tickEls[0];
    var nextTick = tickEls[1];
    var lastTick = tickEls[tickEls.length - 1];
    var prevTick = tickEls[tickEls.length - 2];

    if (showMinLabel === false) {
        ignoreEl(firstLabel);
        ignoreEl(firstTick);
    }
    else if (isTwoLabelOverlapped(firstLabel, nextLabel)) {
        if (showMinLabel) {
            ignoreEl(nextLabel);
            ignoreEl(nextTick);
        }
        else {
            ignoreEl(firstLabel);
            ignoreEl(firstTick);
        }
S
sushuang 已提交
527 528
    }

S
sushuang 已提交
529 530 531 532 533 534 535 536
    if (showMaxLabel === false) {
        ignoreEl(lastLabel);
        ignoreEl(lastTick);
    }
    else if (isTwoLabelOverlapped(prevLabel, lastLabel)) {
        if (showMaxLabel) {
            ignoreEl(prevLabel);
            ignoreEl(prevTick);
537
        }
S
sushuang 已提交
538 539 540
        else {
            ignoreEl(lastLabel);
            ignoreEl(lastTick);
541
        }
S
sushuang 已提交
542 543
    }
}
544

S
sushuang 已提交
545 546 547
function ignoreEl(el) {
    el && (el.ignore = true);
}
548

S
sushuang 已提交
549 550 551 552
function isTwoLabelOverlapped(current, next, labelLayout) {
    // current and next has the same rotation.
    var firstRect = current && current.getBoundingRect().clone();
    var nextRect = next && next.getBoundingRect().clone();
553

S
sushuang 已提交
554 555
    if (!firstRect || !nextRect) {
        return;
556 557
    }

S
sushuang 已提交
558 559
    // When checking intersect of two rotated labels, we use mRotationBack
    // to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`.
S
sushuang 已提交
560 561
    var mRotationBack = matrixUtil.identity([]);
    matrixUtil.rotate(mRotationBack, mRotationBack, -current.rotation);
S
sushuang 已提交
562

S
sushuang 已提交
563 564
    firstRect.applyTransform(matrixUtil.mul([], mRotationBack, current.getLocalTransform()));
    nextRect.applyTransform(matrixUtil.mul([], mRotationBack, next.getLocalTransform()));
S
sushuang 已提交
565 566 567 568 569 570 571 572

    return firstRect.intersect(nextRect);
}

function isNameLocationCenter(nameLocation) {
    return nameLocation === 'middle' || nameLocation === 'center';
}

S
sushuang 已提交
573

P
pissang 已提交
574 575
function createTicks(ticksCoords, tickTransform, tickEndCoord, tickLineStyle, aniid) {
    var tickEls = [];
S
sushuang 已提交
576 577
    var pt1 = [];
    var pt2 = [];
578
    for (var i = 0; i < ticksCoords.length; i++) {
579
        var tickCoord = ticksCoords[i].coord;
S
sushuang 已提交
580

S
sushuang 已提交
581 582 583
        pt1[0] = tickCoord;
        pt1[1] = 0;
        pt2[0] = tickCoord;
P
pissang 已提交
584
        pt2[1] = tickEndCoord;
S
sushuang 已提交
585

P
pissang 已提交
586 587 588
        if (tickTransform) {
            v2ApplyTransform(pt1, pt1, tickTransform);
            v2ApplyTransform(pt2, pt2, tickTransform);
S
sushuang 已提交
589
        }
S
sushuang 已提交
590
        // Tick line, Not use group transform to have better line draw
591
        var tickEl = new graphic.Line({
S
sushuang 已提交
592
            // Id for animation
P
pissang 已提交
593
            anid: aniid + '_' + ticksCoords[i].tickValue,
594
            subPixelOptimize: true,
S
sushuang 已提交
595 596 597 598 599 600
            shape: {
                x1: pt1[0],
                y1: pt1[1],
                x2: pt2[0],
                y2: pt2[1]
            },
P
pissang 已提交
601
            style: tickLineStyle,
S
sushuang 已提交
602 603
            z2: 2,
            silent: true
604
        });
S
sushuang 已提交
605 606 607 608
        tickEls.push(tickEl);
    }
    return tickEls;
}
S
sushuang 已提交
609

P
pissang 已提交
610 611 612 613 614 615 616 617 618 619 620 621
function buildAxisMajorTicks(axisBuilder, axisModel, opt) {
    var axis = axisModel.axis;

    var tickModel = axisModel.getModel('axisTick');

    if (!tickModel.get('show') || axis.scale.isBlank()) {
        return;
    }

    var lineStyleModel = tickModel.getModel('lineStyle');
    var tickEndCoord = opt.tickDirection * tickModel.get('length');

622
    var ticksCoords = axis.getTicksCoords();
P
pissang 已提交
623 624 625 626 627 628 629 630

    var ticksEls = createTicks(ticksCoords, axisBuilder._transform, tickEndCoord, defaults(
        lineStyleModel.getLineStyle(),
        {
            stroke: axisModel.get('axisLine.lineStyle.color')
        }
    ), 'ticks');

P
pissang 已提交
631
    for (var i = 0; i < ticksEls.length; i++) {
P
pissang 已提交
632 633 634 635 636 637
        axisBuilder.group.add(ticksEls[i]);
    }

    return ticksEls;
}

P
pissang 已提交
638
function buildAxisMinorTicks(axisBuilder, axisModel, opt) {
P
pissang 已提交
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
    var axis = axisModel.axis;

    var minorTickModel = axisModel.getModel('minorTick');

    if (!minorTickModel.get('show') || axis.scale.isBlank()) {
        return;
    }

    var minorTicksCoords = axis.getMinorTicksCoords();
    if (!minorTicksCoords.length) {
        return;
    }

    var lineStyleModel = minorTickModel.getModel('lineStyle');
    var tickEndCoord = opt.tickDirection * minorTickModel.get('length');

    var minorTickLineStyle = defaults(
        lineStyleModel.getLineStyle(),
        defaults(
            axisModel.getModel('axisTick').getLineStyle(),
            {
                stroke: axisModel.get('axisLine.lineStyle.color')
            }
        )
    );

    for (var i = 0; i < minorTicksCoords.length; i++) {
        var minorTicksEls = createTicks(
S
susiwen 已提交
667
            minorTicksCoords[i], axisBuilder._transform, tickEndCoord, minorTickLineStyle, 'minorticks_' + i
P
pissang 已提交
668
        );
P
pissang 已提交
669
        for (var k = 0; k < minorTicksEls.length; k++) {
P
pissang 已提交
670 671 672 673 674
            axisBuilder.group.add(minorTicksEls[k]);
        }
    }
}

S
sushuang 已提交
675 676 677
function buildAxisLabel(axisBuilder, axisModel, opt) {
    var axis = axisModel.axis;
    var show = retrieve(opt.axisLabelShow, axisModel.get('axisLabel.show'));
S
sushuang 已提交
678

S
sushuang 已提交
679 680 681
    if (!show || axis.scale.isBlank()) {
        return;
    }
S
sushuang 已提交
682

S
sushuang 已提交
683 684
    var labelModel = axisModel.getModel('axisLabel');
    var labelMargin = labelModel.get('margin');
685
    var labels = axis.getViewLabels();
S
sushuang 已提交
686

S
sushuang 已提交
687 688 689 690
    // Special label rotate.
    var labelRotation = (
        retrieve(opt.labelRotate, labelModel.get('rotate')) || 0
    ) * PI / 180;
S
sushuang 已提交
691

S
sushuang 已提交
692
    var labelLayout = innerTextLayout(opt.rotation, labelRotation, opt.labelDirection);
693
    var rawCategoryData = axisModel.getCategories && axisModel.getCategories(true);
S
sushuang 已提交
694

S
sushuang 已提交
695
    var labelEls = [];
696
    var silent = isLabelSilent(axisModel);
S
sushuang 已提交
697
    var triggerEvent = axisModel.get('triggerEvent');
S
sushuang 已提交
698

699 700 701 702
    each(labels, function (labelItem, index) {
        var tickValue = labelItem.tickValue;
        var formattedLabel = labelItem.formattedLabel;
        var rawLabel = labelItem.rawLabel;
S
sushuang 已提交
703

S
sushuang 已提交
704
        var itemLabelModel = labelModel;
705
        if (rawCategoryData && rawCategoryData[tickValue] && rawCategoryData[tickValue].textStyle) {
S
sushuang 已提交
706
            itemLabelModel = new Model(
707
                rawCategoryData[tickValue].textStyle, labelModel, axisModel.ecModel
S
sushuang 已提交
708 709
            );
        }
S
sushuang 已提交
710

S
sushuang 已提交
711 712 713
        var textColor = itemLabelModel.getTextColor()
            || axisModel.get('axisLine.lineStyle.color');

714
        var tickCoord = axis.dataToCoord(tickValue);
S
sushuang 已提交
715 716 717 718 719 720 721
        var pos = [
            tickCoord,
            opt.labelOffset + opt.labelDirection * labelMargin
        ];

        var textEl = new graphic.Text({
            // Id for animation
722
            anid: 'label_' + tickValue,
S
sushuang 已提交
723 724 725 726 727
            position: pos,
            rotation: labelLayout.rotation,
            silent: silent,
            z2: 10
        });
S
sushuang 已提交
728

S
sushuang 已提交
729
        graphic.setTextStyle(textEl.style, itemLabelModel, {
730
            text: formattedLabel,
S
sushuang 已提交
731 732 733 734 735 736 737 738 739 740
            textAlign: itemLabelModel.getShallow('align', true)
                || labelLayout.textAlign,
            textVerticalAlign: itemLabelModel.getShallow('verticalAlign', true)
                || itemLabelModel.getShallow('baseline', true)
                || labelLayout.textVerticalAlign,
            textFill: typeof textColor === 'function'
                ? textColor(
                    // (1) In category axis with data zoom, tick is not the original
                    // index of axis.data. So tick should not be exposed to user
                    // in category axis.
741 742 743
                    // (2) Compatible with previous version, which always use formatted label as
                    // input. But in interval scale the formatted label is like '223,445', which
                    // maked user repalce ','. So we modify it to return original val but remain
S
sushuang 已提交
744
                    // it as 'string' to avoid error in replacing.
745 746 747 748 749
                    axis.type === 'category'
                        ? rawLabel
                        : axis.type === 'value'
                        ? tickValue + ''
                        : tickValue,
S
sushuang 已提交
750 751 752
                    index
                )
                : textColor
S
sushuang 已提交
753 754
        });

S
sushuang 已提交
755 756 757 758
        // Pack data for mouse event
        if (triggerEvent) {
            textEl.eventData = makeAxisEventDataBase(axisModel);
            textEl.eventData.targetType = 'axisLabel';
759
            textEl.eventData.value = rawLabel;
S
sushuang 已提交
760 761 762 763 764 765 766 767 768 769 770 771
        }

        // FIXME
        axisBuilder._dumbGroup.add(textEl);
        textEl.updateTransform();

        labelEls.push(textEl);
        axisBuilder.group.add(textEl);

        textEl.decomposeTransform();

    });
S
sushuang 已提交
772

S
sushuang 已提交
773 774
    return labelEls;
}
S
sushuang 已提交
775

P
pah100 已提交
776

S
sushuang 已提交
777
export default AxisBuilder;