1/* * 2 * 3 * (c) 2010-2024 Torstein Honsi 4 * 5 * License: www.highcharts.com/license 6 * 7 * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! 8 * 9 * */ 10'use strict'; 11import F from '../Templating.js'; 12import H from '../Globals.js'; 13const { deg2rad } = H; 14import U from '../Utilities.js'; 15const { clamp, correctFloat, defined, destroyObjectProperties, extend, fireEvent, getAlignFactor, isNumber, merge, objectEach, pick } = U; 16/* * 17 * 18 * Class 19 * 20 * */ 21/* eslint-disable no-invalid-this, valid-jsdoc */ 22/** 23 * The Tick class. 24 * 25 * @class 26 * @name Highcharts.Tick 27 * 28 * @param {Highcharts.Axis} axis 29 * The axis of the tick. 30 * 31 * @param {number} pos 32 * The position of the tick on the axis in terms of axis values. 33 * 34 * @param {string} [type] 35 * The type of tick, either 'minor' or an empty string 36 * 37 * @param {boolean} [noLabel=false] 38 * Whether to disable the label or not. Defaults to false. 39 * 40 * @param {Object} [parameters] 41 * Optional parameters for the tick. 42 */ 43class Tick { 44 /* * 45 * 46 * Constructors 47 * 48 * */ 49 constructor(axis, pos, type, noLabel, parameters) { 50 this.isNew = true; 51 this.isNewLabel = true; 52 /** 53 * The related axis of the tick. 54 * @name Highcharts.Tick#axis 55 * @type {Highcharts.Axis} 56 */ 57 this.axis = axis; 58 /** 59 * The logical position of the tick on the axis in terms of axis values. 60 * @name Highcharts.Tick#pos 61 * @type {number} 62 */ 63 this.pos = pos; 64 /** 65 * The tick type, which can be `"minor"`, or an empty string. 66 * @name Highcharts.Tick#type 67 * @type {string} 68 */ 69 this.type = type || ''; 70 this.parameters = parameters || {}; 71 /** 72 * The mark offset of the tick on the axis. Usually `undefined`, numeric 73 * for grid axes. 74 * @name Highcharts.Tick#tickmarkOffset 75 * @type {number|undefined} 76 */ 77 this.tickmarkOffset = this.parameters.tickmarkOffset; 78 this.options = this.parameters.options; 79 fireEvent(this, 'init'); 80 if (!type && !noLabel) { 81 this.addLabel(); 82 } 83 } 84 /* * 85 * 86 * Functions 87 * 88 * */ 89 /** 90 * Write the tick label. 91 * 92 * @private 93 * @function Highcharts.Tick#addLabel 94 */ 95 addLabel() { 96 const tick = this, axis = tick.axis, options = axis.options, chart = axis.chart, categories = axis.categories, log = axis.logarithmic, names = axis.names, pos = tick.pos, labelOptions = pick(tick.options && tick.options.labels, options.labels), tickPositions = axis.tickPositions, isFirst = pos === tickPositions[0], isLast = pos === tickPositions[tickPositions.length - 1], animateLabels = (!labelOptions.step || labelOptions.step === 1) && 97 axis.tickInterval === 1, tickPositionInfo = tickPositions.info; 98 let label = tick.label, dateTimeLabelFormat, dateTimeLabelFormats, i; 99 // The context value 100 let value = this.parameters.category || (categories ? 101 pick(categories[pos], names[pos], pos) : 102 pos); 103 if (log && isNumber(value)) { 104 value = correctFloat(log.lin2log(value)); 105 } 106 // Set the datetime label format. If a higher rank is set for this 107 // position, use that. If not, use the general format. 108 if (axis.dateTime) { 109 if (tickPositionInfo) { 110 dateTimeLabelFormats = chart.time.resolveDTLFormat(options.dateTimeLabelFormats[(!options.grid && 111 tickPositionInfo.higherRanks[pos]) || 112 tickPositionInfo.unitName]); 113 dateTimeLabelFormat = dateTimeLabelFormats.main; 114 } 115 else if (isNumber(value)) { // #1441 116 dateTimeLabelFormat = axis.dateTime.getXDateFormat(value, options.dateTimeLabelFormats || 117 {}); 118 } 119 } 120 // Set properties for access in render method 121 /** 122 * True if the tick is the first one on the axis. 123 * @name Highcharts.Tick#isFirst 124 * @readonly 125 * @type {boolean|undefined} 126 */ 127 tick.isFirst = isFirst; 128 /** 129 * True if the tick is the last one on the axis. 130 * @name Highcharts.Tick#isLast 131 * @readonly 132 * @type {boolean|undefined} 133 */ 134 tick.isLast = isLast; 135 // Get the string 136 const ctx = { 137 axis, 138 chart, 139 dateTimeLabelFormat: dateTimeLabelFormat, 140 isFirst, 141 isLast, 142 pos, 143 tick: tick, 144 tickPositionInfo, 145 value 146 }; 147 // Fire an event that allows modifying the context for use in 148 // `labels.format` and `labels.formatter`. 149 fireEvent(this, 'labelFormat', ctx); 150 // Label formatting. When `labels.format` is given, we first run the 151 // defaultFormatter and append the result to the context as `text`. 152 // Handy for adding prefix or suffix while keeping default number 153 // formatting. 154 const labelFormatter = (ctx) => { 155 if (labelOptions.formatter) { 156 return labelOptions.formatter.call(ctx, ctx); 157 } 158 if (labelOptions.format) { 159 ctx.text = axis.defaultLabelFormatter.call(ctx); 160 return F.format(labelOptions.format, ctx, chart); 161 } 162 return axis.defaultLabelFormatter.call(ctx); 163 }; 164 const str = labelFormatter.call(ctx, ctx); 165 // Set up conditional formatting based on the format list if existing. 166 const list = dateTimeLabelFormats && dateTimeLabelFormats.list; 167 if (list) { 168 tick.shortenLabel = function () { 169 for (i = 0; i < list.length; i++) { 170 extend(ctx, { dateTimeLabelFormat: list[i] }); 171 label.attr({ 172 text: labelFormatter.call(ctx, ctx) 173 }); 174 if (label.getBBox().width < 175 axis.getSlotWidth(tick) - 2 * 176 (labelOptions.padding || 0)) { 177 return; 178 } 179 } 180 label.attr({ 181 text: '' 182 }); 183 }; 184 } 185 else { 186 // #15692 187 tick.shortenLabel = void 0; 188 } 189 // Call only after first render 190 if (animateLabels && axis._addedPlotLB) { 191 tick.moveLabel(str, labelOptions); 192 } 193 // First call 194 if (!defined(label) && !tick.movedLabel) { 195 /** 196 * The rendered text label of the tick. 197 * @name Highcharts.Tick#label 198 * @type {Highcharts.SVGElement|undefined} 199 */ 200 tick.label = label = tick.createLabel(str, labelOptions); 201 // Base value to detect change for new calls to getBBox 202 tick.rotation = 0; 203 // Update 204 }
205 else if (label && label.textStr !== str && !animateLabels) { 206 // When resetting text, also reset the width if dynamically set 207 // (#8809) 208 if (label.textWidth && 209 !labelOptions.style.width && 210 !label.styles.width) { 211 label.css({ width: null }); 212 } 213 label.attr({ text: str }); 214 label.textPxLength = label.getBBox().width; 215 } 216 } 217 /** 218 * Render and return the label of the tick. 219 * 220 * @private 221 * @function Highcharts.Tick#createLabel 222 */ 223 createLabel(str, labelOptions, xy) { 224 const axis = this.axis, { renderer, styledMode } = axis.chart, label = defined(str) && labelOptions.enabled ? 225 renderer 226 .text(str, xy?.x, xy?.y, labelOptions.useHTML) 227 .add(axis.labelGroup) : 228 void 0; 229 // Un-rotated length 230 if (label) { 231 const whiteSpace = labelOptions.style.whiteSpace || 'normal'; 232 // Without position absolute, IE export sometimes is wrong 233 if (!styledMode) { 234 label.css(merge(labelOptions.style, { whiteSpace: 'nowrap' })); 235 } 236 label.textPxLength = label.getBBox().width; 237 if (!styledMode) { 238 label.css({ whiteSpace }); 239 } 240 } 241 return label; 242 } 243 /** 244 * Destructor for the tick prototype 245 * 246 * @private 247 * @function Highcharts.Tick#destroy 248 */ 249 destroy() { 250 destroyObjectProperties(this, this.axis); 251 } 252 /** 253 * Gets the x and y positions for ticks in terms of pixels. 254 * 255 * @private 256 * @function Highcharts.Tick#getPosition 257 * 258 * @param {boolean} horiz 259 * Whether the tick is on an horizontal axis or not. 260 * 261 * @param {number} tickPos 262 * Position of the tick. 263 * 264 * @param {number} tickmarkOffset 265 * Tickmark offset for all ticks. 266 * 267 * @param {boolean} [old] 268 * Whether the axis has changed or not. 269 * 270 * @return {Highcharts.PositionObject} 271 * The tick position. 272 * 273 * @emits Highcharts.Tick#event:afterGetPosition 274 */ 275 getPosition(horiz, tickPos, tickmarkOffset, old) { 276 const axis = this.axis, chart = axis.chart, cHeight = (old && chart.oldChartHeight) || chart.chartHeight, pos = { 277 x: horiz ? 278 correctFloat(axis.translate(tickPos + tickmarkOffset, void 0, void 0, old) + 279 axis.transB) : 280 (axis.left + 281 axis.offset + 282 (axis.opposite ? 283 (((old && chart.oldChartWidth) || 284 chart.chartWidth) - 285 axis.right - 286 axis.left) : 287 0)), 288 y: horiz ? 289 (cHeight - 290 axis.bottom + 291 axis.offset - 292 (axis.opposite ? axis.height : 0)) : 293 correctFloat(cHeight - 294 axis.translate(tickPos + tickmarkOffset, void 0, void 0, old) - 295 axis.transB) 296 }; 297 // Chrome workaround for #10516 298 pos.y = clamp(pos.y, -1e9, 1e9); 299 fireEvent(this, 'afterGetPosition', { pos: pos }); 300 return pos; 301 } 302 /** 303 * Get the x, y position of the tick label 304 * @private 305 */ 306 getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { 307 const axis = this.axis, transA = axis.transA, reversed = ( // #7911 308 axis.isLinked && axis.linkedParent ? 309 axis.linkedParent.reversed : 310 axis.reversed), staggerLines = axis.staggerLines, rotCorr = axis.tickRotCorr || { x: 0, y: 0 }, 311 // Adjust for label alignment if we use reserveSpace: true (#5286) 312 labelOffsetCorrection = (!horiz && !axis.reserveSpaceDefault ? 313 -axis.labelOffset * (axis.labelAlign === 'center' ? 0.5 : 1) : 314 0), distance = labelOptions.distance, pos = {}; 315 let yOffset, line; 316 if (axis.side === 0) { 317 yOffset = label.rotation ? -distance : -label.getBBox().height; 318 } 319 else if (axis.side === 2) { 320 yOffset = rotCorr.y + distance; 321 } 322 else { 323 // #3140, #3140
324 yOffset = Math.cos(label.rotation * deg2rad) * 325 (rotCorr.y - label.getBBox(false, 0).height / 2); 326 } 327 if (defined(labelOptions.y)) { 328 yOffset = axis.side === 0 && axis.horiz ? 329 labelOptions.y + yOffset : 330 labelOptions.y; 331 } 332 x = x + 333 pick(labelOptions.x, [0, 1, 0, -1][axis.side] * distance) + 334 labelOffsetCorrection + 335 rotCorr.x - 336 (tickmarkOffset && horiz ? 337 tickmarkOffset * transA * (reversed ? -1 : 1) : 338 0); 339 y = y + yOffset - (tickmarkOffset && !horiz ? 340 tickmarkOffset * transA * (reversed ? 1 : -1) : 0); 341 // Correct for staggered labels 342 if (staggerLines) { 343 line = (index / (step || 1) % staggerLines); 344 if (axis.opposite) { 345 line = staggerLines - line - 1; 346 } 347 y += line * (axis.labelOffset / staggerLines); 348 } 349 pos.x = x; 350 pos.y = Math.round(y); 351 fireEvent(this, 'afterGetLabelPosition', { pos: pos, tickmarkOffset: tickmarkOffset, index: index }); 352 return pos; 353 } 354 /** 355 * Get the offset height or width of the label 356 * 357 * @private 358 * @function Highcharts.Tick#getLabelSize 359 */ 360 getLabelSize() { 361 return this.label ? 362 this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] : 363 0; 364 } 365 /** 366 * Extendible method to return the path of the marker 367 * @private 368 */ 369 getMarkPath(x, y, tickLength, tickWidth, horiz = false, renderer) { 370 return renderer.crispLine([[ 371 'M', 372 x, 373 y 374 ], [ 375 'L', 376 x + (horiz ? 0 : -tickLength), 377 y + (horiz ? tickLength : 0) 378 ]], tickWidth); 379 } 380 /** 381 * Handle the label overflow by adjusting the labels to the left and right 382 * edge, or hide them if they collide into the neighbour label. 383 * 384 * @private 385 * @function Highcharts.Tick#handleOverflow 386 */ 387 handleOverflow(xy) { 388 const tick = this, axis = this.axis, labelOptions = axis.options.labels, pxPos = xy.x, chartWidth = axis.chart.chartWidth, spacing = axis.chart.spacing, leftBound = pick(axis.labelLeft, Math.min(axis.pos, spacing[3])), rightBound = pick(axis.labelRight, Math.max(!axis.isRadial ? axis.pos + axis.len : 0, chartWidth - spacing[1])), label = this.label, rotation = this.rotation, factor = getAlignFactor(axis.labelAlign || label.attr('align')), labelWidth = label.getBBox().width, slotWidth = axis.getSlotWidth(tick), xCorrection = factor, css = {}; 389 let modifiedSlotWidth = slotWidth, goRight = 1, leftPos, rightPos, textWidth; 390 // Check if the label overshoots the chart spacing box. If it does, move 391 // it. If it now overshoots the slotWidth, add ellipsis. 392 if (!rotation && labelOptions.overflow === 'justify') { 393 leftPos = pxPos - factor * labelWidth; 394 rightPos = pxPos + (1 - factor) * labelWidth; 395 if (leftPos < leftBound) { 396 modifiedSlotWidth = 397 xy.x + modifiedSlotWidth * (1 - factor) - leftBound; 398 } 399 else if (rightPos > rightBound) { 400 modifiedSlotWidth = 401 rightBound - xy.x + modifiedSlotWidth * factor; 402 goRight = -1; 403 } 404 modifiedSlotWidth = Math.min(slotWidth, modifiedSlotWidth); // #4177 405 if (modifiedSlotWidth < slotWidth && axis.labelAlign === 'center') { 406 xy.x += (goRight * 407 (slotWidth - 408 modifiedSlotWidth - 409 xCorrection * (slotWidth - Math.min(labelWidth, modifiedSlotWidth)))); 410 } 411 // If the label width exceeds the available space, set a text width 412 // to be picked up below. Also, if a width has been set before, we 413 // need to set a new one because the reported labelWidth will be 414 // limited by the box (#3938). 415 if (labelWidth > modifiedSlotWidth || 416 (axis.autoRotation && (label.styles || {}).width)) { 417 textWidth = modifiedSlotWidth; 418 } 419 // Add ellipsis to prevent rotated labels to be clipped against the edge 420 // of the chart 421 } 422 else if (rotation < 0 && 423 pxPos - factor * labelWidth < leftBound) { 424 textWidth = Math.round(pxPos / Math.cos(rotation * deg2rad) - leftBound); 425 } 426 else if (rotation > 0 && 427 pxPos + factor * labelWidth > rightBound) { 428 textWidth = Math.round((chartWidth - pxPos) / 429 Math.cos(rotation * deg2rad)); 430 } 431 if (textWidth && label) { 432 if (tick.shortenLabel) { 433 tick.shortenLabel(); 434 } 435 else { 436 label.css(extend(css, { 437 width: Math.floor(textWidth) + 'px', 438 lineClamp: axis.isRadial ? 0 : 1 439 })); 440 } 441 } 442 } 443 /** 444 * Try to replace the label if the same one already exists. 445 * 446 * @private 447 * @function Highcharts.Tick#moveLabel 448 */ 449 moveLabel(str, labelOptions) { 450 const tick = this, label = tick.label, axis = tick.axis; 451 let moved = false, labelPos; 452 if (label && label.textStr === str) { 453 tick.movedLabel = label; 454 moved = true; 455 delete tick.label; 456 } 457 else { // Find a label with the same string 458 objectEach(axis.ticks, function (currentTick) { 459 if (!moved && 460 !currentTick.isNew && 461 currentTick !== tick && 462 currentTick.label && 463 currentTick.label.textStr === str) { 464 tick.movedLabel = currentTick.label; 465 moved = true; 466 currentTick.labelPos = tick.movedLabel.xy; 467 delete currentTick.label; 468 } 469 }); 470 } 471 // Create new label if the actual one is moved 472 if (!moved && (tick.labelPos || label)) { 473 labelPos = tick.labelPos || label.xy; 474 tick.movedLabel = tick.createLabel(str, labelOptions, labelPos); 475 if (tick.movedLabel) { 476 tick.movedLabel.attr({ opacity: 0 }); 477 } 478 } 479 } 480 /** 481 * Put everything in place 482 * 483 * @private 484 * @param {number} index 485 * 486 * @param {boolean} [old] 487 * Use old coordinates to prepare an animation into new position 488 * 489 * @param {number} [opacity] 490 */ 491 render(index, old, opacity) { 492 const tick = this, axis = tick.axis, horiz = axis.horiz, pos = tick.pos, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), xy = tick.getPosition(horiz, pos, tickmarkOffset, old), x = xy.x, y = xy.y, axisStart = axis.pos, axisEnd = axisStart + axis.len, pxPos = horiz ? x : y; 493 // Anything that is not between `axis.pos` and `axis.pos + axis.length` 494 // should not be visible (#20166). The `correctFloat` is for reversed 495 // axes in Safari. 496 if (!axis.chart.polar && 497 tick.isNew && 498 (correctFloat(pxPos) < axisStart || pxPos > axisEnd)) { 499 opacity = 0; 500 } 501 const labelOpacity = pick(opacity, tick.label && tick.label.newOpacity, // #15528 502 1); 503 opacity = pick(opacity, 1); 504 this.isActive = true; 505 // Create the grid line 506 this.renderGridLine(old, opacity); 507 // Create the tick mark 508 this.renderMark(xy, opacity); 509 // The label is created on init - now move it into place 510 this.renderLabel(xy, old, labelOpacity, index); 511 tick.isNew = false;
512 fireEvent(this, 'afterRender'); 513 } 514 /** 515 * Renders the gridLine. 516 * 517 * @private 518 * @function Highcharts.Tick#renderGridLine 519 * @param {boolean} old Whether or not the tick is old 520 * @param {number} opacity The opacity of the grid line 521 */ 522 renderGridLine(old, opacity) { 523 const tick = this, axis = tick.axis, options = axis.options, attribs = {}, pos = tick.pos, type = tick.type, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), renderer = axis.chart.renderer; 524 let gridLine = tick.gridLine, gridLinePath, gridLineWidth = options.gridLineWidth, gridLineColor = options.gridLineColor, dashStyle = options.gridLineDashStyle; 525 if (tick.type === 'minor') { 526 gridLineWidth = options.minorGridLineWidth; 527 gridLineColor = options.minorGridLineColor; 528 dashStyle = options.minorGridLineDashStyle; 529 } 530 if (!gridLine) { 531 if (!axis.chart.styledMode) { 532 attribs.stroke = gridLineColor; 533 attribs['stroke-width'] = gridLineWidth || 0; 534 attribs.dashstyle = dashStyle; 535 } 536 if (!type) { 537 attribs.zIndex = 1; 538 } 539 if (old) { 540 opacity = 0; 541 } 542 /** 543 * The rendered grid line of the tick. 544 * @name Highcharts.Tick#gridLine 545 * @type {Highcharts.SVGElement|undefined} 546 */ 547 tick.gridLine = gridLine = renderer.path() 548 .attr(attribs) 549 .addClass('highcharts-' + (type ? type + '-' : '') + 'grid-line') 550 .add(axis.gridGroup); 551 } 552 if (gridLine) { 553 gridLinePath = axis.getPlotLinePath({ 554 value: pos + tickmarkOffset, 555 lineWidth: gridLine.strokeWidth(), 556 force: 'pass', 557 old: old, 558 acrossPanes: false // #18025 559 }); 560 // If the parameter 'old' is set, the current call will be followed 561 // by another call, therefore do not do any animations this time 562 if (gridLinePath) { 563 gridLine[old || tick.isNew ? 'attr' : 'animate']({ 564 d: gridLinePath, 565 opacity: opacity 566 }); 567 } 568 } 569 } 570 /** 571 * Renders the tick mark. 572 * 573 * @private 574 * @function Highcharts.Tick#renderMark 575 * @param {Highcharts.PositionObject} xy The position vector of the mark 576 * @param {number} opacity The opacity of the mark 577 */ 578 renderMark(xy, opacity) { 579 const tick = this, axis = tick.axis, options = axis.options, renderer = axis.chart.renderer, type = tick.type, tickSize = axis.tickSize(type ? type + 'Tick' : 'tick'), x = xy.x, y = xy.y, tickWidth = pick(options[type !== 'minor' ? 'tickWidth' : 'minorTickWidth'], !type && axis.isXAxis ? 1 : 0), // X axis defaults to 1 580 tickColor = options[type !== 'minor' ? 'tickColor' : 'minorTickColor']; 581 let mark = tick.mark; 582 const isNewMark = !mark; 583 if (tickSize) { 584 // Negate the length 585 if (axis.opposite) { 586 tickSize[0] = -tickSize[0]; 587 } 588 // First time, create it 589 if (!mark) { 590 /** 591 * The rendered mark of the tick. 592 * @name Highcharts.Tick#mark 593 * @type {Highcharts.SVGElement|undefined} 594 */ 595 tick.mark = mark = renderer.path() 596 .addClass('highcharts-' + (type ? type + '-' : '') + 'tick') 597 .add(axis.axisGroup); 598 if (!axis.chart.styledMode) { 599 mark.attr({ 600 stroke: tickColor, 601 'stroke-width': tickWidth 602 }); 603 } 604 } 605 mark[isNewMark ? 'attr' : 'animate']({ 606 d: tick.getMarkPath(x, y, tickSize[0], mark.strokeWidth(), axis.horiz, renderer), 607 opacity: opacity 608 }); 609 } 610 } 611 /**
612 * Renders the tick label. 613 * Note: The label should already be created in init(), so it should only 614 * have to be moved into place. 615 * 616 * @private 617 * @function Highcharts.Tick#renderLabel 618 * @param {Highcharts.PositionObject} xy The position vector of the label 619 * @param {boolean} old Whether or not the tick is old 620 * @param {number} opacity The opacity of the label 621 * @param {number} index The index of the tick 622 */ 623 renderLabel(xy, old, opacity, index) { 624 const tick = this, axis = tick.axis, horiz = axis.horiz, options = axis.options, label = tick.label, labelOptions = options.labels, step = labelOptions.step, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), x = xy.x, y = xy.y; 625 let show = true; 626 if (label && isNumber(x)) { 627 label.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step); 628 // Apply show first and show last. If the tick is both first and 629 // last, it is a single centered tick, in which case we show the 630 // label anyway (#2100). 631 if ((tick.isFirst && 632 !tick.isLast && 633 !options.showFirstLabel) || 634 (tick.isLast && 635 !tick.isFirst && 636 !options.showLastLabel)) { 637 show = false; 638 // Handle label overflow and show or hide accordingly 639 } 640 else if (horiz && 641 !labelOptions.step && 642 !labelOptions.rotation && 643 !old && 644 opacity !== 0) { 645 tick.handleOverflow(xy); 646 } 647 // Apply step 648 if (step && index % step) { 649 // Show those indices dividable by step 650 show = false; 651 } 652 // Set the new position, and show or hide 653 if (show && isNumber(xy.y)) { 654 xy.opacity = opacity; 655 label[tick.isNewLabel ? 'attr' : 'animate'](xy).show(true); 656 tick.isNewLabel = false; 657 } 658 else { 659 label.hide(); // #1338, #15863 660 tick.isNewLabel = true; 661 } 662 } 663 } 664 /** 665 * Replace labels with the moved ones to perform animation. Additionally 666 * destroy unused labels. 667 * 668 * @private 669 * @function Highcharts.Tick#replaceMovedLabel 670 */ 671 replaceMovedLabel() { 672 const tick = this, label = tick.label, axis = tick.axis; 673 // Animate and destroy 674 if (label && !tick.isNew) { 675 label.animate({ opacity: 0 }, void 0, label.destroy); 676 delete tick.label; 677 } 678 axis.isDirty = true; 679 tick.label = tick.movedLabel; 680 delete tick.movedLabel; 681 } 682} 683/* * 684 * 685 * Default Export 686 * 687 * */ 688export default Tick; 689/* * 690 * 691 * API Declarations 692 * 693 * */ 694/** 695 * Optional parameters for the tick. 696 * @private 697 * @interface Highcharts.TickParametersObject 698 */ /** 699* Set category for the tick. 700* @name Highcharts.TickParametersObject#category 701* @type {string|undefined} 702*/ /** 703* @name Highcharts.TickParametersObject#options 704* @type {Highcharts.Dictionary<any>|undefined} 705*/ /** 706* Set tickmarkOffset for the tick. 707* @name Highcharts.TickParametersObject#tickmarkOffset 708* @type {number|undefined} 709*/ 710/** 711 * Additional time tick information. 712 * 713 * @interface Highcharts.TimeTicksInfoObject 714 * @extends Highcharts.TimeNormalizedObject 715 */ /** 716* @name Highcharts.TimeTicksInfoObject#higherRanks 717* @type {Array<string>} 718*/ /** 719* @name Highcharts.TimeTicksInfoObject#totalRange 720* @type {number} 721*/ 722(''); // Keeps doclets above in JS file
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.