diff --git a/src/chart/line/LineSeries.ts b/src/chart/line/LineSeries.ts index 9faf5c5175..a0804099e6 100644 --- a/src/chart/line/LineSeries.ts +++ b/src/chart/line/LineSeries.ts @@ -69,6 +69,10 @@ export interface LineEndLabelOption extends SeriesLabelOption { valueAnimation?: boolean } +export interface LinePiece { + startDataIndices: number[] + lineStyle: LineStyleOption[] +} export interface LineSeriesOption extends SeriesOption, LineStateOptionMixin & { emphasis?: { @@ -99,6 +103,7 @@ export interface LineSeriesOption extends SeriesOption; _points: ArrayLike; @@ -624,6 +625,7 @@ class LineView extends ChartView { this._symbolDraw = symbolDraw; this._lineGroup = lineGroup; + this._linePieces = []; this._changePolyState = zrUtil.bind(this._changePolyState, this); } @@ -644,6 +646,9 @@ class LineView extends ChartView { let polyline = this._polyline; let polygon = this._polygon; + const linePieces = seriesModel.get('linePieces'); + const useCompoundPaths = linePieces && linePieces.length; + const lineGroup = this._lineGroup; const hasAnimation = !ecModel.ssr && seriesModel.get('animation'); @@ -727,15 +732,29 @@ class LineView extends ChartView { } } - polyline = this._newPolyline(points); - if (isAreaChart) { - polygon = this._newPolygon( - points, stackedOnPoints + if (useCompoundPaths) { + this._newCompoundLines( + seriesModel, + linePieces, + coordSys, + api, + hasAnimation, + points, + valueOrigin ); - }// If areaStyle is removed - else if (polygon) { - lineGroup.remove(polygon); - polygon = this._polygon = null; + return; + } + else { + 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. @@ -1062,6 +1081,67 @@ class LineView extends ChartView { return polygon; } + _newCompoundLines( + seriesModel: LineSeriesModel, + linePieces: LinePiece[], + coordSys: Cartesian2D | Polar, + api: ExtensionAPI, + hasAnimation: boolean, + points: ArrayLike, + valueOrigin: LineSeriesOption['areaStyle']['origin'] + ) { + this._linePieces = []; + const dataCount = seriesModel.getData().count(); + // The segments that are not in pieces takes the last piece index + const NOT_IN_PIECES_INDEX = linePieces.length; + const paths: number[][][] = [] + for (let i = 0; i < dataCount - 1; ++i) { + let pieceId = NOT_IN_PIECES_INDEX; + for (let j = 0; j < linePieces.length; ++j) { + if (linePieces[j].startDataIndices.indexOf(i) >= 0) { + pieceId = j; + break; + } + } + if (paths[pieceId] == null) { + paths[pieceId] = []; + } + paths[pieceId].push([ + points[i * 2], + points[i * 2 + 1], + points[i * 2 + 2], + points[i * 2 + 3] + ]) + } + + const excludeLast = true; // TODO: only for debug + for (let i = 0; i < paths.length - (excludeLast ? 1 : 0); ++i) { + if (paths[i]) { + const lineStyle = i === NOT_IN_PIECES_INDEX + ? seriesModel.getLineStyle() + : new Model(linePieces[i].lineStyle).getLineStyle(); + // console.log(lineStyle) + const path = new graphic.CompoundPath({ + shape: { + paths: zrUtil.map(paths[i], p => new graphic.Line({ + shape: { + x1: p[0], + y1: p[1], + x2: p[2], + y2: p[3] + } + })) + }, + style: lineStyle, // TODO: only for debug + segmentIgnoreThreshold: 2, + z2: 10 + }); + this._linePieces.push(path); + this._lineGroup.add(path); + } + } + } + _initSymbolLabelAnimation( data: SeriesData, coordSys: Polar | Cartesian2D, diff --git a/test/line-pieces.html b/test/line-pieces.html new file mode 100644 index 0000000000..a4e314e2a5 --- /dev/null +++ b/test/line-pieces.html @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +