LineView.js 41 KB

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