AxisBuilder.js 22.2 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
sushuang 已提交
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

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

S
sushuang 已提交
252 253
        fixMinMaxLabelShow(axisModel, labelEls, tickEls);
    },
P
pah100 已提交
254 255

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

        if (!name) {
            return;
P
pah100 已提交
265 266
        }

S
sushuang 已提交
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
        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 已提交
289 290
        }

S
sushuang 已提交
291
        var axisNameAvailableWidth;
P
pah100 已提交
292

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

S
sushuang 已提交
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
        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 已提交
337
        };
S
sushuang 已提交
338 339 340 341 342 343 344 345 346 347 348
        formatterParams[mainType + 'Index'] = axisModel.componentIndex;

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

            __fullText: name,
            __truncatedText: truncatedText,

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

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

S
sushuang 已提交
371 372 373 374 375
        if (axisModel.get('triggerEvent')) {
            textEl.eventData = makeAxisEventDataBase(axisModel);
            textEl.eventData.targetType = 'axisName';
            textEl.eventData.name = name;
        }
O
Ovilia 已提交
376

S
sushuang 已提交
377
        // FIXME
S
sushuang 已提交
378 379
        this._dumbGroup.add(textEl);
        textEl.updateTransform();
S
sushuang 已提交
380

S
sushuang 已提交
381
        this.group.add(textEl);
S
sushuang 已提交
382

S
sushuang 已提交
383 384
        textEl.decomposeTransform();
    }
385

S
sushuang 已提交
386 387
};

388 389 390 391 392 393 394 395 396
var makeAxisEventDataBase = AxisBuilder.makeAxisEventDataBase = function (axisModel) {
    var eventData = {
        componentType: axisModel.mainType,
        componentIndex: axisModel.componentIndex
    };
    eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex;
    return eventData;
};

S
sushuang 已提交
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
/**
 * @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 已提交
425

S
sushuang 已提交
426 427
        if (rotationDiff > 0 && rotationDiff < PI) {
            textAlign = direction > 0 ? 'right' : 'left';
428
        }
S
sushuang 已提交
429 430
        else {
            textAlign = direction > 0 ? 'left' : 'right';
431
        }
S
sushuang 已提交
432
    }
433

S
sushuang 已提交
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
    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';
461
        }
S
sushuang 已提交
462 463
        else {
            textAlign = onLeft ? 'right' : 'left';
464 465 466
        }
    }

S
sushuang 已提交
467 468 469 470 471 472 473
    return {
        rotation: rotationDiff,
        textAlign: textAlign,
        textVerticalAlign: textVerticalAlign
    };
}

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

function fixMinMaxLabelShow(axisModel, labelEls, tickEls) {
484 485 486 487
    if (shouldShowAllLabels(axisModel.axis)) {
        return;
    }

S
sushuang 已提交
488 489 490 491 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
    // 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 已提交
523 524
    }

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

S
sushuang 已提交
541 542 543
function ignoreEl(el) {
    el && (el.ignore = true);
}
544

S
sushuang 已提交
545 546 547 548
function isTwoLabelOverlapped(current, next, labelLayout) {
    // current and next has the same rotation.
    var firstRect = current && current.getBoundingRect().clone();
    var nextRect = next && next.getBoundingRect().clone();
549

S
sushuang 已提交
550 551
    if (!firstRect || !nextRect) {
        return;
552 553
    }

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

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

    return firstRect.intersect(nextRect);
}

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

function buildAxisTick(axisBuilder, axisModel, opt) {
    var axis = axisModel.axis;
P
pah100 已提交
571

S
sushuang 已提交
572 573 574
    if (!axisModel.get('axisTick.show') || axis.scale.isBlank()) {
        return;
    }
S
sushuang 已提交
575

S
sushuang 已提交
576
    var tickModel = axisModel.getModel('axisTick');
S
sushuang 已提交
577

S
sushuang 已提交
578 579
    var lineStyleModel = tickModel.getModel('lineStyle');
    var tickLen = tickModel.get('length');
S
sushuang 已提交
580

581
    var ticksCoords = axis.getTicksCoords();
S
sushuang 已提交
582

S
sushuang 已提交
583 584 585
    var pt1 = [];
    var pt2 = [];
    var matrix = axisBuilder._transform;
S
sushuang 已提交
586

S
sushuang 已提交
587
    var tickEls = [];
S
sushuang 已提交
588

589 590
    for (var i = 0; i < ticksCoords.length; i++) {
        var tickCoord = ticksCoords[i].coord;
S
sushuang 已提交
591

S
sushuang 已提交
592 593 594 595
        pt1[0] = tickCoord;
        pt1[1] = 0;
        pt2[0] = tickCoord;
        pt2[1] = opt.tickDirection * tickLen;
S
sushuang 已提交
596

S
sushuang 已提交
597 598 599
        if (matrix) {
            v2ApplyTransform(pt1, pt1, matrix);
            v2ApplyTransform(pt2, pt2, matrix);
S
sushuang 已提交
600
        }
S
sushuang 已提交
601
        // Tick line, Not use group transform to have better line draw
602
        var tickEl = new graphic.Line({
S
sushuang 已提交
603
            // Id for animation
604
            anid: 'tick_' + ticksCoords[i].tickValue,
605
            subPixelOptimize: true,
S
sushuang 已提交
606 607 608 609 610 611
            shape: {
                x1: pt1[0],
                y1: pt1[1],
                x2: pt2[0],
                y2: pt2[1]
            },
S
sushuang 已提交
612
            style: defaults(
S
sushuang 已提交
613 614 615 616 617 618 619
                lineStyleModel.getLineStyle(),
                {
                    stroke: axisModel.get('axisLine.lineStyle.color')
                }
            ),
            z2: 2,
            silent: true
620
        });
S
sushuang 已提交
621 622 623
        axisBuilder.group.add(tickEl);
        tickEls.push(tickEl);
    }
S
sushuang 已提交
624

S
sushuang 已提交
625 626
    return tickEls;
}
S
sushuang 已提交
627

S
sushuang 已提交
628 629 630
function buildAxisLabel(axisBuilder, axisModel, opt) {
    var axis = axisModel.axis;
    var show = retrieve(opt.axisLabelShow, axisModel.get('axisLabel.show'));
S
sushuang 已提交
631

S
sushuang 已提交
632 633 634
    if (!show || axis.scale.isBlank()) {
        return;
    }
S
sushuang 已提交
635

S
sushuang 已提交
636 637
    var labelModel = axisModel.getModel('axisLabel');
    var labelMargin = labelModel.get('margin');
638
    var labels = axis.getViewLabels();
S
sushuang 已提交
639

S
sushuang 已提交
640 641 642 643
    // Special label rotate.
    var labelRotation = (
        retrieve(opt.labelRotate, labelModel.get('rotate')) || 0
    ) * PI / 180;
S
sushuang 已提交
644

S
sushuang 已提交
645
    var labelLayout = innerTextLayout(opt.rotation, labelRotation, opt.labelDirection);
646
    var rawCategoryData = axisModel.getCategories(true);
S
sushuang 已提交
647

S
sushuang 已提交
648
    var labelEls = [];
649
    var silent = isLabelSilent(axisModel);
S
sushuang 已提交
650
    var triggerEvent = axisModel.get('triggerEvent');
S
sushuang 已提交
651

652 653 654 655
    each(labels, function (labelItem, index) {
        var tickValue = labelItem.tickValue;
        var formattedLabel = labelItem.formattedLabel;
        var rawLabel = labelItem.rawLabel;
S
sushuang 已提交
656

S
sushuang 已提交
657
        var itemLabelModel = labelModel;
658
        if (rawCategoryData && rawCategoryData[tickValue] && rawCategoryData[tickValue].textStyle) {
S
sushuang 已提交
659
            itemLabelModel = new Model(
660
                rawCategoryData[tickValue].textStyle, labelModel, axisModel.ecModel
S
sushuang 已提交
661 662
            );
        }
S
sushuang 已提交
663

S
sushuang 已提交
664 665 666
        var textColor = itemLabelModel.getTextColor()
            || axisModel.get('axisLine.lineStyle.color');

667
        var tickCoord = axis.dataToCoord(tickValue);
S
sushuang 已提交
668 669 670 671 672 673 674
        var pos = [
            tickCoord,
            opt.labelOffset + opt.labelDirection * labelMargin
        ];

        var textEl = new graphic.Text({
            // Id for animation
675
            anid: 'label_' + tickValue,
S
sushuang 已提交
676 677 678 679 680
            position: pos,
            rotation: labelLayout.rotation,
            silent: silent,
            z2: 10
        });
S
sushuang 已提交
681

S
sushuang 已提交
682
        graphic.setTextStyle(textEl.style, itemLabelModel, {
683
            text: formattedLabel,
S
sushuang 已提交
684 685 686 687 688 689 690 691 692 693
            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.
694 695 696
                    // (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 已提交
697
                    // it as 'string' to avoid error in replacing.
698 699 700 701 702
                    axis.type === 'category'
                        ? rawLabel
                        : axis.type === 'value'
                        ? tickValue + ''
                        : tickValue,
S
sushuang 已提交
703 704 705
                    index
                )
                : textColor
S
sushuang 已提交
706 707
        });

S
sushuang 已提交
708 709 710 711
        // Pack data for mouse event
        if (triggerEvent) {
            textEl.eventData = makeAxisEventDataBase(axisModel);
            textEl.eventData.targetType = 'axisLabel';
712
            textEl.eventData.value = rawLabel;
S
sushuang 已提交
713 714 715 716 717 718 719 720 721 722 723 724
        }

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

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

        textEl.decomposeTransform();

    });
S
sushuang 已提交
725

S
sushuang 已提交
726 727
    return labelEls;
}
S
sushuang 已提交
728

P
pah100 已提交
729

S
sushuang 已提交
730
export default AxisBuilder;