| 
/* 
 | 
* 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. 
 | 
*/ 
 | 
  
 | 
  
 | 
/** 
 | 
 * AUTO-GENERATED FILE. DO NOT MODIFY. 
 | 
 */ 
 | 
  
 | 
/* 
 | 
* 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. 
 | 
*/ 
 | 
import { __extends } from "tslib"; 
 | 
// FIXME step not support polar 
 | 
import * as zrUtil from 'zrender/lib/core/util.js'; 
 | 
import SymbolDraw from '../helper/SymbolDraw.js'; 
 | 
import SymbolClz from '../helper/Symbol.js'; 
 | 
import lineAnimationDiff from './lineAnimationDiff.js'; 
 | 
import * as graphic from '../../util/graphic.js'; 
 | 
import * as modelUtil from '../../util/model.js'; 
 | 
import { ECPolyline, ECPolygon } from './poly.js'; 
 | 
import ChartView from '../../view/Chart.js'; 
 | 
import { prepareDataCoordInfo, getStackedOnPoint } from './helper.js'; 
 | 
import { createGridClipPath, createPolarClipPath } from '../helper/createClipPathFromCoordSys.js'; 
 | 
import { isCoordinateSystemType } from '../../coord/CoordinateSystem.js'; 
 | 
import { setStatesStylesFromModel, setStatesFlag, toggleHoverEmphasis, SPECIAL_STATES } from '../../util/states.js'; 
 | 
import { setLabelStyle, getLabelStatesModels, labelInner } from '../../label/labelStyle.js'; 
 | 
import { getDefaultLabel, getDefaultInterpolatedLabel } from '../helper/labelHelper.js'; 
 | 
import { getECData } from '../../util/innerStore.js'; 
 | 
import { createFloat32Array } from '../../util/vendor.js'; 
 | 
import { convertToColorString } from '../../util/format.js'; 
 | 
import { lerp } from 'zrender/lib/tool/color.js'; 
 | 
function isPointsSame(points1, points2) { 
 | 
  if (points1.length !== points2.length) { 
 | 
    return; 
 | 
  } 
 | 
  for (var i = 0; i < points1.length; i++) { 
 | 
    if (points1[i] !== points2[i]) { 
 | 
      return; 
 | 
    } 
 | 
  } 
 | 
  return true; 
 | 
} 
 | 
function bboxFromPoints(points) { 
 | 
  var minX = Infinity; 
 | 
  var minY = Infinity; 
 | 
  var maxX = -Infinity; 
 | 
  var maxY = -Infinity; 
 | 
  for (var i = 0; i < points.length;) { 
 | 
    var x = points[i++]; 
 | 
    var y = points[i++]; 
 | 
    if (!isNaN(x)) { 
 | 
      minX = Math.min(x, minX); 
 | 
      maxX = Math.max(x, maxX); 
 | 
    } 
 | 
    if (!isNaN(y)) { 
 | 
      minY = Math.min(y, minY); 
 | 
      maxY = Math.max(y, maxY); 
 | 
    } 
 | 
  } 
 | 
  return [[minX, minY], [maxX, maxY]]; 
 | 
} 
 | 
function getBoundingDiff(points1, points2) { 
 | 
  var _a = bboxFromPoints(points1), 
 | 
    min1 = _a[0], 
 | 
    max1 = _a[1]; 
 | 
  var _b = bboxFromPoints(points2), 
 | 
    min2 = _b[0], 
 | 
    max2 = _b[1]; 
 | 
  // Get a max value from each corner of two boundings. 
 | 
  return Math.max(Math.abs(min1[0] - min2[0]), Math.abs(min1[1] - min2[1]), Math.abs(max1[0] - max2[0]), Math.abs(max1[1] - max2[1])); 
 | 
} 
 | 
function getSmooth(smooth) { 
 | 
  return zrUtil.isNumber(smooth) ? smooth : smooth ? 0.5 : 0; 
 | 
} 
 | 
function getStackedOnPoints(coordSys, data, dataCoordInfo) { 
 | 
  if (!dataCoordInfo.valueDim) { 
 | 
    return []; 
 | 
  } 
 | 
  var len = data.count(); 
 | 
  var points = createFloat32Array(len * 2); 
 | 
  for (var idx = 0; idx < len; idx++) { 
 | 
    var pt = getStackedOnPoint(dataCoordInfo, coordSys, data, idx); 
 | 
    points[idx * 2] = pt[0]; 
 | 
    points[idx * 2 + 1] = pt[1]; 
 | 
  } 
 | 
  return points; 
 | 
} 
 | 
/** 
 | 
 * Filter the null data and extend data for step considering `stepTurnAt` 
 | 
 * 
 | 
 * @param points data to convert, that may containing null 
 | 
 * @param basePoints base data to reference, used only for areaStyle points 
 | 
 * @param coordSys coordinate system 
 | 
 * @param stepTurnAt 'start' | 'end' | 'middle' | true 
 | 
 * @param connectNulls whether to connect nulls 
 | 
 * @returns converted point positions 
 | 
 */ 
 | 
function turnPointsIntoStep(points, basePoints, coordSys, stepTurnAt, connectNulls) { 
 | 
  var baseAxis = coordSys.getBaseAxis(); 
 | 
  var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1; 
 | 
  var stepPoints = []; 
 | 
  var i = 0; 
 | 
  var stepPt = []; 
 | 
  var pt = []; 
 | 
  var nextPt = []; 
 | 
  var filteredPoints = []; 
 | 
  if (connectNulls) { 
 | 
    for (i = 0; i < points.length; i += 2) { 
 | 
      /** 
 | 
       * For areaStyle of stepped lines, `stackedOnPoints` should be 
 | 
       * filtered the same as `points` so that the base axis values 
 | 
       * should stay the same as the lines above. See #20021 
 | 
       */ 
 | 
      var reference = basePoints || points; 
 | 
      if (!isNaN(reference[i]) && !isNaN(reference[i + 1])) { 
 | 
        filteredPoints.push(points[i], points[i + 1]); 
 | 
      } 
 | 
    } 
 | 
    points = filteredPoints; 
 | 
  } 
 | 
  for (i = 0; i < points.length - 2; i += 2) { 
 | 
    nextPt[0] = points[i + 2]; 
 | 
    nextPt[1] = points[i + 3]; 
 | 
    pt[0] = points[i]; 
 | 
    pt[1] = points[i + 1]; 
 | 
    stepPoints.push(pt[0], pt[1]); 
 | 
    switch (stepTurnAt) { 
 | 
      case 'end': 
 | 
        stepPt[baseIndex] = nextPt[baseIndex]; 
 | 
        stepPt[1 - baseIndex] = pt[1 - baseIndex]; 
 | 
        stepPoints.push(stepPt[0], stepPt[1]); 
 | 
        break; 
 | 
      case 'middle': 
 | 
        var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2; 
 | 
        var stepPt2 = []; 
 | 
        stepPt[baseIndex] = stepPt2[baseIndex] = middle; 
 | 
        stepPt[1 - baseIndex] = pt[1 - baseIndex]; 
 | 
        stepPt2[1 - baseIndex] = nextPt[1 - baseIndex]; 
 | 
        stepPoints.push(stepPt[0], stepPt[1]); 
 | 
        stepPoints.push(stepPt2[0], stepPt2[1]); 
 | 
        break; 
 | 
      default: 
 | 
        // default is start 
 | 
        stepPt[baseIndex] = pt[baseIndex]; 
 | 
        stepPt[1 - baseIndex] = nextPt[1 - baseIndex]; 
 | 
        stepPoints.push(stepPt[0], stepPt[1]); 
 | 
    } 
 | 
  } 
 | 
  // Last points 
 | 
  stepPoints.push(points[i++], points[i++]); 
 | 
  return stepPoints; 
 | 
} 
 | 
/** 
 | 
 * Clip color stops to edge. Avoid creating too large gradients. 
 | 
 * Which may lead to blurry when GPU acceleration is enabled. See #15680 
 | 
 * 
 | 
 * The stops has been sorted from small to large. 
 | 
 */ 
 | 
function clipColorStops(colorStops, maxSize) { 
 | 
  var newColorStops = []; 
 | 
  var len = colorStops.length; 
 | 
  // coord will always < 0 in prevOutOfRangeColorStop. 
 | 
  var prevOutOfRangeColorStop; 
 | 
  var prevInRangeColorStop; 
 | 
  function lerpStop(stop0, stop1, clippedCoord) { 
 | 
    var coord0 = stop0.coord; 
 | 
    var p = (clippedCoord - coord0) / (stop1.coord - coord0); 
 | 
    var color = lerp(p, [stop0.color, stop1.color]); 
 | 
    return { 
 | 
      coord: clippedCoord, 
 | 
      color: color 
 | 
    }; 
 | 
  } 
 | 
  for (var i = 0; i < len; i++) { 
 | 
    var stop_1 = colorStops[i]; 
 | 
    var coord = stop_1.coord; 
 | 
    if (coord < 0) { 
 | 
      prevOutOfRangeColorStop = stop_1; 
 | 
    } else if (coord > maxSize) { 
 | 
      if (prevInRangeColorStop) { 
 | 
        newColorStops.push(lerpStop(prevInRangeColorStop, stop_1, maxSize)); 
 | 
      } else if (prevOutOfRangeColorStop) { 
 | 
        // If there are two stops and coord range is between these two stops 
 | 
        newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0), lerpStop(prevOutOfRangeColorStop, stop_1, maxSize)); 
 | 
      } 
 | 
      // All following stop will be out of range. So just ignore them. 
 | 
      break; 
 | 
    } else { 
 | 
      if (prevOutOfRangeColorStop) { 
 | 
        newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0)); 
 | 
        // Reset 
 | 
        prevOutOfRangeColorStop = null; 
 | 
      } 
 | 
      newColorStops.push(stop_1); 
 | 
      prevInRangeColorStop = stop_1; 
 | 
    } 
 | 
  } 
 | 
  return newColorStops; 
 | 
} 
 | 
function getVisualGradient(data, coordSys, api) { 
 | 
  var visualMetaList = data.getVisual('visualMeta'); 
 | 
  if (!visualMetaList || !visualMetaList.length || !data.count()) { 
 | 
    // When data.count() is 0, gradient range can not be calculated. 
 | 
    return; 
 | 
  } 
 | 
  if (coordSys.type !== 'cartesian2d') { 
 | 
    if (process.env.NODE_ENV !== 'production') { 
 | 
      console.warn('Visual map on line style is only supported on cartesian2d.'); 
 | 
    } 
 | 
    return; 
 | 
  } 
 | 
  var coordDim; 
 | 
  var visualMeta; 
 | 
  for (var i = visualMetaList.length - 1; i >= 0; i--) { 
 | 
    var dimInfo = data.getDimensionInfo(visualMetaList[i].dimension); 
 | 
    coordDim = dimInfo && dimInfo.coordDim; 
 | 
    // Can only be x or y 
 | 
    if (coordDim === 'x' || coordDim === 'y') { 
 | 
      visualMeta = visualMetaList[i]; 
 | 
      break; 
 | 
    } 
 | 
  } 
 | 
  if (!visualMeta) { 
 | 
    if (process.env.NODE_ENV !== 'production') { 
 | 
      console.warn('Visual map on line style only support x or y dimension.'); 
 | 
    } 
 | 
    return; 
 | 
  } 
 | 
  // If the area to be rendered is bigger than area defined by LinearGradient, 
 | 
  // the canvas spec prescribes that the color of the first stop and the last 
 | 
  // stop should be used. But if two stops are added at offset 0, in effect 
 | 
  // browsers use the color of the second stop to render area outside 
 | 
  // LinearGradient. So we can only infinitesimally extend area defined in 
 | 
  // LinearGradient to render `outerColors`. 
 | 
  var axis = coordSys.getAxis(coordDim); 
 | 
  // dataToCoord mapping may not be linear, but must be monotonic. 
 | 
  var colorStops = zrUtil.map(visualMeta.stops, function (stop) { 
 | 
    // offset will be calculated later. 
 | 
    return { 
 | 
      coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)), 
 | 
      color: stop.color 
 | 
    }; 
 | 
  }); 
 | 
  var stopLen = colorStops.length; 
 | 
  var outerColors = visualMeta.outerColors.slice(); 
 | 
  if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) { 
 | 
    colorStops.reverse(); 
 | 
    outerColors.reverse(); 
 | 
  } 
 | 
  var colorStopsInRange = clipColorStops(colorStops, coordDim === 'x' ? api.getWidth() : api.getHeight()); 
 | 
  var inRangeStopLen = colorStopsInRange.length; 
 | 
  if (!inRangeStopLen && stopLen) { 
 | 
    // All stops are out of range. All will be the same color. 
 | 
    return colorStops[0].coord < 0 ? outerColors[1] ? outerColors[1] : colorStops[stopLen - 1].color : outerColors[0] ? outerColors[0] : colorStops[0].color; 
 | 
  } 
 | 
  var tinyExtent = 10; // Arbitrary value: 10px 
 | 
  var minCoord = colorStopsInRange[0].coord - tinyExtent; 
 | 
  var maxCoord = colorStopsInRange[inRangeStopLen - 1].coord + tinyExtent; 
 | 
  var coordSpan = maxCoord - minCoord; 
 | 
  if (coordSpan < 1e-3) { 
 | 
    return 'transparent'; 
 | 
  } 
 | 
  zrUtil.each(colorStopsInRange, function (stop) { 
 | 
    stop.offset = (stop.coord - minCoord) / coordSpan; 
 | 
  }); 
 | 
  colorStopsInRange.push({ 
 | 
    // NOTE: inRangeStopLen may still be 0 if stoplen is zero. 
 | 
    offset: inRangeStopLen ? colorStopsInRange[inRangeStopLen - 1].offset : 0.5, 
 | 
    color: outerColors[1] || 'transparent' 
 | 
  }); 
 | 
  colorStopsInRange.unshift({ 
 | 
    offset: inRangeStopLen ? colorStopsInRange[0].offset : 0.5, 
 | 
    color: outerColors[0] || 'transparent' 
 | 
  }); 
 | 
  var gradient = new graphic.LinearGradient(0, 0, 0, 0, colorStopsInRange, true); 
 | 
  gradient[coordDim] = minCoord; 
 | 
  gradient[coordDim + '2'] = maxCoord; 
 | 
  return gradient; 
 | 
} 
 | 
function getIsIgnoreFunc(seriesModel, data, coordSys) { 
 | 
  var showAllSymbol = seriesModel.get('showAllSymbol'); 
 | 
  var isAuto = showAllSymbol === 'auto'; 
 | 
  if (showAllSymbol && !isAuto) { 
 | 
    return; 
 | 
  } 
 | 
  var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; 
 | 
  if (!categoryAxis) { 
 | 
    return; 
 | 
  } 
 | 
  // Note that category label interval strategy might bring some weird effect 
 | 
  // in some scenario: users may wonder why some of the symbols are not 
 | 
  // displayed. So we show all symbols as possible as we can. 
 | 
  if (isAuto 
 | 
  // Simplify the logic, do not determine label overlap here. 
 | 
  && canShowAllSymbolForCategory(categoryAxis, data)) { 
 | 
    return; 
 | 
  } 
 | 
  // Otherwise follow the label interval strategy on category axis. 
 | 
  var categoryDataDim = data.mapDimension(categoryAxis.dim); 
 | 
  var labelMap = {}; 
 | 
  zrUtil.each(categoryAxis.getViewLabels(), function (labelItem) { 
 | 
    var ordinalNumber = categoryAxis.scale.getRawOrdinalNumber(labelItem.tickValue); 
 | 
    labelMap[ordinalNumber] = 1; 
 | 
  }); 
 | 
  return function (dataIndex) { 
 | 
    return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex)); 
 | 
  }; 
 | 
} 
 | 
function canShowAllSymbolForCategory(categoryAxis, data) { 
 | 
  // In most cases, line is monotonous on category axis, and the label size 
 | 
  // is close with each other. So we check the symbol size and some of the 
 | 
  // label size alone with the category axis to estimate whether all symbol 
 | 
  // can be shown without overlap. 
 | 
  var axisExtent = categoryAxis.getExtent(); 
 | 
  var availSize = Math.abs(axisExtent[1] - axisExtent[0]) / categoryAxis.scale.count(); 
 | 
  isNaN(availSize) && (availSize = 0); // 0/0 is NaN. 
 | 
  // Sampling some points, max 5. 
 | 
  var dataLen = data.count(); 
 | 
  var step = Math.max(1, Math.round(dataLen / 5)); 
 | 
  for (var dataIndex = 0; dataIndex < dataLen; dataIndex += step) { 
 | 
    if (SymbolClz.getSymbolSize(data, dataIndex 
 | 
    // Only for cartesian, where `isHorizontal` exists. 
 | 
    )[categoryAxis.isHorizontal() ? 1 : 0] 
 | 
    // Empirical number 
 | 
    * 1.5 > availSize) { 
 | 
      return false; 
 | 
    } 
 | 
  } 
 | 
  return true; 
 | 
} 
 | 
function isPointNull(x, y) { 
 | 
  return isNaN(x) || isNaN(y); 
 | 
} 
 | 
function getLastIndexNotNull(points) { 
 | 
  var len = points.length / 2; 
 | 
  for (; len > 0; len--) { 
 | 
    if (!isPointNull(points[len * 2 - 2], points[len * 2 - 1])) { 
 | 
      break; 
 | 
    } 
 | 
  } 
 | 
  return len - 1; 
 | 
} 
 | 
function getPointAtIndex(points, idx) { 
 | 
  return [points[idx * 2], points[idx * 2 + 1]]; 
 | 
} 
 | 
function getIndexRange(points, xOrY, dim) { 
 | 
  var len = points.length / 2; 
 | 
  var dimIdx = dim === 'x' ? 0 : 1; 
 | 
  var a; 
 | 
  var b; 
 | 
  var prevIndex = 0; 
 | 
  var nextIndex = -1; 
 | 
  for (var i = 0; i < len; i++) { 
 | 
    b = points[i * 2 + dimIdx]; 
 | 
    if (isNaN(b) || isNaN(points[i * 2 + 1 - dimIdx])) { 
 | 
      continue; 
 | 
    } 
 | 
    if (i === 0) { 
 | 
      a = b; 
 | 
      continue; 
 | 
    } 
 | 
    if (a <= xOrY && b >= xOrY || a >= xOrY && b <= xOrY) { 
 | 
      nextIndex = i; 
 | 
      break; 
 | 
    } 
 | 
    prevIndex = i; 
 | 
    a = b; 
 | 
  } 
 | 
  return { 
 | 
    range: [prevIndex, nextIndex], 
 | 
    t: (xOrY - a) / (b - a) 
 | 
  }; 
 | 
} 
 | 
function anyStateShowEndLabel(seriesModel) { 
 | 
  if (seriesModel.get(['endLabel', 'show'])) { 
 | 
    return true; 
 | 
  } 
 | 
  for (var i = 0; i < SPECIAL_STATES.length; i++) { 
 | 
    if (seriesModel.get([SPECIAL_STATES[i], 'endLabel', 'show'])) { 
 | 
      return true; 
 | 
    } 
 | 
  } 
 | 
  return false; 
 | 
} 
 | 
function createLineClipPath(lineView, coordSys, hasAnimation, seriesModel) { 
 | 
  if (isCoordinateSystemType(coordSys, 'cartesian2d')) { 
 | 
    var endLabelModel_1 = seriesModel.getModel('endLabel'); 
 | 
    var valueAnimation_1 = endLabelModel_1.get('valueAnimation'); 
 | 
    var data_1 = seriesModel.getData(); 
 | 
    var labelAnimationRecord_1 = { 
 | 
      lastFrameIndex: 0 
 | 
    }; 
 | 
    var during = anyStateShowEndLabel(seriesModel) ? function (percent, clipRect) { 
 | 
      lineView._endLabelOnDuring(percent, clipRect, data_1, labelAnimationRecord_1, valueAnimation_1, endLabelModel_1, coordSys); 
 | 
    } : null; 
 | 
    var isHorizontal = coordSys.getBaseAxis().isHorizontal(); 
 | 
    var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel, function () { 
 | 
      var endLabel = lineView._endLabel; 
 | 
      if (endLabel && hasAnimation) { 
 | 
        if (labelAnimationRecord_1.originalX != null) { 
 | 
          endLabel.attr({ 
 | 
            x: labelAnimationRecord_1.originalX, 
 | 
            y: labelAnimationRecord_1.originalY 
 | 
          }); 
 | 
        } 
 | 
      } 
 | 
    }, during); 
 | 
    // Expand clip shape to avoid clipping when line value exceeds axis 
 | 
    if (!seriesModel.get('clip', true)) { 
 | 
      var rectShape = clipPath.shape; 
 | 
      var expandSize = Math.max(rectShape.width, rectShape.height); 
 | 
      if (isHorizontal) { 
 | 
        rectShape.y -= expandSize; 
 | 
        rectShape.height += expandSize * 2; 
 | 
      } else { 
 | 
        rectShape.x -= expandSize; 
 | 
        rectShape.width += expandSize * 2; 
 | 
      } 
 | 
    } 
 | 
    // Set to the final frame. To make sure label layout is right. 
 | 
    if (during) { 
 | 
      during(1, clipPath); 
 | 
    } 
 | 
    return clipPath; 
 | 
  } else { 
 | 
    if (process.env.NODE_ENV !== 'production') { 
 | 
      if (seriesModel.get(['endLabel', 'show'])) { 
 | 
        console.warn('endLabel is not supported for lines in polar systems.'); 
 | 
      } 
 | 
    } 
 | 
    return createPolarClipPath(coordSys, hasAnimation, seriesModel); 
 | 
  } 
 | 
} 
 | 
function getEndLabelStateSpecified(endLabelModel, coordSys) { 
 | 
  var baseAxis = coordSys.getBaseAxis(); 
 | 
  var isHorizontal = baseAxis.isHorizontal(); 
 | 
  var isBaseInversed = baseAxis.inverse; 
 | 
  var align = isHorizontal ? isBaseInversed ? 'right' : 'left' : 'center'; 
 | 
  var verticalAlign = isHorizontal ? 'middle' : isBaseInversed ? 'top' : 'bottom'; 
 | 
  return { 
 | 
    normal: { 
 | 
      align: endLabelModel.get('align') || align, 
 | 
      verticalAlign: endLabelModel.get('verticalAlign') || verticalAlign 
 | 
    } 
 | 
  }; 
 | 
} 
 | 
var LineView = /** @class */function (_super) { 
 | 
  __extends(LineView, _super); 
 | 
  function LineView() { 
 | 
    return _super !== null && _super.apply(this, arguments) || this; 
 | 
  } 
 | 
  LineView.prototype.init = function () { 
 | 
    var lineGroup = new graphic.Group(); 
 | 
    var symbolDraw = new SymbolDraw(); 
 | 
    this.group.add(symbolDraw.group); 
 | 
    this._symbolDraw = symbolDraw; 
 | 
    this._lineGroup = lineGroup; 
 | 
    this._changePolyState = zrUtil.bind(this._changePolyState, this); 
 | 
  }; 
 | 
  LineView.prototype.render = function (seriesModel, ecModel, api) { 
 | 
    var coordSys = seriesModel.coordinateSystem; 
 | 
    var group = this.group; 
 | 
    var data = seriesModel.getData(); 
 | 
    var lineStyleModel = seriesModel.getModel('lineStyle'); 
 | 
    var areaStyleModel = seriesModel.getModel('areaStyle'); 
 | 
    var points = data.getLayout('points') || []; 
 | 
    var isCoordSysPolar = coordSys.type === 'polar'; 
 | 
    var prevCoordSys = this._coordSys; 
 | 
    var symbolDraw = this._symbolDraw; 
 | 
    var polyline = this._polyline; 
 | 
    var polygon = this._polygon; 
 | 
    var lineGroup = this._lineGroup; 
 | 
    var hasAnimation = !ecModel.ssr && seriesModel.get('animation'); 
 | 
    var isAreaChart = !areaStyleModel.isEmpty(); 
 | 
    var valueOrigin = areaStyleModel.get('origin'); 
 | 
    var dataCoordInfo = prepareDataCoordInfo(coordSys, data, valueOrigin); 
 | 
    var stackedOnPoints = isAreaChart && getStackedOnPoints(coordSys, data, dataCoordInfo); 
 | 
    var showSymbol = seriesModel.get('showSymbol'); 
 | 
    var connectNulls = seriesModel.get('connectNulls'); 
 | 
    var isIgnoreFunc = showSymbol && !isCoordSysPolar && getIsIgnoreFunc(seriesModel, data, coordSys); 
 | 
    // Remove temporary symbols 
 | 
    var oldData = this._data; 
 | 
    oldData && oldData.eachItemGraphicEl(function (el, idx) { 
 | 
      if (el.__temp) { 
 | 
        group.remove(el); 
 | 
        oldData.setItemGraphicEl(idx, null); 
 | 
      } 
 | 
    }); 
 | 
    // Remove previous created symbols if showSymbol changed to false 
 | 
    if (!showSymbol) { 
 | 
      symbolDraw.remove(); 
 | 
    } 
 | 
    group.add(lineGroup); 
 | 
    // FIXME step not support polar 
 | 
    var step = !isCoordSysPolar ? seriesModel.get('step') : false; 
 | 
    var clipShapeForSymbol; 
 | 
    if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) { 
 | 
      clipShapeForSymbol = coordSys.getArea(); 
 | 
      // Avoid float number rounding error for symbol on the edge of axis extent. 
 | 
      // See #7913 and `test/dataZoom-clip.html`. 
 | 
      if (clipShapeForSymbol.width != null) { 
 | 
        clipShapeForSymbol.x -= 0.1; 
 | 
        clipShapeForSymbol.y -= 0.1; 
 | 
        clipShapeForSymbol.width += 0.2; 
 | 
        clipShapeForSymbol.height += 0.2; 
 | 
      } else if (clipShapeForSymbol.r0) { 
 | 
        clipShapeForSymbol.r0 -= 0.5; 
 | 
        clipShapeForSymbol.r += 0.5; 
 | 
      } 
 | 
    } 
 | 
    this._clipShapeForSymbol = clipShapeForSymbol; 
 | 
    var visualColor = getVisualGradient(data, coordSys, api) || data.getVisual('style')[data.getVisual('drawType')]; 
 | 
    // Initialization animation or coordinate system changed 
 | 
    if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) { 
 | 
      showSymbol && symbolDraw.updateData(data, { 
 | 
        isIgnore: isIgnoreFunc, 
 | 
        clipShape: clipShapeForSymbol, 
 | 
        disableAnimation: true, 
 | 
        getSymbolPoint: function (idx) { 
 | 
          return [points[idx * 2], points[idx * 2 + 1]]; 
 | 
        } 
 | 
      }); 
 | 
      hasAnimation && this._initSymbolLabelAnimation(data, coordSys, clipShapeForSymbol); 
 | 
      if (step) { 
 | 
        if (stackedOnPoints) { 
 | 
          stackedOnPoints = turnPointsIntoStep(stackedOnPoints, points, coordSys, step, connectNulls); 
 | 
        } 
 | 
        // TODO If stacked series is not step 
 | 
        points = turnPointsIntoStep(points, null, coordSys, step, connectNulls); 
 | 
      } 
 | 
      polyline = this._newPolyline(points); 
 | 
      if (isAreaChart) { 
 | 
        polygon = this._newPolygon(points, stackedOnPoints); 
 | 
      } // If areaStyle is removed 
 | 
      else if (polygon) { 
 | 
        lineGroup.remove(polygon); 
 | 
        polygon = this._polygon = null; 
 | 
      } 
 | 
      // NOTE: Must update _endLabel before setClipPath. 
 | 
      if (!isCoordSysPolar) { 
 | 
        this._initOrUpdateEndLabel(seriesModel, coordSys, convertToColorString(visualColor)); 
 | 
      } 
 | 
      lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel)); 
 | 
    } else { 
 | 
      if (isAreaChart && !polygon) { 
 | 
        // If areaStyle is added 
 | 
        polygon = this._newPolygon(points, stackedOnPoints); 
 | 
      } else if (polygon && !isAreaChart) { 
 | 
        // If areaStyle is removed 
 | 
        lineGroup.remove(polygon); 
 | 
        polygon = this._polygon = null; 
 | 
      } 
 | 
      // NOTE: Must update _endLabel before setClipPath. 
 | 
      if (!isCoordSysPolar) { 
 | 
        this._initOrUpdateEndLabel(seriesModel, coordSys, convertToColorString(visualColor)); 
 | 
      } 
 | 
      // Update clipPath 
 | 
      var oldClipPath = lineGroup.getClipPath(); 
 | 
      if (oldClipPath) { 
 | 
        var newClipPath = createLineClipPath(this, coordSys, false, seriesModel); 
 | 
        graphic.initProps(oldClipPath, { 
 | 
          shape: newClipPath.shape 
 | 
        }, seriesModel); 
 | 
      } else { 
 | 
        lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel)); 
 | 
      } 
 | 
      // Always update, or it is wrong in the case turning on legend 
 | 
      // because points are not changed. 
 | 
      showSymbol && symbolDraw.updateData(data, { 
 | 
        isIgnore: isIgnoreFunc, 
 | 
        clipShape: clipShapeForSymbol, 
 | 
        disableAnimation: true, 
 | 
        getSymbolPoint: function (idx) { 
 | 
          return [points[idx * 2], points[idx * 2 + 1]]; 
 | 
        } 
 | 
      }); 
 | 
      // In the case data zoom triggered refreshing frequently 
 | 
      // Data may not change if line has a category axis. So it should animate nothing. 
 | 
      if (!isPointsSame(this._stackedOnPoints, stackedOnPoints) || !isPointsSame(this._points, points)) { 
 | 
        if (hasAnimation) { 
 | 
          this._doUpdateAnimation(data, stackedOnPoints, coordSys, api, step, valueOrigin, connectNulls); 
 | 
        } else { 
 | 
          // Not do it in update with animation 
 | 
          if (step) { 
 | 
            if (stackedOnPoints) { 
 | 
              stackedOnPoints = turnPointsIntoStep(stackedOnPoints, points, coordSys, step, connectNulls); 
 | 
            } 
 | 
            // TODO If stacked series is not step 
 | 
            points = turnPointsIntoStep(points, null, coordSys, step, connectNulls); 
 | 
          } 
 | 
          polyline.setShape({ 
 | 
            points: points 
 | 
          }); 
 | 
          polygon && polygon.setShape({ 
 | 
            points: points, 
 | 
            stackedOnPoints: stackedOnPoints 
 | 
          }); 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
    var emphasisModel = seriesModel.getModel('emphasis'); 
 | 
    var focus = emphasisModel.get('focus'); 
 | 
    var blurScope = emphasisModel.get('blurScope'); 
 | 
    var emphasisDisabled = emphasisModel.get('disabled'); 
 | 
    polyline.useStyle(zrUtil.defaults( 
 | 
    // Use color in lineStyle first 
 | 
    lineStyleModel.getLineStyle(), { 
 | 
      fill: 'none', 
 | 
      stroke: visualColor, 
 | 
      lineJoin: 'bevel' 
 | 
    })); 
 | 
    setStatesStylesFromModel(polyline, seriesModel, 'lineStyle'); 
 | 
    if (polyline.style.lineWidth > 0 && seriesModel.get(['emphasis', 'lineStyle', 'width']) === 'bolder') { 
 | 
      var emphasisLineStyle = polyline.getState('emphasis').style; 
 | 
      emphasisLineStyle.lineWidth = +polyline.style.lineWidth + 1; 
 | 
    } 
 | 
    // Needs seriesIndex for focus 
 | 
    getECData(polyline).seriesIndex = seriesModel.seriesIndex; 
 | 
    toggleHoverEmphasis(polyline, focus, blurScope, emphasisDisabled); 
 | 
    var smooth = getSmooth(seriesModel.get('smooth')); 
 | 
    var smoothMonotone = seriesModel.get('smoothMonotone'); 
 | 
    polyline.setShape({ 
 | 
      smooth: smooth, 
 | 
      smoothMonotone: smoothMonotone, 
 | 
      connectNulls: connectNulls 
 | 
    }); 
 | 
    if (polygon) { 
 | 
      var stackedOnSeries = data.getCalculationInfo('stackedOnSeries'); 
 | 
      var stackedOnSmooth = 0; 
 | 
      polygon.useStyle(zrUtil.defaults(areaStyleModel.getAreaStyle(), { 
 | 
        fill: visualColor, 
 | 
        opacity: 0.7, 
 | 
        lineJoin: 'bevel', 
 | 
        decal: data.getVisual('style').decal 
 | 
      })); 
 | 
      if (stackedOnSeries) { 
 | 
        stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth')); 
 | 
      } 
 | 
      polygon.setShape({ 
 | 
        smooth: smooth, 
 | 
        stackedOnSmooth: stackedOnSmooth, 
 | 
        smoothMonotone: smoothMonotone, 
 | 
        connectNulls: connectNulls 
 | 
      }); 
 | 
      setStatesStylesFromModel(polygon, seriesModel, 'areaStyle'); 
 | 
      // Needs seriesIndex for focus 
 | 
      getECData(polygon).seriesIndex = seriesModel.seriesIndex; 
 | 
      toggleHoverEmphasis(polygon, focus, blurScope, emphasisDisabled); 
 | 
    } 
 | 
    var changePolyState = this._changePolyState; 
 | 
    data.eachItemGraphicEl(function (el) { 
 | 
      // Switch polyline / polygon state if element changed its state. 
 | 
      el && (el.onHoverStateChange = changePolyState); 
 | 
    }); 
 | 
    this._polyline.onHoverStateChange = changePolyState; 
 | 
    this._data = data; 
 | 
    // Save the coordinate system for transition animation when data changed 
 | 
    this._coordSys = coordSys; 
 | 
    this._stackedOnPoints = stackedOnPoints; 
 | 
    this._points = points; 
 | 
    this._step = step; 
 | 
    this._valueOrigin = valueOrigin; 
 | 
    if (seriesModel.get('triggerLineEvent')) { 
 | 
      this.packEventData(seriesModel, polyline); 
 | 
      polygon && this.packEventData(seriesModel, polygon); 
 | 
    } 
 | 
  }; 
 | 
  LineView.prototype.packEventData = function (seriesModel, el) { 
 | 
    getECData(el).eventData = { 
 | 
      componentType: 'series', 
 | 
      componentSubType: 'line', 
 | 
      componentIndex: seriesModel.componentIndex, 
 | 
      seriesIndex: seriesModel.seriesIndex, 
 | 
      seriesName: seriesModel.name, 
 | 
      seriesType: 'line' 
 | 
    }; 
 | 
  }; 
 | 
  LineView.prototype.highlight = function (seriesModel, ecModel, api, payload) { 
 | 
    var data = seriesModel.getData(); 
 | 
    var dataIndex = modelUtil.queryDataIndex(data, payload); 
 | 
    this._changePolyState('emphasis'); 
 | 
    if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) { 
 | 
      var points = data.getLayout('points'); 
 | 
      var symbol = data.getItemGraphicEl(dataIndex); 
 | 
      if (!symbol) { 
 | 
        // Create a temporary symbol if it is not exists 
 | 
        var x = points[dataIndex * 2]; 
 | 
        var y = points[dataIndex * 2 + 1]; 
 | 
        if (isNaN(x) || isNaN(y)) { 
 | 
          // Null data 
 | 
          return; 
 | 
        } 
 | 
        // fix #11360: shouldn't draw symbol outside clipShapeForSymbol 
 | 
        if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(x, y)) { 
 | 
          return; 
 | 
        } 
 | 
        var zlevel = seriesModel.get('zlevel') || 0; 
 | 
        var z = seriesModel.get('z') || 0; 
 | 
        symbol = new SymbolClz(data, dataIndex); 
 | 
        symbol.x = x; 
 | 
        symbol.y = y; 
 | 
        symbol.setZ(zlevel, z); 
 | 
        // ensure label text of the temporary symbol is in front of line and area polygon 
 | 
        var symbolLabel = symbol.getSymbolPath().getTextContent(); 
 | 
        if (symbolLabel) { 
 | 
          symbolLabel.zlevel = zlevel; 
 | 
          symbolLabel.z = z; 
 | 
          symbolLabel.z2 = this._polyline.z2 + 1; 
 | 
        } 
 | 
        symbol.__temp = true; 
 | 
        data.setItemGraphicEl(dataIndex, symbol); 
 | 
        // Stop scale animation 
 | 
        symbol.stopSymbolAnimation(true); 
 | 
        this.group.add(symbol); 
 | 
      } 
 | 
      symbol.highlight(); 
 | 
    } else { 
 | 
      // Highlight whole series 
 | 
      ChartView.prototype.highlight.call(this, seriesModel, ecModel, api, payload); 
 | 
    } 
 | 
  }; 
 | 
  LineView.prototype.downplay = function (seriesModel, ecModel, api, payload) { 
 | 
    var data = seriesModel.getData(); 
 | 
    var dataIndex = modelUtil.queryDataIndex(data, payload); 
 | 
    this._changePolyState('normal'); 
 | 
    if (dataIndex != null && dataIndex >= 0) { 
 | 
      var symbol = data.getItemGraphicEl(dataIndex); 
 | 
      if (symbol) { 
 | 
        if (symbol.__temp) { 
 | 
          data.setItemGraphicEl(dataIndex, null); 
 | 
          this.group.remove(symbol); 
 | 
        } else { 
 | 
          symbol.downplay(); 
 | 
        } 
 | 
      } 
 | 
    } else { 
 | 
      // FIXME 
 | 
      // can not downplay completely. 
 | 
      // Downplay whole series 
 | 
      ChartView.prototype.downplay.call(this, seriesModel, ecModel, api, payload); 
 | 
    } 
 | 
  }; 
 | 
  LineView.prototype._changePolyState = function (toState) { 
 | 
    var polygon = this._polygon; 
 | 
    setStatesFlag(this._polyline, toState); 
 | 
    polygon && setStatesFlag(polygon, toState); 
 | 
  }; 
 | 
  LineView.prototype._newPolyline = function (points) { 
 | 
    var polyline = this._polyline; 
 | 
    // Remove previous created polyline 
 | 
    if (polyline) { 
 | 
      this._lineGroup.remove(polyline); 
 | 
    } 
 | 
    polyline = new ECPolyline({ 
 | 
      shape: { 
 | 
        points: points 
 | 
      }, 
 | 
      segmentIgnoreThreshold: 2, 
 | 
      z2: 10 
 | 
    }); 
 | 
    this._lineGroup.add(polyline); 
 | 
    this._polyline = polyline; 
 | 
    return polyline; 
 | 
  }; 
 | 
  LineView.prototype._newPolygon = function (points, stackedOnPoints) { 
 | 
    var polygon = this._polygon; 
 | 
    // Remove previous created polygon 
 | 
    if (polygon) { 
 | 
      this._lineGroup.remove(polygon); 
 | 
    } 
 | 
    polygon = new ECPolygon({ 
 | 
      shape: { 
 | 
        points: points, 
 | 
        stackedOnPoints: stackedOnPoints 
 | 
      }, 
 | 
      segmentIgnoreThreshold: 2 
 | 
    }); 
 | 
    this._lineGroup.add(polygon); 
 | 
    this._polygon = polygon; 
 | 
    return polygon; 
 | 
  }; 
 | 
  LineView.prototype._initSymbolLabelAnimation = function (data, coordSys, clipShape) { 
 | 
    var isHorizontalOrRadial; 
 | 
    var isCoordSysPolar; 
 | 
    var baseAxis = coordSys.getBaseAxis(); 
 | 
    var isAxisInverse = baseAxis.inverse; 
 | 
    if (coordSys.type === 'cartesian2d') { 
 | 
      isHorizontalOrRadial = baseAxis.isHorizontal(); 
 | 
      isCoordSysPolar = false; 
 | 
    } else if (coordSys.type === 'polar') { 
 | 
      isHorizontalOrRadial = baseAxis.dim === 'angle'; 
 | 
      isCoordSysPolar = true; 
 | 
    } 
 | 
    var seriesModel = data.hostModel; 
 | 
    var seriesDuration = seriesModel.get('animationDuration'); 
 | 
    if (zrUtil.isFunction(seriesDuration)) { 
 | 
      seriesDuration = seriesDuration(null); 
 | 
    } 
 | 
    var seriesDelay = seriesModel.get('animationDelay') || 0; 
 | 
    var seriesDelayValue = zrUtil.isFunction(seriesDelay) ? seriesDelay(null) : seriesDelay; 
 | 
    data.eachItemGraphicEl(function (symbol, idx) { 
 | 
      var el = symbol; 
 | 
      if (el) { 
 | 
        var point = [symbol.x, symbol.y]; 
 | 
        var start = void 0; 
 | 
        var end = void 0; 
 | 
        var current = void 0; 
 | 
        if (clipShape) { 
 | 
          if (isCoordSysPolar) { 
 | 
            var polarClip = clipShape; 
 | 
            var coord = coordSys.pointToCoord(point); 
 | 
            if (isHorizontalOrRadial) { 
 | 
              start = polarClip.startAngle; 
 | 
              end = polarClip.endAngle; 
 | 
              current = -coord[1] / 180 * Math.PI; 
 | 
            } else { 
 | 
              start = polarClip.r0; 
 | 
              end = polarClip.r; 
 | 
              current = coord[0]; 
 | 
            } 
 | 
          } else { 
 | 
            var gridClip = clipShape; 
 | 
            if (isHorizontalOrRadial) { 
 | 
              start = gridClip.x; 
 | 
              end = gridClip.x + gridClip.width; 
 | 
              current = symbol.x; 
 | 
            } else { 
 | 
              start = gridClip.y + gridClip.height; 
 | 
              end = gridClip.y; 
 | 
              current = symbol.y; 
 | 
            } 
 | 
          } 
 | 
        } 
 | 
        var ratio = end === start ? 0 : (current - start) / (end - start); 
 | 
        if (isAxisInverse) { 
 | 
          ratio = 1 - ratio; 
 | 
        } 
 | 
        var delay = zrUtil.isFunction(seriesDelay) ? seriesDelay(idx) : seriesDuration * ratio + seriesDelayValue; 
 | 
        var symbolPath = el.getSymbolPath(); 
 | 
        var text = symbolPath.getTextContent(); 
 | 
        el.attr({ 
 | 
          scaleX: 0, 
 | 
          scaleY: 0 
 | 
        }); 
 | 
        el.animateTo({ 
 | 
          scaleX: 1, 
 | 
          scaleY: 1 
 | 
        }, { 
 | 
          duration: 200, 
 | 
          setToFinal: true, 
 | 
          delay: delay 
 | 
        }); 
 | 
        if (text) { 
 | 
          text.animateFrom({ 
 | 
            style: { 
 | 
              opacity: 0 
 | 
            } 
 | 
          }, { 
 | 
            duration: 300, 
 | 
            delay: delay 
 | 
          }); 
 | 
        } 
 | 
        symbolPath.disableLabelAnimation = true; 
 | 
      } 
 | 
    }); 
 | 
  }; 
 | 
  LineView.prototype._initOrUpdateEndLabel = function (seriesModel, coordSys, inheritColor) { 
 | 
    var endLabelModel = seriesModel.getModel('endLabel'); 
 | 
    if (anyStateShowEndLabel(seriesModel)) { 
 | 
      var data_2 = seriesModel.getData(); 
 | 
      var polyline = this._polyline; 
 | 
      // series may be filtered. 
 | 
      var points = data_2.getLayout('points'); 
 | 
      if (!points) { 
 | 
        polyline.removeTextContent(); 
 | 
        this._endLabel = null; 
 | 
        return; 
 | 
      } 
 | 
      var endLabel = this._endLabel; 
 | 
      if (!endLabel) { 
 | 
        endLabel = this._endLabel = new graphic.Text({ 
 | 
          z2: 200 // should be higher than item symbol 
 | 
        }); 
 | 
        endLabel.ignoreClip = true; 
 | 
        polyline.setTextContent(this._endLabel); 
 | 
        polyline.disableLabelAnimation = true; 
 | 
      } 
 | 
      // Find last non-NaN data to display data 
 | 
      var dataIndex = getLastIndexNotNull(points); 
 | 
      if (dataIndex >= 0) { 
 | 
        setLabelStyle(polyline, getLabelStatesModels(seriesModel, 'endLabel'), { 
 | 
          inheritColor: inheritColor, 
 | 
          labelFetcher: seriesModel, 
 | 
          labelDataIndex: dataIndex, 
 | 
          defaultText: function (dataIndex, opt, interpolatedValue) { 
 | 
            return interpolatedValue != null ? getDefaultInterpolatedLabel(data_2, interpolatedValue) : getDefaultLabel(data_2, dataIndex); 
 | 
          }, 
 | 
          enableTextSetter: true 
 | 
        }, getEndLabelStateSpecified(endLabelModel, coordSys)); 
 | 
        polyline.textConfig.position = null; 
 | 
      } 
 | 
    } else if (this._endLabel) { 
 | 
      this._polyline.removeTextContent(); 
 | 
      this._endLabel = null; 
 | 
    } 
 | 
  }; 
 | 
  LineView.prototype._endLabelOnDuring = function (percent, clipRect, data, animationRecord, valueAnimation, endLabelModel, coordSys) { 
 | 
    var endLabel = this._endLabel; 
 | 
    var polyline = this._polyline; 
 | 
    if (endLabel) { 
 | 
      // NOTE: Don't remove percent < 1. percent === 1 means the first frame during render. 
 | 
      // The label is not prepared at this time. 
 | 
      if (percent < 1 && animationRecord.originalX == null) { 
 | 
        animationRecord.originalX = endLabel.x; 
 | 
        animationRecord.originalY = endLabel.y; 
 | 
      } 
 | 
      var points = data.getLayout('points'); 
 | 
      var seriesModel = data.hostModel; 
 | 
      var connectNulls = seriesModel.get('connectNulls'); 
 | 
      var precision = endLabelModel.get('precision'); 
 | 
      var distance = endLabelModel.get('distance') || 0; 
 | 
      var baseAxis = coordSys.getBaseAxis(); 
 | 
      var isHorizontal = baseAxis.isHorizontal(); 
 | 
      var isBaseInversed = baseAxis.inverse; 
 | 
      var clipShape = clipRect.shape; 
 | 
      var xOrY = isBaseInversed ? isHorizontal ? clipShape.x : clipShape.y + clipShape.height : isHorizontal ? clipShape.x + clipShape.width : clipShape.y; 
 | 
      var distanceX = (isHorizontal ? distance : 0) * (isBaseInversed ? -1 : 1); 
 | 
      var distanceY = (isHorizontal ? 0 : -distance) * (isBaseInversed ? -1 : 1); 
 | 
      var dim = isHorizontal ? 'x' : 'y'; 
 | 
      var dataIndexRange = getIndexRange(points, xOrY, dim); 
 | 
      var indices = dataIndexRange.range; 
 | 
      var diff = indices[1] - indices[0]; 
 | 
      var value = void 0; 
 | 
      if (diff >= 1) { 
 | 
        // diff > 1 && connectNulls, which is on the null data. 
 | 
        if (diff > 1 && !connectNulls) { 
 | 
          var pt = getPointAtIndex(points, indices[0]); 
 | 
          endLabel.attr({ 
 | 
            x: pt[0] + distanceX, 
 | 
            y: pt[1] + distanceY 
 | 
          }); 
 | 
          valueAnimation && (value = seriesModel.getRawValue(indices[0])); 
 | 
        } else { 
 | 
          var pt = polyline.getPointOn(xOrY, dim); 
 | 
          pt && endLabel.attr({ 
 | 
            x: pt[0] + distanceX, 
 | 
            y: pt[1] + distanceY 
 | 
          }); 
 | 
          var startValue = seriesModel.getRawValue(indices[0]); 
 | 
          var endValue = seriesModel.getRawValue(indices[1]); 
 | 
          valueAnimation && (value = modelUtil.interpolateRawValues(data, precision, startValue, endValue, dataIndexRange.t)); 
 | 
        } 
 | 
        animationRecord.lastFrameIndex = indices[0]; 
 | 
      } else { 
 | 
        // If diff <= 0, which is the range is not found(Include NaN) 
 | 
        // Choose the first point or last point. 
 | 
        var idx = percent === 1 || animationRecord.lastFrameIndex > 0 ? indices[0] : 0; 
 | 
        var pt = getPointAtIndex(points, idx); 
 | 
        valueAnimation && (value = seriesModel.getRawValue(idx)); 
 | 
        endLabel.attr({ 
 | 
          x: pt[0] + distanceX, 
 | 
          y: pt[1] + distanceY 
 | 
        }); 
 | 
      } 
 | 
      if (valueAnimation) { 
 | 
        var inner = labelInner(endLabel); 
 | 
        if (typeof inner.setLabelText === 'function') { 
 | 
          inner.setLabelText(value); 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
  }; 
 | 
  /** 
 | 
   * @private 
 | 
   */ 
 | 
  // FIXME Two value axis 
 | 
  LineView.prototype._doUpdateAnimation = function (data, stackedOnPoints, coordSys, api, step, valueOrigin, connectNulls) { 
 | 
    var polyline = this._polyline; 
 | 
    var polygon = this._polygon; 
 | 
    var seriesModel = data.hostModel; 
 | 
    var diff = lineAnimationDiff(this._data, data, this._stackedOnPoints, stackedOnPoints, this._coordSys, coordSys, this._valueOrigin, valueOrigin); 
 | 
    var current = diff.current; 
 | 
    var stackedOnCurrent = diff.stackedOnCurrent; 
 | 
    var next = diff.next; 
 | 
    var stackedOnNext = diff.stackedOnNext; 
 | 
    if (step) { 
 | 
      // TODO If stacked series is not step 
 | 
      stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, diff.current, coordSys, step, connectNulls); 
 | 
      current = turnPointsIntoStep(diff.current, null, coordSys, step, connectNulls); 
 | 
      stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, diff.next, coordSys, step, connectNulls); 
 | 
      next = turnPointsIntoStep(diff.next, null, coordSys, step, connectNulls); 
 | 
    } 
 | 
    // Don't apply animation if diff is large. 
 | 
    // For better result and avoid memory explosion problems like 
 | 
    // https://github.com/apache/incubator-echarts/issues/12229 
 | 
    if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) { 
 | 
      polyline.stopAnimation(); 
 | 
      polyline.setShape({ 
 | 
        points: next 
 | 
      }); 
 | 
      if (polygon) { 
 | 
        polygon.stopAnimation(); 
 | 
        polygon.setShape({ 
 | 
          points: next, 
 | 
          stackedOnPoints: stackedOnNext 
 | 
        }); 
 | 
      } 
 | 
      return; 
 | 
    } 
 | 
    polyline.shape.__points = diff.current; 
 | 
    polyline.shape.points = current; 
 | 
    var target = { 
 | 
      shape: { 
 | 
        points: next 
 | 
      } 
 | 
    }; 
 | 
    // Also animate the original points. 
 | 
    // If points reference is changed when turning into step line. 
 | 
    if (diff.current !== current) { 
 | 
      target.shape.__points = diff.next; 
 | 
    } 
 | 
    // Stop previous animation. 
 | 
    polyline.stopAnimation(); 
 | 
    graphic.updateProps(polyline, target, seriesModel); 
 | 
    if (polygon) { 
 | 
      polygon.setShape({ 
 | 
        // Reuse the points with polyline. 
 | 
        points: current, 
 | 
        stackedOnPoints: stackedOnCurrent 
 | 
      }); 
 | 
      polygon.stopAnimation(); 
 | 
      graphic.updateProps(polygon, { 
 | 
        shape: { 
 | 
          stackedOnPoints: stackedOnNext 
 | 
        } 
 | 
      }, seriesModel); 
 | 
      // If use attr directly in updateProps. 
 | 
      if (polyline.shape.points !== polygon.shape.points) { 
 | 
        polygon.shape.points = polyline.shape.points; 
 | 
      } 
 | 
    } 
 | 
    var updatedDataInfo = []; 
 | 
    var diffStatus = diff.status; 
 | 
    for (var i = 0; i < diffStatus.length; i++) { 
 | 
      var cmd = diffStatus[i].cmd; 
 | 
      if (cmd === '=') { 
 | 
        var el = data.getItemGraphicEl(diffStatus[i].idx1); 
 | 
        if (el) { 
 | 
          updatedDataInfo.push({ 
 | 
            el: el, 
 | 
            ptIdx: i // Index of points 
 | 
          }); 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
    if (polyline.animators && polyline.animators.length) { 
 | 
      polyline.animators[0].during(function () { 
 | 
        polygon && polygon.dirtyShape(); 
 | 
        var points = polyline.shape.__points; 
 | 
        for (var i = 0; i < updatedDataInfo.length; i++) { 
 | 
          var el = updatedDataInfo[i].el; 
 | 
          var offset = updatedDataInfo[i].ptIdx * 2; 
 | 
          el.x = points[offset]; 
 | 
          el.y = points[offset + 1]; 
 | 
          el.markRedraw(); 
 | 
        } 
 | 
      }); 
 | 
    } 
 | 
  }; 
 | 
  LineView.prototype.remove = function (ecModel) { 
 | 
    var group = this.group; 
 | 
    var oldData = this._data; 
 | 
    this._lineGroup.removeAll(); 
 | 
    this._symbolDraw.remove(true); 
 | 
    // Remove temporary created elements when highlighting 
 | 
    oldData && oldData.eachItemGraphicEl(function (el, idx) { 
 | 
      if (el.__temp) { 
 | 
        group.remove(el); 
 | 
        oldData.setItemGraphicEl(idx, null); 
 | 
      } 
 | 
    }); 
 | 
    this._polyline = this._polygon = this._coordSys = this._points = this._stackedOnPoints = this._endLabel = this._data = null; 
 | 
  }; 
 | 
  LineView.type = 'line'; 
 | 
  return LineView; 
 | 
}(ChartView); 
 | 
export default LineView; 
 |