| /* | 
 | * 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 LineDraw from '../helper/LineDraw'; | 
 | import EffectLine from '../helper/EffectLine'; | 
 | import Line from '../helper/Line'; | 
 | import Polyline from '../helper/Polyline'; | 
 | import EffectPolyline from '../helper/EffectPolyline'; | 
 | import LargeLineDraw from '../helper/LargeLineDraw'; | 
 | import linesLayout from './linesLayout'; | 
 | import {createClipPath} from '../helper/createClipPathFromCoordSys'; | 
 | import ChartView from '../../view/Chart'; | 
 | import LinesSeriesModel from './LinesSeries'; | 
 | import GlobalModel from '../../model/Global'; | 
 | import ExtensionAPI from '../../core/ExtensionAPI'; | 
 | import CanvasPainter from 'zrender/src/canvas/Painter'; | 
 | import { StageHandlerProgressParams, StageHandlerProgressExecutor } from '../../util/types'; | 
 | import SeriesData from '../../data/SeriesData'; | 
 | import type Polar from '../../coord/polar/Polar'; | 
 | import type Cartesian2D from '../../coord/cartesian/Cartesian2D'; | 
 | import Element from 'zrender/src/Element'; | 
 |  | 
 | class LinesView extends ChartView { | 
 |  | 
 |     static readonly type = 'lines'; | 
 |     readonly type = LinesView.type; | 
 |  | 
 |     private _lastZlevel: number; | 
 |     private _finished: boolean; | 
 |  | 
 |     private _lineDraw: LineDraw | LargeLineDraw; | 
 |  | 
 |     private _hasEffet: boolean; | 
 |     private _isPolyline: boolean; | 
 |     private _isLargeDraw: boolean; | 
 |  | 
 |     render(seriesModel: LinesSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) { | 
 |         const data = seriesModel.getData(); | 
 |  | 
 |         const lineDraw = this._updateLineDraw(data, seriesModel); | 
 |  | 
 |         const zlevel = seriesModel.get('zlevel'); | 
 |         const trailLength = seriesModel.get(['effect', 'trailLength']); | 
 |  | 
 |         const zr = api.getZr(); | 
 |         // Avoid the drag cause ghost shadow | 
 |         // FIXME Better way ? | 
 |         // SVG doesn't support | 
 |         const isSvg = zr.painter.getType() === 'svg'; | 
 |         if (!isSvg) { | 
 |             (zr.painter as CanvasPainter).getLayer(zlevel).clear(true); | 
 |         } | 
 |         // Config layer with motion blur | 
 |         if (this._lastZlevel != null && !isSvg) { | 
 |             zr.configLayer(this._lastZlevel, { | 
 |                 motionBlur: false | 
 |             }); | 
 |         } | 
 |         if (this._showEffect(seriesModel) && trailLength > 0) { | 
 |             if (!isSvg) { | 
 |                 zr.configLayer(zlevel, { | 
 |                     motionBlur: true, | 
 |                     lastFrameAlpha: Math.max(Math.min(trailLength / 10 + 0.9, 1), 0) | 
 |                 }); | 
 |             } | 
 |             else if (__DEV__) { | 
 |                 console.warn('SVG render mode doesn\'t support lines with trail effect'); | 
 |             } | 
 |         } | 
 |  | 
 |         lineDraw.updateData(data as SeriesData); | 
 |  | 
 |         const clipPath = seriesModel.get('clip', true) && createClipPath( | 
 |             (seriesModel.coordinateSystem as Polar | Cartesian2D), false, seriesModel | 
 |         ); | 
 |         if (clipPath) { | 
 |             this.group.setClipPath(clipPath); | 
 |         } | 
 |         else { | 
 |             this.group.removeClipPath(); | 
 |         } | 
 |  | 
 |         this._lastZlevel = zlevel; | 
 |  | 
 |         this._finished = true; | 
 |     } | 
 |  | 
 |     incrementalPrepareRender(seriesModel: LinesSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) { | 
 |         const data = seriesModel.getData(); | 
 |  | 
 |         const lineDraw = this._updateLineDraw(data, seriesModel); | 
 |  | 
 |         lineDraw.incrementalPrepareUpdate(data as any); | 
 |  | 
 |         this._clearLayer(api); | 
 |  | 
 |         this._finished = false; | 
 |     } | 
 |  | 
 |     incrementalRender( | 
 |         taskParams: StageHandlerProgressParams, | 
 |         seriesModel: LinesSeriesModel, | 
 |         ecModel: GlobalModel | 
 |     ) { | 
 |         this._lineDraw.incrementalUpdate(taskParams, seriesModel.getData() as any); | 
 |  | 
 |         this._finished = taskParams.end === seriesModel.getData().count(); | 
 |     } | 
 |  | 
 |     eachRendered(cb: (el: Element) => boolean | void) { | 
 |         this._lineDraw && this._lineDraw.eachRendered(cb); | 
 |     } | 
 |  | 
 |     updateTransform(seriesModel: LinesSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) { | 
 |         const data = seriesModel.getData(); | 
 |         const pipelineContext = seriesModel.pipelineContext; | 
 |  | 
 |         if (!this._finished || pipelineContext.large || pipelineContext.progressiveRender) { | 
 |             // TODO Don't have to do update in large mode. Only do it when there are millions of data. | 
 |             return { | 
 |                 update: true | 
 |             } as const; | 
 |         } | 
 |         else { | 
 |             // TODO Use same logic with ScatterView. | 
 |             // Manually update layout | 
 |             const res = linesLayout.reset(seriesModel, ecModel, api) as StageHandlerProgressExecutor; | 
 |             if (res.progress) { | 
 |                 res.progress({ | 
 |                     start: 0, | 
 |                     end: data.count(), | 
 |                     count: data.count() | 
 |                 }, data); | 
 |             } | 
 |             // Not in large mode | 
 |             (this._lineDraw as LineDraw).updateLayout(); | 
 |             this._clearLayer(api); | 
 |         } | 
 |     } | 
 |  | 
 |     _updateLineDraw(data: SeriesData, seriesModel: LinesSeriesModel) { | 
 |         let lineDraw = this._lineDraw; | 
 |         const hasEffect = this._showEffect(seriesModel); | 
 |         const isPolyline = !!seriesModel.get('polyline'); | 
 |         const pipelineContext = seriesModel.pipelineContext; | 
 |         const isLargeDraw = pipelineContext.large; | 
 |  | 
 |         if (__DEV__) { | 
 |             if (hasEffect && isLargeDraw) { | 
 |                 console.warn('Large lines not support effect'); | 
 |             } | 
 |         } | 
 |         if (!lineDraw | 
 |             || hasEffect !== this._hasEffet | 
 |             || isPolyline !== this._isPolyline | 
 |             || isLargeDraw !== this._isLargeDraw | 
 |         ) { | 
 |             if (lineDraw) { | 
 |                 lineDraw.remove(); | 
 |             } | 
 |             lineDraw = this._lineDraw = isLargeDraw | 
 |                 ? new LargeLineDraw() | 
 |                 : new LineDraw( | 
 |                     isPolyline | 
 |                         ? (hasEffect ? EffectPolyline : Polyline) | 
 |                         : (hasEffect ? EffectLine : Line) | 
 |                 ); | 
 |             this._hasEffet = hasEffect; | 
 |             this._isPolyline = isPolyline; | 
 |             this._isLargeDraw = isLargeDraw; | 
 |         } | 
 |  | 
 |         this.group.add(lineDraw.group); | 
 |  | 
 |         return lineDraw; | 
 |     } | 
 |  | 
 |     private _showEffect(seriesModel: LinesSeriesModel) { | 
 |         return !!seriesModel.get(['effect', 'show']); | 
 |     } | 
 |  | 
 |     _clearLayer(api: ExtensionAPI) { | 
 |         // Not use motion when dragging or zooming | 
 |         const zr = api.getZr(); | 
 |         const isSvg = zr.painter.getType() === 'svg'; | 
 |         if (!isSvg && this._lastZlevel != null) { | 
 |             (zr.painter as CanvasPainter).getLayer(this._lastZlevel).clear(true); | 
 |         } | 
 |     } | 
 |  | 
 |     remove(ecModel: GlobalModel, api: ExtensionAPI) { | 
 |         this._lineDraw && this._lineDraw.remove(); | 
 |         this._lineDraw = null; | 
 |         // Clear motion when lineDraw is removed | 
 |         this._clearLayer(api); | 
 |     } | 
 |  | 
 |     dispose(ecModel: GlobalModel, api: ExtensionAPI) { | 
 |         this.remove(ecModel, api); | 
 |     } | 
 |  | 
 | } | 
 |  | 
 | export default LinesView; |