LineView.js 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. import { __extends } from "tslib";
  41. // FIXME step not support polar
  42. import * as zrUtil from 'zrender/lib/core/util.js';
  43. import SymbolDraw from '../helper/SymbolDraw.js';
  44. import SymbolClz from '../helper/Symbol.js';
  45. import lineAnimationDiff from './lineAnimationDiff.js';
  46. import * as graphic from '../../util/graphic.js';
  47. import * as modelUtil from '../../util/model.js';
  48. import { ECPolyline, ECPolygon } from './poly.js';
  49. import ChartView from '../../view/Chart.js';
  50. import { prepareDataCoordInfo, getStackedOnPoint } from './helper.js';
  51. import { createGridClipPath, createPolarClipPath } from '../helper/createClipPathFromCoordSys.js';
  52. import { isCoordinateSystemType } from '../../coord/CoordinateSystem.js';
  53. import { setStatesStylesFromModel, setStatesFlag, toggleHoverEmphasis, SPECIAL_STATES } from '../../util/states.js';
  54. import { setLabelStyle, getLabelStatesModels, labelInner } from '../../label/labelStyle.js';
  55. import { getDefaultLabel, getDefaultInterpolatedLabel } from '../helper/labelHelper.js';
  56. import { getECData } from '../../util/innerStore.js';
  57. import { createFloat32Array } from '../../util/vendor.js';
  58. import { convertToColorString } from '../../util/format.js';
  59. import { lerp } from 'zrender/lib/tool/color.js';
  60. function isPointsSame(points1, points2) {
  61. if (points1.length !== points2.length) {
  62. return;
  63. }
  64. for (var i = 0; i < points1.length; i++) {
  65. if (points1[i] !== points2[i]) {
  66. return;
  67. }
  68. }
  69. return true;
  70. }
  71. function bboxFromPoints(points) {
  72. var minX = Infinity;
  73. var minY = Infinity;
  74. var maxX = -Infinity;
  75. var maxY = -Infinity;
  76. for (var i = 0; i < points.length;) {
  77. var x = points[i++];
  78. var y = points[i++];
  79. if (!isNaN(x)) {
  80. minX = Math.min(x, minX);
  81. maxX = Math.max(x, maxX);
  82. }
  83. if (!isNaN(y)) {
  84. minY = Math.min(y, minY);
  85. maxY = Math.max(y, maxY);
  86. }
  87. }
  88. return [[minX, minY], [maxX, maxY]];
  89. }
  90. function getBoundingDiff(points1, points2) {
  91. var _a = bboxFromPoints(points1),
  92. min1 = _a[0],
  93. max1 = _a[1];
  94. var _b = bboxFromPoints(points2),
  95. min2 = _b[0],
  96. max2 = _b[1];
  97. // Get a max value from each corner of two boundings.
  98. 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]));
  99. }
  100. function getSmooth(smooth) {
  101. return zrUtil.isNumber(smooth) ? smooth : smooth ? 0.5 : 0;
  102. }
  103. function getStackedOnPoints(coordSys, data, dataCoordInfo) {
  104. if (!dataCoordInfo.valueDim) {
  105. return [];
  106. }
  107. var len = data.count();
  108. var points = createFloat32Array(len * 2);
  109. for (var idx = 0; idx < len; idx++) {
  110. var pt = getStackedOnPoint(dataCoordInfo, coordSys, data, idx);
  111. points[idx * 2] = pt[0];
  112. points[idx * 2 + 1] = pt[1];
  113. }
  114. return points;
  115. }
  116. /**
  117. * Filter the null data and extend data for step considering `stepTurnAt`
  118. *
  119. * @param points data to convert, that may containing null
  120. * @param basePoints base data to reference, used only for areaStyle points
  121. * @param coordSys coordinate system
  122. * @param stepTurnAt 'start' | 'end' | 'middle' | true
  123. * @param connectNulls whether to connect nulls
  124. * @returns converted point positions
  125. */
  126. function turnPointsIntoStep(points, basePoints, coordSys, stepTurnAt, connectNulls) {
  127. var baseAxis = coordSys.getBaseAxis();
  128. var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1;
  129. var stepPoints = [];
  130. var i = 0;
  131. var stepPt = [];
  132. var pt = [];
  133. var nextPt = [];
  134. var filteredPoints = [];
  135. if (connectNulls) {
  136. for (i = 0; i < points.length; i += 2) {
  137. /**
  138. * For areaStyle of stepped lines, `stackedOnPoints` should be
  139. * filtered the same as `points` so that the base axis values
  140. * should stay the same as the lines above. See #20021
  141. */
  142. var reference = basePoints || points;
  143. if (!isNaN(reference[i]) && !isNaN(reference[i + 1])) {
  144. filteredPoints.push(points[i], points[i + 1]);
  145. }
  146. }
  147. points = filteredPoints;
  148. }
  149. for (i = 0; i < points.length - 2; i += 2) {
  150. nextPt[0] = points[i + 2];
  151. nextPt[1] = points[i + 3];
  152. pt[0] = points[i];
  153. pt[1] = points[i + 1];
  154. stepPoints.push(pt[0], pt[1]);
  155. switch (stepTurnAt) {
  156. case 'end':
  157. stepPt[baseIndex] = nextPt[baseIndex];
  158. stepPt[1 - baseIndex] = pt[1 - baseIndex];
  159. stepPoints.push(stepPt[0], stepPt[1]);
  160. break;
  161. case 'middle':
  162. var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2;
  163. var stepPt2 = [];
  164. stepPt[baseIndex] = stepPt2[baseIndex] = middle;
  165. stepPt[1 - baseIndex] = pt[1 - baseIndex];
  166. stepPt2[1 - baseIndex] = nextPt[1 - baseIndex];
  167. stepPoints.push(stepPt[0], stepPt[1]);
  168. stepPoints.push(stepPt2[0], stepPt2[1]);
  169. break;
  170. default:
  171. // default is start
  172. stepPt[baseIndex] = pt[baseIndex];
  173. stepPt[1 - baseIndex] = nextPt[1 - baseIndex];
  174. stepPoints.push(stepPt[0], stepPt[1]);
  175. }
  176. }
  177. // Last points
  178. stepPoints.push(points[i++], points[i++]);
  179. return stepPoints;
  180. }
  181. /**
  182. * Clip color stops to edge. Avoid creating too large gradients.
  183. * Which may lead to blurry when GPU acceleration is enabled. See #15680
  184. *
  185. * The stops has been sorted from small to large.
  186. */
  187. function clipColorStops(colorStops, maxSize) {
  188. var newColorStops = [];
  189. var len = colorStops.length;
  190. // coord will always < 0 in prevOutOfRangeColorStop.
  191. var prevOutOfRangeColorStop;
  192. var prevInRangeColorStop;
  193. function lerpStop(stop0, stop1, clippedCoord) {
  194. var coord0 = stop0.coord;
  195. var p = (clippedCoord - coord0) / (stop1.coord - coord0);
  196. var color = lerp(p, [stop0.color, stop1.color]);
  197. return {
  198. coord: clippedCoord,
  199. color: color
  200. };
  201. }
  202. for (var i = 0; i < len; i++) {
  203. var stop_1 = colorStops[i];
  204. var coord = stop_1.coord;
  205. if (coord < 0) {
  206. prevOutOfRangeColorStop = stop_1;
  207. } else if (coord > maxSize) {
  208. if (prevInRangeColorStop) {
  209. newColorStops.push(lerpStop(prevInRangeColorStop, stop_1, maxSize));
  210. } else if (prevOutOfRangeColorStop) {
  211. // If there are two stops and coord range is between these two stops
  212. newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0), lerpStop(prevOutOfRangeColorStop, stop_1, maxSize));
  213. }
  214. // All following stop will be out of range. So just ignore them.
  215. break;
  216. } else {
  217. if (prevOutOfRangeColorStop) {
  218. newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0));
  219. // Reset
  220. prevOutOfRangeColorStop = null;
  221. }
  222. newColorStops.push(stop_1);
  223. prevInRangeColorStop = stop_1;
  224. }
  225. }
  226. return newColorStops;
  227. }
  228. function getVisualGradient(data, coordSys, api) {
  229. var visualMetaList = data.getVisual('visualMeta');
  230. if (!visualMetaList || !visualMetaList.length || !data.count()) {
  231. // When data.count() is 0, gradient range can not be calculated.
  232. return;
  233. }
  234. if (coordSys.type !== 'cartesian2d') {
  235. if (process.env.NODE_ENV !== 'production') {
  236. console.warn('Visual map on line style is only supported on cartesian2d.');
  237. }
  238. return;
  239. }
  240. var coordDim;
  241. var visualMeta;
  242. for (var i = visualMetaList.length - 1; i >= 0; i--) {
  243. var dimInfo = data.getDimensionInfo(visualMetaList[i].dimension);
  244. coordDim = dimInfo && dimInfo.coordDim;
  245. // Can only be x or y
  246. if (coordDim === 'x' || coordDim === 'y') {
  247. visualMeta = visualMetaList[i];
  248. break;
  249. }
  250. }
  251. if (!visualMeta) {
  252. if (process.env.NODE_ENV !== 'production') {
  253. console.warn('Visual map on line style only support x or y dimension.');
  254. }
  255. return;
  256. }
  257. // If the area to be rendered is bigger than area defined by LinearGradient,
  258. // the canvas spec prescribes that the color of the first stop and the last
  259. // stop should be used. But if two stops are added at offset 0, in effect
  260. // browsers use the color of the second stop to render area outside
  261. // LinearGradient. So we can only infinitesimally extend area defined in
  262. // LinearGradient to render `outerColors`.
  263. var axis = coordSys.getAxis(coordDim);
  264. // dataToCoord mapping may not be linear, but must be monotonic.
  265. var colorStops = zrUtil.map(visualMeta.stops, function (stop) {
  266. // offset will be calculated later.
  267. return {
  268. coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)),
  269. color: stop.color
  270. };
  271. });
  272. var stopLen = colorStops.length;
  273. var outerColors = visualMeta.outerColors.slice();
  274. if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) {
  275. colorStops.reverse();
  276. outerColors.reverse();
  277. }
  278. var colorStopsInRange = clipColorStops(colorStops, coordDim === 'x' ? api.getWidth() : api.getHeight());
  279. var inRangeStopLen = colorStopsInRange.length;
  280. if (!inRangeStopLen && stopLen) {
  281. // All stops are out of range. All will be the same color.
  282. return colorStops[0].coord < 0 ? outerColors[1] ? outerColors[1] : colorStops[stopLen - 1].color : outerColors[0] ? outerColors[0] : colorStops[0].color;
  283. }
  284. var tinyExtent = 10; // Arbitrary value: 10px
  285. var minCoord = colorStopsInRange[0].coord - tinyExtent;
  286. var maxCoord = colorStopsInRange[inRangeStopLen - 1].coord + tinyExtent;
  287. var coordSpan = maxCoord - minCoord;
  288. if (coordSpan < 1e-3) {
  289. return 'transparent';
  290. }
  291. zrUtil.each(colorStopsInRange, function (stop) {
  292. stop.offset = (stop.coord - minCoord) / coordSpan;
  293. });
  294. colorStopsInRange.push({
  295. // NOTE: inRangeStopLen may still be 0 if stoplen is zero.
  296. offset: inRangeStopLen ? colorStopsInRange[inRangeStopLen - 1].offset : 0.5,
  297. color: outerColors[1] || 'transparent'
  298. });
  299. colorStopsInRange.unshift({
  300. offset: inRangeStopLen ? colorStopsInRange[0].offset : 0.5,
  301. color: outerColors[0] || 'transparent'
  302. });
  303. var gradient = new graphic.LinearGradient(0, 0, 0, 0, colorStopsInRange, true);
  304. gradient[coordDim] = minCoord;
  305. gradient[coordDim + '2'] = maxCoord;
  306. return gradient;
  307. }
  308. function getIsIgnoreFunc(seriesModel, data, coordSys) {
  309. var showAllSymbol = seriesModel.get('showAllSymbol');
  310. var isAuto = showAllSymbol === 'auto';
  311. if (showAllSymbol && !isAuto) {
  312. return;
  313. }
  314. var categoryAxis = coordSys.getAxesByScale('ordinal')[0];
  315. if (!categoryAxis) {
  316. return;
  317. }
  318. // Note that category label interval strategy might bring some weird effect
  319. // in some scenario: users may wonder why some of the symbols are not
  320. // displayed. So we show all symbols as possible as we can.
  321. if (isAuto
  322. // Simplify the logic, do not determine label overlap here.
  323. && canShowAllSymbolForCategory(categoryAxis, data)) {
  324. return;
  325. }
  326. // Otherwise follow the label interval strategy on category axis.
  327. var categoryDataDim = data.mapDimension(categoryAxis.dim);
  328. var labelMap = {};
  329. zrUtil.each(categoryAxis.getViewLabels(), function (labelItem) {
  330. var ordinalNumber = categoryAxis.scale.getRawOrdinalNumber(labelItem.tickValue);
  331. labelMap[ordinalNumber] = 1;
  332. });
  333. return function (dataIndex) {
  334. return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex));
  335. };
  336. }
  337. function canShowAllSymbolForCategory(categoryAxis, data) {
  338. // In most cases, line is monotonous on category axis, and the label size
  339. // is close with each other. So we check the symbol size and some of the
  340. // label size alone with the category axis to estimate whether all symbol
  341. // can be shown without overlap.
  342. var axisExtent = categoryAxis.getExtent();
  343. var availSize = Math.abs(axisExtent[1] - axisExtent[0]) / categoryAxis.scale.count();
  344. isNaN(availSize) && (availSize = 0); // 0/0 is NaN.
  345. // Sampling some points, max 5.
  346. var dataLen = data.count();
  347. var step = Math.max(1, Math.round(dataLen / 5));
  348. for (var dataIndex = 0; dataIndex < dataLen; dataIndex += step) {
  349. if (SymbolClz.getSymbolSize(data, dataIndex
  350. // Only for cartesian, where `isHorizontal` exists.
  351. )[categoryAxis.isHorizontal() ? 1 : 0]
  352. // Empirical number
  353. * 1.5 > availSize) {
  354. return false;
  355. }
  356. }
  357. return true;
  358. }
  359. function isPointNull(x, y) {
  360. return isNaN(x) || isNaN(y);
  361. }
  362. function getLastIndexNotNull(points) {
  363. var len = points.length / 2;
  364. for (; len > 0; len--) {
  365. if (!isPointNull(points[len * 2 - 2], points[len * 2 - 1])) {
  366. break;
  367. }
  368. }
  369. return len - 1;
  370. }
  371. function getPointAtIndex(points, idx) {
  372. return [points[idx * 2], points[idx * 2 + 1]];
  373. }
  374. function getIndexRange(points, xOrY, dim) {
  375. var len = points.length / 2;
  376. var dimIdx = dim === 'x' ? 0 : 1;
  377. var a;
  378. var b;
  379. var prevIndex = 0;
  380. var nextIndex = -1;
  381. for (var i = 0; i < len; i++) {
  382. b = points[i * 2 + dimIdx];
  383. if (isNaN(b) || isNaN(points[i * 2 + 1 - dimIdx])) {
  384. continue;
  385. }
  386. if (i === 0) {
  387. a = b;
  388. continue;
  389. }
  390. if (a <= xOrY && b >= xOrY || a >= xOrY && b <= xOrY) {
  391. nextIndex = i;
  392. break;
  393. }
  394. prevIndex = i;
  395. a = b;
  396. }
  397. return {
  398. range: [prevIndex, nextIndex],
  399. t: (xOrY - a) / (b - a)
  400. };
  401. }
  402. function anyStateShowEndLabel(seriesModel) {
  403. if (seriesModel.get(['endLabel', 'show'])) {
  404. return true;
  405. }
  406. for (var i = 0; i < SPECIAL_STATES.length; i++) {
  407. if (seriesModel.get([SPECIAL_STATES[i], 'endLabel', 'show'])) {
  408. return true;
  409. }
  410. }
  411. return false;
  412. }
  413. function createLineClipPath(lineView, coordSys, hasAnimation, seriesModel) {
  414. if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
  415. var endLabelModel_1 = seriesModel.getModel('endLabel');
  416. var valueAnimation_1 = endLabelModel_1.get('valueAnimation');
  417. var data_1 = seriesModel.getData();
  418. var labelAnimationRecord_1 = {
  419. lastFrameIndex: 0
  420. };
  421. var during = anyStateShowEndLabel(seriesModel) ? function (percent, clipRect) {
  422. lineView._endLabelOnDuring(percent, clipRect, data_1, labelAnimationRecord_1, valueAnimation_1, endLabelModel_1, coordSys);
  423. } : null;
  424. var isHorizontal = coordSys.getBaseAxis().isHorizontal();
  425. var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel, function () {
  426. var endLabel = lineView._endLabel;
  427. if (endLabel && hasAnimation) {
  428. if (labelAnimationRecord_1.originalX != null) {
  429. endLabel.attr({
  430. x: labelAnimationRecord_1.originalX,
  431. y: labelAnimationRecord_1.originalY
  432. });
  433. }
  434. }
  435. }, during);
  436. // Expand clip shape to avoid clipping when line value exceeds axis
  437. if (!seriesModel.get('clip', true)) {
  438. var rectShape = clipPath.shape;
  439. var expandSize = Math.max(rectShape.width, rectShape.height);
  440. if (isHorizontal) {
  441. rectShape.y -= expandSize;
  442. rectShape.height += expandSize * 2;
  443. } else {
  444. rectShape.x -= expandSize;
  445. rectShape.width += expandSize * 2;
  446. }
  447. }
  448. // Set to the final frame. To make sure label layout is right.
  449. if (during) {
  450. during(1, clipPath);
  451. }
  452. return clipPath;
  453. } else {
  454. if (process.env.NODE_ENV !== 'production') {
  455. if (seriesModel.get(['endLabel', 'show'])) {
  456. console.warn('endLabel is not supported for lines in polar systems.');
  457. }
  458. }
  459. return createPolarClipPath(coordSys, hasAnimation, seriesModel);
  460. }
  461. }
  462. function getEndLabelStateSpecified(endLabelModel, coordSys) {
  463. var baseAxis = coordSys.getBaseAxis();
  464. var isHorizontal = baseAxis.isHorizontal();
  465. var isBaseInversed = baseAxis.inverse;
  466. var align = isHorizontal ? isBaseInversed ? 'right' : 'left' : 'center';
  467. var verticalAlign = isHorizontal ? 'middle' : isBaseInversed ? 'top' : 'bottom';
  468. return {
  469. normal: {
  470. align: endLabelModel.get('align') || align,
  471. verticalAlign: endLabelModel.get('verticalAlign') || verticalAlign
  472. }
  473. };
  474. }
  475. var LineView = /** @class */function (_super) {
  476. __extends(LineView, _super);
  477. function LineView() {
  478. return _super !== null && _super.apply(this, arguments) || this;
  479. }
  480. LineView.prototype.init = function () {
  481. var lineGroup = new graphic.Group();
  482. var symbolDraw = new SymbolDraw();
  483. this.group.add(symbolDraw.group);
  484. this._symbolDraw = symbolDraw;
  485. this._lineGroup = lineGroup;
  486. this._changePolyState = zrUtil.bind(this._changePolyState, this);
  487. };
  488. LineView.prototype.render = function (seriesModel, ecModel, api) {
  489. var coordSys = seriesModel.coordinateSystem;
  490. var group = this.group;
  491. var data = seriesModel.getData();
  492. var lineStyleModel = seriesModel.getModel('lineStyle');
  493. var areaStyleModel = seriesModel.getModel('areaStyle');
  494. var points = data.getLayout('points') || [];
  495. var isCoordSysPolar = coordSys.type === 'polar';
  496. var prevCoordSys = this._coordSys;
  497. var symbolDraw = this._symbolDraw;
  498. var polyline = this._polyline;
  499. var polygon = this._polygon;
  500. var lineGroup = this._lineGroup;
  501. var hasAnimation = !ecModel.ssr && seriesModel.get('animation');
  502. var isAreaChart = !areaStyleModel.isEmpty();
  503. var valueOrigin = areaStyleModel.get('origin');
  504. var dataCoordInfo = prepareDataCoordInfo(coordSys, data, valueOrigin);
  505. var stackedOnPoints = isAreaChart && getStackedOnPoints(coordSys, data, dataCoordInfo);
  506. var showSymbol = seriesModel.get('showSymbol');
  507. var connectNulls = seriesModel.get('connectNulls');
  508. var isIgnoreFunc = showSymbol && !isCoordSysPolar && getIsIgnoreFunc(seriesModel, data, coordSys);
  509. // Remove temporary symbols
  510. var oldData = this._data;
  511. oldData && oldData.eachItemGraphicEl(function (el, idx) {
  512. if (el.__temp) {
  513. group.remove(el);
  514. oldData.setItemGraphicEl(idx, null);
  515. }
  516. });
  517. // Remove previous created symbols if showSymbol changed to false
  518. if (!showSymbol) {
  519. symbolDraw.remove();
  520. }
  521. group.add(lineGroup);
  522. // FIXME step not support polar
  523. var step = !isCoordSysPolar ? seriesModel.get('step') : false;
  524. var clipShapeForSymbol;
  525. if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) {
  526. clipShapeForSymbol = coordSys.getArea();
  527. // Avoid float number rounding error for symbol on the edge of axis extent.
  528. // See #7913 and `test/dataZoom-clip.html`.
  529. if (clipShapeForSymbol.width != null) {
  530. clipShapeForSymbol.x -= 0.1;
  531. clipShapeForSymbol.y -= 0.1;
  532. clipShapeForSymbol.width += 0.2;
  533. clipShapeForSymbol.height += 0.2;
  534. } else if (clipShapeForSymbol.r0) {
  535. clipShapeForSymbol.r0 -= 0.5;
  536. clipShapeForSymbol.r += 0.5;
  537. }
  538. }
  539. this._clipShapeForSymbol = clipShapeForSymbol;
  540. var visualColor = getVisualGradient(data, coordSys, api) || data.getVisual('style')[data.getVisual('drawType')];
  541. // Initialization animation or coordinate system changed
  542. if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) {
  543. showSymbol && symbolDraw.updateData(data, {
  544. isIgnore: isIgnoreFunc,
  545. clipShape: clipShapeForSymbol,
  546. disableAnimation: true,
  547. getSymbolPoint: function (idx) {
  548. return [points[idx * 2], points[idx * 2 + 1]];
  549. }
  550. });
  551. hasAnimation && this._initSymbolLabelAnimation(data, coordSys, clipShapeForSymbol);
  552. if (step) {
  553. if (stackedOnPoints) {
  554. stackedOnPoints = turnPointsIntoStep(stackedOnPoints, points, coordSys, step, connectNulls);
  555. }
  556. // TODO If stacked series is not step
  557. points = turnPointsIntoStep(points, null, coordSys, step, connectNulls);
  558. }
  559. polyline = this._newPolyline(points);
  560. if (isAreaChart) {
  561. polygon = this._newPolygon(points, stackedOnPoints);
  562. } // If areaStyle is removed
  563. else if (polygon) {
  564. lineGroup.remove(polygon);
  565. polygon = this._polygon = null;
  566. }
  567. // NOTE: Must update _endLabel before setClipPath.
  568. if (!isCoordSysPolar) {
  569. this._initOrUpdateEndLabel(seriesModel, coordSys, convertToColorString(visualColor));
  570. }
  571. lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel));
  572. } else {
  573. if (isAreaChart && !polygon) {
  574. // If areaStyle is added
  575. polygon = this._newPolygon(points, stackedOnPoints);
  576. } else if (polygon && !isAreaChart) {
  577. // If areaStyle is removed
  578. lineGroup.remove(polygon);
  579. polygon = this._polygon = null;
  580. }
  581. // NOTE: Must update _endLabel before setClipPath.
  582. if (!isCoordSysPolar) {
  583. this._initOrUpdateEndLabel(seriesModel, coordSys, convertToColorString(visualColor));
  584. }
  585. // Update clipPath
  586. var oldClipPath = lineGroup.getClipPath();
  587. if (oldClipPath) {
  588. var newClipPath = createLineClipPath(this, coordSys, false, seriesModel);
  589. graphic.initProps(oldClipPath, {
  590. shape: newClipPath.shape
  591. }, seriesModel);
  592. } else {
  593. lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel));
  594. }
  595. // Always update, or it is wrong in the case turning on legend
  596. // because points are not changed.
  597. showSymbol && symbolDraw.updateData(data, {
  598. isIgnore: isIgnoreFunc,
  599. clipShape: clipShapeForSymbol,
  600. disableAnimation: true,
  601. getSymbolPoint: function (idx) {
  602. return [points[idx * 2], points[idx * 2 + 1]];
  603. }
  604. });
  605. // In the case data zoom triggered refreshing frequently
  606. // Data may not change if line has a category axis. So it should animate nothing.
  607. if (!isPointsSame(this._stackedOnPoints, stackedOnPoints) || !isPointsSame(this._points, points)) {
  608. if (hasAnimation) {
  609. this._doUpdateAnimation(data, stackedOnPoints, coordSys, api, step, valueOrigin, connectNulls);
  610. } else {
  611. // Not do it in update with animation
  612. if (step) {
  613. if (stackedOnPoints) {
  614. stackedOnPoints = turnPointsIntoStep(stackedOnPoints, points, coordSys, step, connectNulls);
  615. }
  616. // TODO If stacked series is not step
  617. points = turnPointsIntoStep(points, null, coordSys, step, connectNulls);
  618. }
  619. polyline.setShape({
  620. points: points
  621. });
  622. polygon && polygon.setShape({
  623. points: points,
  624. stackedOnPoints: stackedOnPoints
  625. });
  626. }
  627. }
  628. }
  629. var emphasisModel = seriesModel.getModel('emphasis');
  630. var focus = emphasisModel.get('focus');
  631. var blurScope = emphasisModel.get('blurScope');
  632. var emphasisDisabled = emphasisModel.get('disabled');
  633. polyline.useStyle(zrUtil.defaults(
  634. // Use color in lineStyle first
  635. lineStyleModel.getLineStyle(), {
  636. fill: 'none',
  637. stroke: visualColor,
  638. lineJoin: 'bevel'
  639. }));
  640. setStatesStylesFromModel(polyline, seriesModel, 'lineStyle');
  641. if (polyline.style.lineWidth > 0 && seriesModel.get(['emphasis', 'lineStyle', 'width']) === 'bolder') {
  642. var emphasisLineStyle = polyline.getState('emphasis').style;
  643. emphasisLineStyle.lineWidth = +polyline.style.lineWidth + 1;
  644. }
  645. // Needs seriesIndex for focus
  646. getECData(polyline).seriesIndex = seriesModel.seriesIndex;
  647. toggleHoverEmphasis(polyline, focus, blurScope, emphasisDisabled);
  648. var smooth = getSmooth(seriesModel.get('smooth'));
  649. var smoothMonotone = seriesModel.get('smoothMonotone');
  650. polyline.setShape({
  651. smooth: smooth,
  652. smoothMonotone: smoothMonotone,
  653. connectNulls: connectNulls
  654. });
  655. if (polygon) {
  656. var stackedOnSeries = data.getCalculationInfo('stackedOnSeries');
  657. var stackedOnSmooth = 0;
  658. polygon.useStyle(zrUtil.defaults(areaStyleModel.getAreaStyle(), {
  659. fill: visualColor,
  660. opacity: 0.7,
  661. lineJoin: 'bevel',
  662. decal: data.getVisual('style').decal
  663. }));
  664. if (stackedOnSeries) {
  665. stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth'));
  666. }
  667. polygon.setShape({
  668. smooth: smooth,
  669. stackedOnSmooth: stackedOnSmooth,
  670. smoothMonotone: smoothMonotone,
  671. connectNulls: connectNulls
  672. });
  673. setStatesStylesFromModel(polygon, seriesModel, 'areaStyle');
  674. // Needs seriesIndex for focus
  675. getECData(polygon).seriesIndex = seriesModel.seriesIndex;
  676. toggleHoverEmphasis(polygon, focus, blurScope, emphasisDisabled);
  677. }
  678. var changePolyState = this._changePolyState;
  679. data.eachItemGraphicEl(function (el) {
  680. // Switch polyline / polygon state if element changed its state.
  681. el && (el.onHoverStateChange = changePolyState);
  682. });
  683. this._polyline.onHoverStateChange = changePolyState;
  684. this._data = data;
  685. // Save the coordinate system for transition animation when data changed
  686. this._coordSys = coordSys;
  687. this._stackedOnPoints = stackedOnPoints;
  688. this._points = points;
  689. this._step = step;
  690. this._valueOrigin = valueOrigin;
  691. if (seriesModel.get('triggerLineEvent')) {
  692. this.packEventData(seriesModel, polyline);
  693. polygon && this.packEventData(seriesModel, polygon);
  694. }
  695. };
  696. LineView.prototype.packEventData = function (seriesModel, el) {
  697. getECData(el).eventData = {
  698. componentType: 'series',
  699. componentSubType: 'line',
  700. componentIndex: seriesModel.componentIndex,
  701. seriesIndex: seriesModel.seriesIndex,
  702. seriesName: seriesModel.name,
  703. seriesType: 'line'
  704. };
  705. };
  706. LineView.prototype.highlight = function (seriesModel, ecModel, api, payload) {
  707. var data = seriesModel.getData();
  708. var dataIndex = modelUtil.queryDataIndex(data, payload);
  709. this._changePolyState('emphasis');
  710. if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) {
  711. var points = data.getLayout('points');
  712. var symbol = data.getItemGraphicEl(dataIndex);
  713. if (!symbol) {
  714. // Create a temporary symbol if it is not exists
  715. var x = points[dataIndex * 2];
  716. var y = points[dataIndex * 2 + 1];
  717. if (isNaN(x) || isNaN(y)) {
  718. // Null data
  719. return;
  720. }
  721. // fix #11360: shouldn't draw symbol outside clipShapeForSymbol
  722. if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(x, y)) {
  723. return;
  724. }
  725. var zlevel = seriesModel.get('zlevel') || 0;
  726. var z = seriesModel.get('z') || 0;
  727. symbol = new SymbolClz(data, dataIndex);
  728. symbol.x = x;
  729. symbol.y = y;
  730. symbol.setZ(zlevel, z);
  731. // ensure label text of the temporary symbol is in front of line and area polygon
  732. var symbolLabel = symbol.getSymbolPath().getTextContent();
  733. if (symbolLabel) {
  734. symbolLabel.zlevel = zlevel;
  735. symbolLabel.z = z;
  736. symbolLabel.z2 = this._polyline.z2 + 1;
  737. }
  738. symbol.__temp = true;
  739. data.setItemGraphicEl(dataIndex, symbol);
  740. // Stop scale animation
  741. symbol.stopSymbolAnimation(true);
  742. this.group.add(symbol);
  743. }
  744. symbol.highlight();
  745. } else {
  746. // Highlight whole series
  747. ChartView.prototype.highlight.call(this, seriesModel, ecModel, api, payload);
  748. }
  749. };
  750. LineView.prototype.downplay = function (seriesModel, ecModel, api, payload) {
  751. var data = seriesModel.getData();
  752. var dataIndex = modelUtil.queryDataIndex(data, payload);
  753. this._changePolyState('normal');
  754. if (dataIndex != null && dataIndex >= 0) {
  755. var symbol = data.getItemGraphicEl(dataIndex);
  756. if (symbol) {
  757. if (symbol.__temp) {
  758. data.setItemGraphicEl(dataIndex, null);
  759. this.group.remove(symbol);
  760. } else {
  761. symbol.downplay();
  762. }
  763. }
  764. } else {
  765. // FIXME
  766. // can not downplay completely.
  767. // Downplay whole series
  768. ChartView.prototype.downplay.call(this, seriesModel, ecModel, api, payload);
  769. }
  770. };
  771. LineView.prototype._changePolyState = function (toState) {
  772. var polygon = this._polygon;
  773. setStatesFlag(this._polyline, toState);
  774. polygon && setStatesFlag(polygon, toState);
  775. };
  776. LineView.prototype._newPolyline = function (points) {
  777. var polyline = this._polyline;
  778. // Remove previous created polyline
  779. if (polyline) {
  780. this._lineGroup.remove(polyline);
  781. }
  782. polyline = new ECPolyline({
  783. shape: {
  784. points: points
  785. },
  786. segmentIgnoreThreshold: 2,
  787. z2: 10
  788. });
  789. this._lineGroup.add(polyline);
  790. this._polyline = polyline;
  791. return polyline;
  792. };
  793. LineView.prototype._newPolygon = function (points, stackedOnPoints) {
  794. var polygon = this._polygon;
  795. // Remove previous created polygon
  796. if (polygon) {
  797. this._lineGroup.remove(polygon);
  798. }
  799. polygon = new ECPolygon({
  800. shape: {
  801. points: points,
  802. stackedOnPoints: stackedOnPoints
  803. },
  804. segmentIgnoreThreshold: 2
  805. });
  806. this._lineGroup.add(polygon);
  807. this._polygon = polygon;
  808. return polygon;
  809. };
  810. LineView.prototype._initSymbolLabelAnimation = function (data, coordSys, clipShape) {
  811. var isHorizontalOrRadial;
  812. var isCoordSysPolar;
  813. var baseAxis = coordSys.getBaseAxis();
  814. var isAxisInverse = baseAxis.inverse;
  815. if (coordSys.type === 'cartesian2d') {
  816. isHorizontalOrRadial = baseAxis.isHorizontal();
  817. isCoordSysPolar = false;
  818. } else if (coordSys.type === 'polar') {
  819. isHorizontalOrRadial = baseAxis.dim === 'angle';
  820. isCoordSysPolar = true;
  821. }
  822. var seriesModel = data.hostModel;
  823. var seriesDuration = seriesModel.get('animationDuration');
  824. if (zrUtil.isFunction(seriesDuration)) {
  825. seriesDuration = seriesDuration(null);
  826. }
  827. var seriesDelay = seriesModel.get('animationDelay') || 0;
  828. var seriesDelayValue = zrUtil.isFunction(seriesDelay) ? seriesDelay(null) : seriesDelay;
  829. data.eachItemGraphicEl(function (symbol, idx) {
  830. var el = symbol;
  831. if (el) {
  832. var point = [symbol.x, symbol.y];
  833. var start = void 0;
  834. var end = void 0;
  835. var current = void 0;
  836. if (clipShape) {
  837. if (isCoordSysPolar) {
  838. var polarClip = clipShape;
  839. var coord = coordSys.pointToCoord(point);
  840. if (isHorizontalOrRadial) {
  841. start = polarClip.startAngle;
  842. end = polarClip.endAngle;
  843. current = -coord[1] / 180 * Math.PI;
  844. } else {
  845. start = polarClip.r0;
  846. end = polarClip.r;
  847. current = coord[0];
  848. }
  849. } else {
  850. var gridClip = clipShape;
  851. if (isHorizontalOrRadial) {
  852. start = gridClip.x;
  853. end = gridClip.x + gridClip.width;
  854. current = symbol.x;
  855. } else {
  856. start = gridClip.y + gridClip.height;
  857. end = gridClip.y;
  858. current = symbol.y;
  859. }
  860. }
  861. }
  862. var ratio = end === start ? 0 : (current - start) / (end - start);
  863. if (isAxisInverse) {
  864. ratio = 1 - ratio;
  865. }
  866. var delay = zrUtil.isFunction(seriesDelay) ? seriesDelay(idx) : seriesDuration * ratio + seriesDelayValue;
  867. var symbolPath = el.getSymbolPath();
  868. var text = symbolPath.getTextContent();
  869. el.attr({
  870. scaleX: 0,
  871. scaleY: 0
  872. });
  873. el.animateTo({
  874. scaleX: 1,
  875. scaleY: 1
  876. }, {
  877. duration: 200,
  878. setToFinal: true,
  879. delay: delay
  880. });
  881. if (text) {
  882. text.animateFrom({
  883. style: {
  884. opacity: 0
  885. }
  886. }, {
  887. duration: 300,
  888. delay: delay
  889. });
  890. }
  891. symbolPath.disableLabelAnimation = true;
  892. }
  893. });
  894. };
  895. LineView.prototype._initOrUpdateEndLabel = function (seriesModel, coordSys, inheritColor) {
  896. var endLabelModel = seriesModel.getModel('endLabel');
  897. if (anyStateShowEndLabel(seriesModel)) {
  898. var data_2 = seriesModel.getData();
  899. var polyline = this._polyline;
  900. // series may be filtered.
  901. var points = data_2.getLayout('points');
  902. if (!points) {
  903. polyline.removeTextContent();
  904. this._endLabel = null;
  905. return;
  906. }
  907. var endLabel = this._endLabel;
  908. if (!endLabel) {
  909. endLabel = this._endLabel = new graphic.Text({
  910. z2: 200 // should be higher than item symbol
  911. });
  912. endLabel.ignoreClip = true;
  913. polyline.setTextContent(this._endLabel);
  914. polyline.disableLabelAnimation = true;
  915. }
  916. // Find last non-NaN data to display data
  917. var dataIndex = getLastIndexNotNull(points);
  918. if (dataIndex >= 0) {
  919. setLabelStyle(polyline, getLabelStatesModels(seriesModel, 'endLabel'), {
  920. inheritColor: inheritColor,
  921. labelFetcher: seriesModel,
  922. labelDataIndex: dataIndex,
  923. defaultText: function (dataIndex, opt, interpolatedValue) {
  924. return interpolatedValue != null ? getDefaultInterpolatedLabel(data_2, interpolatedValue) : getDefaultLabel(data_2, dataIndex);
  925. },
  926. enableTextSetter: true
  927. }, getEndLabelStateSpecified(endLabelModel, coordSys));
  928. polyline.textConfig.position = null;
  929. }
  930. } else if (this._endLabel) {
  931. this._polyline.removeTextContent();
  932. this._endLabel = null;
  933. }
  934. };
  935. LineView.prototype._endLabelOnDuring = function (percent, clipRect, data, animationRecord, valueAnimation, endLabelModel, coordSys) {
  936. var endLabel = this._endLabel;
  937. var polyline = this._polyline;
  938. if (endLabel) {
  939. // NOTE: Don't remove percent < 1. percent === 1 means the first frame during render.
  940. // The label is not prepared at this time.
  941. if (percent < 1 && animationRecord.originalX == null) {
  942. animationRecord.originalX = endLabel.x;
  943. animationRecord.originalY = endLabel.y;
  944. }
  945. var points = data.getLayout('points');
  946. var seriesModel = data.hostModel;
  947. var connectNulls = seriesModel.get('connectNulls');
  948. var precision = endLabelModel.get('precision');
  949. var distance = endLabelModel.get('distance') || 0;
  950. var baseAxis = coordSys.getBaseAxis();
  951. var isHorizontal = baseAxis.isHorizontal();
  952. var isBaseInversed = baseAxis.inverse;
  953. var clipShape = clipRect.shape;
  954. var xOrY = isBaseInversed ? isHorizontal ? clipShape.x : clipShape.y + clipShape.height : isHorizontal ? clipShape.x + clipShape.width : clipShape.y;
  955. var distanceX = (isHorizontal ? distance : 0) * (isBaseInversed ? -1 : 1);
  956. var distanceY = (isHorizontal ? 0 : -distance) * (isBaseInversed ? -1 : 1);
  957. var dim = isHorizontal ? 'x' : 'y';
  958. var dataIndexRange = getIndexRange(points, xOrY, dim);
  959. var indices = dataIndexRange.range;
  960. var diff = indices[1] - indices[0];
  961. var value = void 0;
  962. if (diff >= 1) {
  963. // diff > 1 && connectNulls, which is on the null data.
  964. if (diff > 1 && !connectNulls) {
  965. var pt = getPointAtIndex(points, indices[0]);
  966. endLabel.attr({
  967. x: pt[0] + distanceX,
  968. y: pt[1] + distanceY
  969. });
  970. valueAnimation && (value = seriesModel.getRawValue(indices[0]));
  971. } else {
  972. var pt = polyline.getPointOn(xOrY, dim);
  973. pt && endLabel.attr({
  974. x: pt[0] + distanceX,
  975. y: pt[1] + distanceY
  976. });
  977. var startValue = seriesModel.getRawValue(indices[0]);
  978. var endValue = seriesModel.getRawValue(indices[1]);
  979. valueAnimation && (value = modelUtil.interpolateRawValues(data, precision, startValue, endValue, dataIndexRange.t));
  980. }
  981. animationRecord.lastFrameIndex = indices[0];
  982. } else {
  983. // If diff <= 0, which is the range is not found(Include NaN)
  984. // Choose the first point or last point.
  985. var idx = percent === 1 || animationRecord.lastFrameIndex > 0 ? indices[0] : 0;
  986. var pt = getPointAtIndex(points, idx);
  987. valueAnimation && (value = seriesModel.getRawValue(idx));
  988. endLabel.attr({
  989. x: pt[0] + distanceX,
  990. y: pt[1] + distanceY
  991. });
  992. }
  993. if (valueAnimation) {
  994. var inner = labelInner(endLabel);
  995. if (typeof inner.setLabelText === 'function') {
  996. inner.setLabelText(value);
  997. }
  998. }
  999. }
  1000. };
  1001. /**
  1002. * @private
  1003. */
  1004. // FIXME Two value axis
  1005. LineView.prototype._doUpdateAnimation = function (data, stackedOnPoints, coordSys, api, step, valueOrigin, connectNulls) {
  1006. var polyline = this._polyline;
  1007. var polygon = this._polygon;
  1008. var seriesModel = data.hostModel;
  1009. var diff = lineAnimationDiff(this._data, data, this._stackedOnPoints, stackedOnPoints, this._coordSys, coordSys, this._valueOrigin, valueOrigin);
  1010. var current = diff.current;
  1011. var stackedOnCurrent = diff.stackedOnCurrent;
  1012. var next = diff.next;
  1013. var stackedOnNext = diff.stackedOnNext;
  1014. if (step) {
  1015. // TODO If stacked series is not step
  1016. stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, diff.current, coordSys, step, connectNulls);
  1017. current = turnPointsIntoStep(diff.current, null, coordSys, step, connectNulls);
  1018. stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, diff.next, coordSys, step, connectNulls);
  1019. next = turnPointsIntoStep(diff.next, null, coordSys, step, connectNulls);
  1020. }
  1021. // Don't apply animation if diff is large.
  1022. // For better result and avoid memory explosion problems like
  1023. // https://github.com/apache/incubator-echarts/issues/12229
  1024. if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) {
  1025. polyline.stopAnimation();
  1026. polyline.setShape({
  1027. points: next
  1028. });
  1029. if (polygon) {
  1030. polygon.stopAnimation();
  1031. polygon.setShape({
  1032. points: next,
  1033. stackedOnPoints: stackedOnNext
  1034. });
  1035. }
  1036. return;
  1037. }
  1038. polyline.shape.__points = diff.current;
  1039. polyline.shape.points = current;
  1040. var target = {
  1041. shape: {
  1042. points: next
  1043. }
  1044. };
  1045. // Also animate the original points.
  1046. // If points reference is changed when turning into step line.
  1047. if (diff.current !== current) {
  1048. target.shape.__points = diff.next;
  1049. }
  1050. // Stop previous animation.
  1051. polyline.stopAnimation();
  1052. graphic.updateProps(polyline, target, seriesModel);
  1053. if (polygon) {
  1054. polygon.setShape({
  1055. // Reuse the points with polyline.
  1056. points: current,
  1057. stackedOnPoints: stackedOnCurrent
  1058. });
  1059. polygon.stopAnimation();
  1060. graphic.updateProps(polygon, {
  1061. shape: {
  1062. stackedOnPoints: stackedOnNext
  1063. }
  1064. }, seriesModel);
  1065. // If use attr directly in updateProps.
  1066. if (polyline.shape.points !== polygon.shape.points) {
  1067. polygon.shape.points = polyline.shape.points;
  1068. }
  1069. }
  1070. var updatedDataInfo = [];
  1071. var diffStatus = diff.status;
  1072. for (var i = 0; i < diffStatus.length; i++) {
  1073. var cmd = diffStatus[i].cmd;
  1074. if (cmd === '=') {
  1075. var el = data.getItemGraphicEl(diffStatus[i].idx1);
  1076. if (el) {
  1077. updatedDataInfo.push({
  1078. el: el,
  1079. ptIdx: i // Index of points
  1080. });
  1081. }
  1082. }
  1083. }
  1084. if (polyline.animators && polyline.animators.length) {
  1085. polyline.animators[0].during(function () {
  1086. polygon && polygon.dirtyShape();
  1087. var points = polyline.shape.__points;
  1088. for (var i = 0; i < updatedDataInfo.length; i++) {
  1089. var el = updatedDataInfo[i].el;
  1090. var offset = updatedDataInfo[i].ptIdx * 2;
  1091. el.x = points[offset];
  1092. el.y = points[offset + 1];
  1093. el.markRedraw();
  1094. }
  1095. });
  1096. }
  1097. };
  1098. LineView.prototype.remove = function (ecModel) {
  1099. var group = this.group;
  1100. var oldData = this._data;
  1101. this._lineGroup.removeAll();
  1102. this._symbolDraw.remove(true);
  1103. // Remove temporary created elements when highlighting
  1104. oldData && oldData.eachItemGraphicEl(function (el, idx) {
  1105. if (el.__temp) {
  1106. group.remove(el);
  1107. oldData.setItemGraphicEl(idx, null);
  1108. }
  1109. });
  1110. this._polyline = this._polygon = this._coordSys = this._points = this._stackedOnPoints = this._endLabel = this._data = null;
  1111. };
  1112. LineView.type = 'line';
  1113. return LineView;
  1114. }(ChartView);
  1115. export default LineView;