LineView.ts 26.1 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.
*/

L
lang 已提交
20
// FIXME step not support polar
L
lang 已提交
21

S
sushuang 已提交
22
import {__DEV__} from '../../config';
S
sushuang 已提交
23
import * as zrUtil from 'zrender/src/core/util';
S
sushuang 已提交
24 25 26
import SymbolDraw from '../helper/SymbolDraw';
import SymbolClz from '../helper/Symbol';
import lineAnimationDiff from './lineAnimationDiff';
S
sushuang 已提交
27 28
import * as graphic from '../../util/graphic';
import * as modelUtil from '../../util/model';
P
pissang 已提交
29
import {ECPolyline, ECPolygon} from './poly';
S
sushuang 已提交
30
import ChartView from '../../view/Chart';
S
sushuang 已提交
31
import {prepareDataCoordInfo, getStackedOnPoint} from './helper';
32
import {createGridClipPath, createPolarClipPath} from '../helper/createClipPathFromCoordSys';
P
pissang 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
import LineSeriesModel, { LineSeriesOption } from './LineSeries';
import type GlobalModel from '../../model/Global';
import type ExtensionAPI from '../../ExtensionAPI';
// TODO
import Cartesian2D from '../../coord/cartesian/Cartesian2D';
import Polar from '../../coord/polar/Polar';
import type List from '../../data/List';
import type { VisualMeta } from '../../component/visualMap/VisualMapModel';
import type { Payload, Dictionary, ColorString } from '../../util/types';
import type OrdinalScale from '../../scale/Ordinal';
import type Axis2D from '../../coord/cartesian/Axis2D';


type PolarArea = ReturnType<Polar['getArea']>
type Cartesian2DArea = ReturnType<Cartesian2D['getArea']>

interface SymbolExtended extends SymbolClz {
    __temp: boolean
}
S
sushuang 已提交
52

P
pissang 已提交
53
function isPointsSame(points1: number[][], points2: number[][]) {
S
sushuang 已提交
54 55 56 57 58 59 60
    if (points1.length !== points2.length) {
        return;
    }
    for (var i = 0; i < points1.length; i++) {
        var p1 = points1[i];
        var p2 = points2[i];
        if (p1[0] !== p2[0] || p1[1] !== p2[1]) {
61 62 63
            return;
        }
    }
S
sushuang 已提交
64 65 66
    return true;
}

P
pissang 已提交
67 68
function getSmooth(smooth: number | boolean) {
    return typeof smooth === 'number' ? smooth : (smooth ? 0.5 : 0);
S
sushuang 已提交
69 70
}

P
pissang 已提交
71 72 73 74 75
function getStackedOnPoints(
    coordSys: Cartesian2D | Polar,
    data: List,
    dataCoordInfo: ReturnType<typeof prepareDataCoordInfo>
) {
S
sushuang 已提交
76 77
    if (!dataCoordInfo.valueDim) {
        return [];
S
sushuang 已提交
78
    }
L
lang 已提交
79

S
sushuang 已提交
80 81 82 83
    var points = [];
    for (var idx = 0, len = data.count(); idx < len; idx++) {
        points.push(getStackedOnPoint(dataCoordInfo, coordSys, data, idx));
    }
S
sushuang 已提交
84

S
sushuang 已提交
85
    return points;
S
sushuang 已提交
86 87
}

P
pissang 已提交
88 89 90 91 92
function turnPointsIntoStep(
    points: number[][],
    coordSys: Cartesian2D | Polar,
    stepTurnAt: 'start' | 'end' | 'middle'
) {
S
sushuang 已提交
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
    var baseAxis = coordSys.getBaseAxis();
    var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1;

    var stepPoints = [];
    for (var i = 0; i < points.length - 1; i++) {
        var nextPt = points[i + 1];
        var pt = points[i];
        stepPoints.push(pt);

        var stepPt = [];
        switch (stepTurnAt) {
            case 'end':
                stepPt[baseIndex] = nextPt[baseIndex];
                stepPt[1 - baseIndex] = pt[1 - baseIndex];
                // default is start
                stepPoints.push(stepPt);
                break;
            case 'middle':
                // default is start
                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);
                stepPoints.push(stepPt2);
                break;
            default:
                stepPt[baseIndex] = pt[baseIndex];
                stepPt[1 - baseIndex] = nextPt[1 - baseIndex];
                // default is start
                stepPoints.push(stepPt);
125 126
        }
    }
S
sushuang 已提交
127 128 129 130 131
    // Last points
    points[i] && stepPoints.push(points[i]);
    return stepPoints;
}

P
pissang 已提交
132 133 134 135 136
function getVisualGradient(
    data: List,
    coordSys: Cartesian2D | Polar
) {
    var visualMetaList = data.getVisual('visualMeta') as VisualMeta[];
S
sushuang 已提交
137 138 139
    if (!visualMetaList || !visualMetaList.length || !data.count()) {
        // When data.count() is 0, gradient range can not be calculated.
        return;
140 141
    }

S
sushuang 已提交
142 143 144 145 146 147 148
    if (coordSys.type !== 'cartesian2d') {
        if (__DEV__) {
            console.warn('Visual map on line style is only supported on cartesian2d.');
        }
        return;
    }

P
pissang 已提交
149
    var coordDim: 'x' | 'y';
S
sushuang 已提交
150
    var visualMeta;
S
sushuang 已提交
151

S
sushuang 已提交
152
    for (var i = visualMetaList.length - 1; i >= 0; i--) {
S
sushuang 已提交
153 154 155
        var dimIndex = visualMetaList[i].dimension;
        var dimName = data.dimensions[dimIndex];
        var dimInfo = data.getDimensionInfo(dimName);
P
pissang 已提交
156
        coordDim = (dimInfo && dimInfo.coordDim) as 'x' | 'y';
S
sushuang 已提交
157
        // Can only be x or y
S
sushuang 已提交
158
        if (coordDim === 'x' || coordDim === 'y') {
S
sushuang 已提交
159 160
            visualMeta = visualMetaList[i];
            break;
L
lang 已提交
161 162
        }
    }
S
sushuang 已提交
163 164

    if (!visualMeta) {
S
sushuang 已提交
165 166
        if (__DEV__) {
            console.warn('Visual map on line style only support x or y dimension.');
167
        }
S
sushuang 已提交
168 169
        return;
    }
170

S
sushuang 已提交
171 172 173 174 175 176 177
    // 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`.

S
sushuang 已提交
178
    var axis = coordSys.getAxis(coordDim);
S
sushuang 已提交
179

P
pissang 已提交
180 181 182 183 184
    interface ColorStop {
        offset: number
        coord?: number
        color: ColorString
    }
S
sushuang 已提交
185
    // dataToCoor mapping may not be linear, but must be monotonic.
P
pissang 已提交
186
    var colorStops: ColorStop[] = zrUtil.map(visualMeta.stops, function (stop) {
S
sushuang 已提交
187
        return {
P
pissang 已提交
188
            offset: 0,
S
sushuang 已提交
189 190 191 192 193 194
            coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)),
            color: stop.color
        };
    });
    var stopLen = colorStops.length;
    var outerColors = visualMeta.outerColors.slice();
195

S
sushuang 已提交
196 197 198 199
    if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) {
        colorStops.reverse();
        outerColors.reverse();
    }
200

S
sushuang 已提交
201 202 203 204
    var tinyExtent = 10; // Arbitrary value: 10px
    var minCoord = colorStops[0].coord - tinyExtent;
    var maxCoord = colorStops[stopLen - 1].coord + tinyExtent;
    var coordSpan = maxCoord - minCoord;
205

S
sushuang 已提交
206 207 208
    if (coordSpan < 1e-3) {
        return 'transparent';
    }
209

S
sushuang 已提交
210 211 212 213 214 215 216 217 218 219 220
    zrUtil.each(colorStops, function (stop) {
        stop.offset = (stop.coord - minCoord) / coordSpan;
    });
    colorStops.push({
        offset: stopLen ? colorStops[stopLen - 1].offset : 0.5,
        color: outerColors[1] || 'transparent'
    });
    colorStops.unshift({ // notice colorStops.length have been changed.
        offset: stopLen ? colorStops[0].offset : 0.5,
        color: outerColors[0] || 'transparent'
    });
221

S
sushuang 已提交
222 223 224 225
    // zrUtil.each(colorStops, function (colorStop) {
    //     // Make sure each offset has rounded px to avoid not sharp edge
    //     colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start);
    // });
226

S
sushuang 已提交
227
    var gradient = new graphic.LinearGradient(0, 0, 0, 0, colorStops, true);
S
sushuang 已提交
228
    gradient[coordDim] = minCoord;
P
pissang 已提交
229
    gradient[coordDim + '2' as 'x2' | 'y2'] = maxCoord;
L
Tweak  
lang 已提交
230

S
sushuang 已提交
231 232
    return gradient;
}
233

P
pissang 已提交
234 235 236 237 238
function getIsIgnoreFunc(
    seriesModel: LineSeriesModel,
    data: List,
    coordSys: Cartesian2D
) {
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
    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);
P
pissang 已提交
263
    var labelMap: Dictionary<1> = {};
264 265 266 267 268

    zrUtil.each(categoryAxis.getViewLabels(), function (labelItem) {
        labelMap[labelItem.tickValue] = 1;
    });

P
pissang 已提交
269
    return function (dataIndex: number) {
270 271 272 273
        return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex));
    };
}

P
pissang 已提交
274 275 276 277
function canShowAllSymbolForCategory(
    categoryAxis: Axis2D,
    data: List
) {
278 279 280 281 282
    // In mose 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();
P
pissang 已提交
283
    var availSize = Math.abs(axisExtent[1] - axisExtent[0]) / (categoryAxis.scale as OrdinalScale).count();
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
    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;
}

P
pissang 已提交
304 305 306 307 308
function createLineClipPath(
    coordSys: Cartesian2D | Polar,
    hasAnimation: boolean,
    seriesModel: LineSeriesModel
) {
309 310 311 312
    if (coordSys.type === 'cartesian2d') {
        var isHorizontal = coordSys.getBaseAxis().isHorizontal();
        var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel);
        // Expand clip shape to avoid clipping when line value exceeds axis
313
        if (!seriesModel.get('clip', true)) {
314 315 316 317 318 319 320 321 322 323 324
            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;
            }
        }
325
        return clipPath;
326 327 328 329 330 331 332
    }
    else {
        return createPolarClipPath(coordSys, hasAnimation, seriesModel);
    }

}

P
pissang 已提交
333 334 335 336 337 338 339 340 341 342 343 344 345 346
class LineView extends ChartView {

    static readonly type = 'line'

    _symbolDraw: SymbolDraw

    _lineGroup: graphic.Group
    _coordSys: Cartesian2D | Polar

    _polyline: ECPolyline
    _polygon: ECPolygon

    _stackedOnPoints: number[][]
    _points: number[][]
347

P
pissang 已提交
348 349
    _step: LineSeriesOption['step']
    _valueOrigin: LineSeriesOption['areaStyle']['origin']
L
lang 已提交
350

P
pissang 已提交
351 352 353 354 355 356 357
    _clipShapeForSymbol: {
        contain(x: number, y: number): boolean
    }

    _data: List

    init() {
S
sushuang 已提交
358
        var lineGroup = new graphic.Group();
L
lang 已提交
359

S
sushuang 已提交
360 361
        var symbolDraw = new SymbolDraw();
        this.group.add(symbolDraw.group);
L
tweak  
lang 已提交
362

S
sushuang 已提交
363 364
        this._symbolDraw = symbolDraw;
        this._lineGroup = lineGroup;
P
pissang 已提交
365
    }
L
tweak  
lang 已提交
366

P
pissang 已提交
367
    render(seriesModel: LineSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {
S
sushuang 已提交
368 369 370
        var coordSys = seriesModel.coordinateSystem;
        var group = this.group;
        var data = seriesModel.getData();
371
        var lineStyleModel = seriesModel.getModel('lineStyle');
P
pissang 已提交
372
        var areaStyleModel = seriesModel.getModel('areaStyle');
L
lang 已提交
373

S
sushuang 已提交
374
        var points = data.mapArray(data.getItemLayout);
L
lang 已提交
375

S
sushuang 已提交
376 377
        var isCoordSysPolar = coordSys.type === 'polar';
        var prevCoordSys = this._coordSys;
378

S
sushuang 已提交
379 380 381
        var symbolDraw = this._symbolDraw;
        var polyline = this._polyline;
        var polygon = this._polygon;
L
lang 已提交
382

S
sushuang 已提交
383
        var lineGroup = this._lineGroup;
L
lang 已提交
384

S
sushuang 已提交
385
        var hasAnimation = seriesModel.get('animation');
L
tweak  
lang 已提交
386

S
sushuang 已提交
387
        var isAreaChart = !areaStyleModel.isEmpty();
S
sushuang 已提交
388 389 390 391 392

        var valueOrigin = areaStyleModel.get('origin');
        var dataCoordInfo = prepareDataCoordInfo(coordSys, data, valueOrigin);

        var stackedOnPoints = getStackedOnPoints(coordSys, data, dataCoordInfo);
L
lang 已提交
393

S
sushuang 已提交
394
        var showSymbol = seriesModel.get('showSymbol');
L
lang 已提交
395

396
        var isIgnoreFunc = showSymbol && !isCoordSysPolar
P
pissang 已提交
397
            && getIsIgnoreFunc(seriesModel, data, coordSys as Cartesian2D);
398

S
sushuang 已提交
399 400
        // Remove temporary symbols
        var oldData = this._data;
P
pissang 已提交
401
        oldData && oldData.eachItemGraphicEl(function (el: SymbolExtended, idx) {
S
sushuang 已提交
402 403 404 405 406
            if (el.__temp) {
                group.remove(el);
                oldData.setItemGraphicEl(idx, null);
            }
        });
L
lang 已提交
407

S
sushuang 已提交
408 409 410 411 412 413
        // Remove previous created symbols if showSymbol changed to false
        if (!showSymbol) {
            symbolDraw.remove();
        }

        group.add(lineGroup);
414

S
sushuang 已提交
415
        // FIXME step not support polar
P
pissang 已提交
416 417
        var step = !isCoordSysPolar ? seriesModel.get('step') : false;
        var clipShapeForSymbol: PolarArea | Cartesian2DArea;
H
hantianjiao 已提交
418
        if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) {
419 420 421
            clipShapeForSymbol = coordSys.getArea();
            // Avoid float number rounding error for symbol on the edge of axis extent.
            // See #7913 and `test/dataZoom-clip.html`.
P
pissang 已提交
422 423 424 425 426
            if ((clipShapeForSymbol as Cartesian2DArea).width != null) {
                (clipShapeForSymbol as Cartesian2DArea).x -= 0.1;
                (clipShapeForSymbol as Cartesian2DArea).y -= 0.1;
                (clipShapeForSymbol as Cartesian2DArea).width += 0.2;
                (clipShapeForSymbol as Cartesian2DArea).height += 0.2;
427
            }
P
pissang 已提交
428 429 430
            else if ((clipShapeForSymbol as PolarArea).r0) {
                (clipShapeForSymbol as PolarArea).r0 -= 0.5;
                (clipShapeForSymbol as PolarArea).r += 0.5;
431 432
            }
        }
433
        this._clipShapeForSymbol = clipShapeForSymbol;
S
sushuang 已提交
434 435 436 437
        // Initialization animation or coordinate system changed
        if (
            !(polyline && prevCoordSys.type === coordSys.type && step === this._step)
        ) {
S
sushuang 已提交
438
            showSymbol && symbolDraw.updateData(data, {
439
                isIgnore: isIgnoreFunc,
440
                clipShape: clipShapeForSymbol
S
sushuang 已提交
441
            });
S
sushuang 已提交
442 443 444 445 446

            if (step) {
                // TODO If stacked series is not step
                points = turnPointsIntoStep(points, coordSys, step);
                stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step);
447 448
            }

P
pissang 已提交
449
            polyline = this._newPolyline(points);
S
sushuang 已提交
450 451
            if (isAreaChart) {
                polygon = this._newPolygon(
P
pissang 已提交
452
                    points, stackedOnPoints
S
sushuang 已提交
453 454
                );
            }
455
            lineGroup.setClipPath(createLineClipPath(coordSys, true, seriesModel));
S
sushuang 已提交
456 457 458 459 460
        }
        else {
            if (isAreaChart && !polygon) {
                // If areaStyle is added
                polygon = this._newPolygon(
P
pissang 已提交
461
                    points, stackedOnPoints
S
sushuang 已提交
462 463 464 465 466 467 468
                );
            }
            else if (polygon && !isAreaChart) {
                // If areaStyle is removed
                lineGroup.remove(polygon);
                polygon = this._polygon = null;
            }
469

S
sushuang 已提交
470
            // Update clipPath
471
            lineGroup.setClipPath(createLineClipPath(coordSys, false, seriesModel));
472

S
sushuang 已提交
473 474
            // Always update, or it is wrong in the case turning on legend
            // because points are not changed
S
sushuang 已提交
475
            showSymbol && symbolDraw.updateData(data, {
476
                isIgnore: isIgnoreFunc,
477
                clipShape: clipShapeForSymbol
S
sushuang 已提交
478
            });
L
lang 已提交
479

S
sushuang 已提交
480 481 482 483 484 485 486 487 488 489 490 491 492
            // Stop symbol animation and sync with line points
            // FIXME performance?
            data.eachItemGraphicEl(function (el) {
                el.stopAnimation(true);
            });

            // In the case data zoom triggerred 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._updateAnimation(
S
sushuang 已提交
493
                        data, stackedOnPoints, coordSys, api, step, valueOrigin
L
lang 已提交
494 495
                    );
                }
S
sushuang 已提交
496 497 498 499 500 501
                else {
                    // Not do it in update with animation
                    if (step) {
                        // TODO If stacked series is not step
                        points = turnPointsIntoStep(points, coordSys, step);
                        stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step);
L
lang 已提交
502
                    }
S
sushuang 已提交
503 504 505 506 507 508 509 510

                    polyline.setShape({
                        points: points
                    });
                    polygon && polygon.setShape({
                        points: points,
                        stackedOnPoints: stackedOnPoints
                    });
L
lang 已提交
511
                }
L
lang 已提交
512
            }
S
sushuang 已提交
513 514 515 516 517 518 519 520 521 522 523 524 525 526
        }

        var visualColor = getVisualGradient(data, coordSys) || data.getVisual('color');

        polyline.useStyle(zrUtil.defaults(
            // Use color in lineStyle first
            lineStyleModel.getLineStyle(),
            {
                fill: 'none',
                stroke: visualColor,
                lineJoin: 'bevel'
            }
        ));

P
pissang 已提交
527
        var smooth = getSmooth(seriesModel.get('smooth'));
S
sushuang 已提交
528 529 530 531 532
        polyline.setShape({
            smooth: smooth,
            smoothMonotone: seriesModel.get('smoothMonotone'),
            connectNulls: seriesModel.get('connectNulls')
        });
L
lang 已提交
533

S
sushuang 已提交
534
        if (polygon) {
S
sushuang 已提交
535
            var stackedOnSeries = data.getCalculationInfo('stackedOnSeries');
S
sushuang 已提交
536
            var stackedOnSmooth = 0;
537

S
sushuang 已提交
538 539
            polygon.useStyle(zrUtil.defaults(
                areaStyleModel.getAreaStyle(),
L
lang 已提交
540
                {
S
sushuang 已提交
541 542
                    fill: visualColor,
                    opacity: 0.7,
L
lang 已提交
543 544 545
                    lineJoin: 'bevel'
                }
            ));
L
lang 已提交
546

S
sushuang 已提交
547
            if (stackedOnSeries) {
S
sushuang 已提交
548 549 550 551
                stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth'));
            }

            polygon.setShape({
552
                smooth: smooth,
S
sushuang 已提交
553
                stackedOnSmooth: stackedOnSmooth,
L
lang 已提交
554 555
                smoothMonotone: seriesModel.get('smoothMonotone'),
                connectNulls: seriesModel.get('connectNulls')
556
            });
S
sushuang 已提交
557
        }
L
lang 已提交
558

S
sushuang 已提交
559 560 561 562 563 564
        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;
S
sushuang 已提交
565
        this._valueOrigin = valueOrigin;
P
pissang 已提交
566
    }
S
sushuang 已提交
567

P
pissang 已提交
568
    dispose() {}
S
sushuang 已提交
569

P
pissang 已提交
570 571 572 573 574 575
    highlight(
        seriesModel: LineSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: Payload
    ) {
S
sushuang 已提交
576 577 578 579
        var data = seriesModel.getData();
        var dataIndex = modelUtil.queryDataIndex(data, payload);

        if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) {
P
pissang 已提交
580
            var symbol = data.getItemGraphicEl(dataIndex) as SymbolClz;
S
sushuang 已提交
581 582
            if (!symbol) {
                // Create a temporary symbol if it is not exists
P
pissang 已提交
583
                var pt = data.getItemLayout(dataIndex) as number[];
S
sushuang 已提交
584 585 586 587
                if (!pt) {
                    // Null data
                    return;
                }
588 589 590 591
                // fix #11360: should't draw symbol outside clipShapeForSymbol
                if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(pt[0], pt[1])) {
                    return;
                }
S
sushuang 已提交
592 593 594 595 596 597 598
                symbol = new SymbolClz(data, dataIndex);
                symbol.position = pt;
                symbol.setZ(
                    seriesModel.get('zlevel'),
                    seriesModel.get('z')
                );
                symbol.ignore = isNaN(pt[0]) || isNaN(pt[1]);
P
pissang 已提交
599
                (symbol as SymbolExtended).__temp = true;
S
sushuang 已提交
600
                data.setItemGraphicEl(dataIndex, symbol);
L
lang 已提交
601

S
sushuang 已提交
602 603
                // Stop scale animation
                symbol.stopSymbolAnimation(true);
L
lang 已提交
604

S
sushuang 已提交
605 606 607 608 609 610 611 612 613 614
                this.group.add(symbol);
            }
            symbol.highlight();
        }
        else {
            // Highlight whole series
            ChartView.prototype.highlight.call(
                this, seriesModel, ecModel, api, payload
            );
        }
P
pissang 已提交
615
    }
S
sushuang 已提交
616

P
pissang 已提交
617 618 619 620 621 622
    downplay(
        seriesModel: LineSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: Payload
    ) {
S
sushuang 已提交
623
        var data = seriesModel.getData();
P
pissang 已提交
624
        var dataIndex = modelUtil.queryDataIndex(data, payload) as number;
S
sushuang 已提交
625
        if (dataIndex != null && dataIndex >= 0) {
P
pissang 已提交
626
            var symbol = data.getItemGraphicEl(dataIndex) as SymbolExtended;
S
sushuang 已提交
627 628 629 630 631 632 633
            if (symbol) {
                if (symbol.__temp) {
                    data.setItemGraphicEl(dataIndex, null);
                    this.group.remove(symbol);
                }
                else {
                    symbol.downplay();
L
lang 已提交
634
                }
L
lang 已提交
635
            }
S
sushuang 已提交
636 637 638 639 640 641 642 643 644
        }
        else {
            // FIXME
            // can not downplay completely.
            // Downplay whole series
            ChartView.prototype.downplay.call(
                this, seriesModel, ecModel, api, payload
            );
        }
P
pissang 已提交
645
    }
L
lang 已提交
646

P
pissang 已提交
647
    _newPolyline(points: number[][]) {
S
sushuang 已提交
648 649 650 651 652
        var polyline = this._polyline;
        // Remove previous created polyline
        if (polyline) {
            this._lineGroup.remove(polyline);
        }
L
lang 已提交
653

P
pissang 已提交
654
        polyline = new ECPolyline({
S
sushuang 已提交
655 656 657 658 659 660
            shape: {
                points: points
            },
            silent: true,
            z2: 10
        });
661

S
sushuang 已提交
662
        this._lineGroup.add(polyline);
L
lang 已提交
663

S
sushuang 已提交
664
        this._polyline = polyline;
L
lang 已提交
665

S
sushuang 已提交
666
        return polyline;
P
pissang 已提交
667
    }
L
lang 已提交
668

P
pissang 已提交
669
    _newPolygon(points: number[][], stackedOnPoints: number[][]) {
S
sushuang 已提交
670 671 672 673 674
        var polygon = this._polygon;
        // Remove previous created polygon
        if (polygon) {
            this._lineGroup.remove(polygon);
        }
L
lang 已提交
675

P
pissang 已提交
676
        polygon = new ECPolygon({
S
sushuang 已提交
677 678 679 680 681 682
            shape: {
                points: points,
                stackedOnPoints: stackedOnPoints
            },
            silent: true
        });
L
lang 已提交
683

S
sushuang 已提交
684
        this._lineGroup.add(polygon);
L
lang 已提交
685

S
sushuang 已提交
686 687
        this._polygon = polygon;
        return polygon;
P
pissang 已提交
688
    }
689

S
sushuang 已提交
690 691 692 693
    /**
     * @private
     */
    // FIXME Two value axis
P
pissang 已提交
694 695 696 697 698 699 700 701
    _updateAnimation(
        data: List,
        stackedOnPoints: number[][],
        coordSys: Cartesian2D | Polar,
        api: ExtensionAPI,
        step: LineSeriesOption['step'],
        valueOrigin: LineSeriesOption['areaStyle']['origin']
    ) {
S
sushuang 已提交
702 703 704 705 706 707 708
        var polyline = this._polyline;
        var polygon = this._polygon;
        var seriesModel = data.hostModel;

        var diff = lineAnimationDiff(
            this._data, data,
            this._stackedOnPoints, stackedOnPoints,
S
sushuang 已提交
709 710
            this._coordSys, coordSys,
            this._valueOrigin, valueOrigin
S
sushuang 已提交
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
        );

        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
            current = turnPointsIntoStep(diff.current, coordSys, step);
            stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, coordSys, step);
            next = turnPointsIntoStep(diff.next, coordSys, step);
            stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step);
        }
        // `diff.current` is subset of `current` (which should be ensured by
        // turnPointsIntoStep), so points in `__points` can be updated when
        // points in `current` are update during animation.
P
pissang 已提交
727
        (polyline.shape as any).__points = diff.current;
S
sushuang 已提交
728
        polyline.shape.points = current;
L
lang 已提交
729

S
sushuang 已提交
730 731 732
        graphic.updateProps(polyline, {
            shape: {
                points: next
L
lang 已提交
733
            }
S
sushuang 已提交
734
        }, seriesModel);
L
lang 已提交
735

S
sushuang 已提交
736 737 738 739 740 741
        if (polygon) {
            polygon.setShape({
                points: current,
                stackedOnPoints: stackedOnCurrent
            });
            graphic.updateProps(polygon, {
L
lang 已提交
742
                shape: {
S
sushuang 已提交
743 744
                    points: next,
                    stackedOnPoints: stackedOnNext
L
lang 已提交
745
                }
L
lang 已提交
746
            }, seriesModel);
S
sushuang 已提交
747
        }
L
lang 已提交
748

P
pissang 已提交
749 750 751 752
        var updatedDataInfo: {
            el: SymbolExtended,
            ptIdx: number
        }[] = [];
S
sushuang 已提交
753 754 755 756 757
        var diffStatus = diff.status;

        for (var i = 0; i < diffStatus.length; i++) {
            var cmd = diffStatus[i].cmd;
            if (cmd === '=') {
P
pissang 已提交
758
                var el = data.getItemGraphicEl(diffStatus[i].idx1) as SymbolExtended;
S
sushuang 已提交
759 760 761 762 763
                if (el) {
                    updatedDataInfo.push({
                        el: el,
                        ptIdx: i    // Index of points
                    });
L
lang 已提交
764
                }
L
lang 已提交
765
            }
S
sushuang 已提交
766
        }
L
lang 已提交
767

S
sushuang 已提交
768 769 770 771
        if (polyline.animators && polyline.animators.length) {
            polyline.animators[0].during(function () {
                for (var i = 0; i < updatedDataInfo.length; i++) {
                    var el = updatedDataInfo[i].el;
P
pissang 已提交
772
                    el.attr('position', (polyline.shape as any).__points[updatedDataInfo[i].ptIdx]);
773 774
                }
            });
L
lang 已提交
775
        }
P
pissang 已提交
776
    }
S
sushuang 已提交
777

P
pissang 已提交
778
    remove(ecModel: GlobalModel) {
S
sushuang 已提交
779 780 781 782 783
        var group = this.group;
        var oldData = this._data;
        this._lineGroup.removeAll();
        this._symbolDraw.remove(true);
        // Remove temporary created elements when highlighting
P
pissang 已提交
784
        oldData && oldData.eachItemGraphicEl(function (el: SymbolExtended, idx) {
S
sushuang 已提交
785 786 787 788 789 790
            if (el.__temp) {
                group.remove(el);
                oldData.setItemGraphicEl(idx, null);
            }
        });

S
sushuang 已提交
791 792 793 794 795 796
        this._polyline =
            this._polygon =
            this._coordSys =
            this._points =
            this._stackedOnPoints =
            this._data = null;
S
sushuang 已提交
797
    }
P
pissang 已提交
798 799 800 801 802
}

ChartView.registerClass(LineView);

export default ChartView;