SliderTimelineView.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  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. import BoundingRect from 'zrender/lib/core/BoundingRect.js';
  42. import * as matrix from 'zrender/lib/core/matrix.js';
  43. import * as graphic from '../../util/graphic.js';
  44. import { createTextStyle } from '../../label/labelStyle.js';
  45. import * as layout from '../../util/layout.js';
  46. import TimelineView from './TimelineView.js';
  47. import TimelineAxis from './TimelineAxis.js';
  48. import { createSymbol, normalizeSymbolOffset, normalizeSymbolSize } from '../../util/symbol.js';
  49. import * as numberUtil from '../../util/number.js';
  50. import { merge, each, extend, isString, bind, defaults, retrieve2 } from 'zrender/lib/core/util.js';
  51. import OrdinalScale from '../../scale/Ordinal.js';
  52. import TimeScale from '../../scale/Time.js';
  53. import IntervalScale from '../../scale/Interval.js';
  54. import { parsePercent } from 'zrender/lib/contain/text.js';
  55. import { makeInner } from '../../util/model.js';
  56. import { getECData } from '../../util/innerStore.js';
  57. import { enableHoverEmphasis } from '../../util/states.js';
  58. import { createTooltipMarkup } from '../tooltip/tooltipMarkup.js';
  59. var PI = Math.PI;
  60. var labelDataIndexStore = makeInner();
  61. var SliderTimelineView =
  62. /** @class */
  63. function (_super) {
  64. __extends(SliderTimelineView, _super);
  65. function SliderTimelineView() {
  66. var _this = _super !== null && _super.apply(this, arguments) || this;
  67. _this.type = SliderTimelineView.type;
  68. return _this;
  69. }
  70. SliderTimelineView.prototype.init = function (ecModel, api) {
  71. this.api = api;
  72. };
  73. /**
  74. * @override
  75. */
  76. SliderTimelineView.prototype.render = function (timelineModel, ecModel, api) {
  77. this.model = timelineModel;
  78. this.api = api;
  79. this.ecModel = ecModel;
  80. this.group.removeAll();
  81. if (timelineModel.get('show', true)) {
  82. var layoutInfo_1 = this._layout(timelineModel, api);
  83. var mainGroup_1 = this._createGroup('_mainGroup');
  84. var labelGroup = this._createGroup('_labelGroup');
  85. var axis_1 = this._axis = this._createAxis(layoutInfo_1, timelineModel);
  86. timelineModel.formatTooltip = function (dataIndex) {
  87. var name = axis_1.scale.getLabel({
  88. value: dataIndex
  89. });
  90. return createTooltipMarkup('nameValue', {
  91. noName: true,
  92. value: name
  93. });
  94. };
  95. each(['AxisLine', 'AxisTick', 'Control', 'CurrentPointer'], function (name) {
  96. this['_render' + name](layoutInfo_1, mainGroup_1, axis_1, timelineModel);
  97. }, this);
  98. this._renderAxisLabel(layoutInfo_1, labelGroup, axis_1, timelineModel);
  99. this._position(layoutInfo_1, timelineModel);
  100. }
  101. this._doPlayStop();
  102. this._updateTicksStatus();
  103. };
  104. /**
  105. * @override
  106. */
  107. SliderTimelineView.prototype.remove = function () {
  108. this._clearTimer();
  109. this.group.removeAll();
  110. };
  111. /**
  112. * @override
  113. */
  114. SliderTimelineView.prototype.dispose = function () {
  115. this._clearTimer();
  116. };
  117. SliderTimelineView.prototype._layout = function (timelineModel, api) {
  118. var labelPosOpt = timelineModel.get(['label', 'position']);
  119. var orient = timelineModel.get('orient');
  120. var viewRect = getViewRect(timelineModel, api);
  121. var parsedLabelPos; // Auto label offset.
  122. if (labelPosOpt == null || labelPosOpt === 'auto') {
  123. parsedLabelPos = orient === 'horizontal' ? viewRect.y + viewRect.height / 2 < api.getHeight() / 2 ? '-' : '+' : viewRect.x + viewRect.width / 2 < api.getWidth() / 2 ? '+' : '-';
  124. } else if (isString(labelPosOpt)) {
  125. parsedLabelPos = {
  126. horizontal: {
  127. top: '-',
  128. bottom: '+'
  129. },
  130. vertical: {
  131. left: '-',
  132. right: '+'
  133. }
  134. }[orient][labelPosOpt];
  135. } else {
  136. // is number
  137. parsedLabelPos = labelPosOpt;
  138. }
  139. var labelAlignMap = {
  140. horizontal: 'center',
  141. vertical: parsedLabelPos >= 0 || parsedLabelPos === '+' ? 'left' : 'right'
  142. };
  143. var labelBaselineMap = {
  144. horizontal: parsedLabelPos >= 0 || parsedLabelPos === '+' ? 'top' : 'bottom',
  145. vertical: 'middle'
  146. };
  147. var rotationMap = {
  148. horizontal: 0,
  149. vertical: PI / 2
  150. }; // Position
  151. var mainLength = orient === 'vertical' ? viewRect.height : viewRect.width;
  152. var controlModel = timelineModel.getModel('controlStyle');
  153. var showControl = controlModel.get('show', true);
  154. var controlSize = showControl ? controlModel.get('itemSize') : 0;
  155. var controlGap = showControl ? controlModel.get('itemGap') : 0;
  156. var sizePlusGap = controlSize + controlGap; // Special label rotate.
  157. var labelRotation = timelineModel.get(['label', 'rotate']) || 0;
  158. labelRotation = labelRotation * PI / 180; // To radian.
  159. var playPosition;
  160. var prevBtnPosition;
  161. var nextBtnPosition;
  162. var controlPosition = controlModel.get('position', true);
  163. var showPlayBtn = showControl && controlModel.get('showPlayBtn', true);
  164. var showPrevBtn = showControl && controlModel.get('showPrevBtn', true);
  165. var showNextBtn = showControl && controlModel.get('showNextBtn', true);
  166. var xLeft = 0;
  167. var xRight = mainLength; // position[0] means left, position[1] means middle.
  168. if (controlPosition === 'left' || controlPosition === 'bottom') {
  169. showPlayBtn && (playPosition = [0, 0], xLeft += sizePlusGap);
  170. showPrevBtn && (prevBtnPosition = [xLeft, 0], xLeft += sizePlusGap);
  171. showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
  172. } else {
  173. // 'top' 'right'
  174. showPlayBtn && (playPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
  175. showPrevBtn && (prevBtnPosition = [0, 0], xLeft += sizePlusGap);
  176. showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
  177. }
  178. var axisExtent = [xLeft, xRight];
  179. if (timelineModel.get('inverse')) {
  180. axisExtent.reverse();
  181. }
  182. return {
  183. viewRect: viewRect,
  184. mainLength: mainLength,
  185. orient: orient,
  186. rotation: rotationMap[orient],
  187. labelRotation: labelRotation,
  188. labelPosOpt: parsedLabelPos,
  189. labelAlign: timelineModel.get(['label', 'align']) || labelAlignMap[orient],
  190. labelBaseline: timelineModel.get(['label', 'verticalAlign']) || timelineModel.get(['label', 'baseline']) || labelBaselineMap[orient],
  191. // Based on mainGroup.
  192. playPosition: playPosition,
  193. prevBtnPosition: prevBtnPosition,
  194. nextBtnPosition: nextBtnPosition,
  195. axisExtent: axisExtent,
  196. controlSize: controlSize,
  197. controlGap: controlGap
  198. };
  199. };
  200. SliderTimelineView.prototype._position = function (layoutInfo, timelineModel) {
  201. // Position is be called finally, because bounding rect is needed for
  202. // adapt content to fill viewRect (auto adapt offset).
  203. // Timeline may be not all in the viewRect when 'offset' is specified
  204. // as a number, because it is more appropriate that label aligns at
  205. // 'offset' but not the other edge defined by viewRect.
  206. var mainGroup = this._mainGroup;
  207. var labelGroup = this._labelGroup;
  208. var viewRect = layoutInfo.viewRect;
  209. if (layoutInfo.orient === 'vertical') {
  210. // transform to horizontal, inverse rotate by left-top point.
  211. var m = matrix.create();
  212. var rotateOriginX = viewRect.x;
  213. var rotateOriginY = viewRect.y + viewRect.height;
  214. matrix.translate(m, m, [-rotateOriginX, -rotateOriginY]);
  215. matrix.rotate(m, m, -PI / 2);
  216. matrix.translate(m, m, [rotateOriginX, rotateOriginY]);
  217. viewRect = viewRect.clone();
  218. viewRect.applyTransform(m);
  219. }
  220. var viewBound = getBound(viewRect);
  221. var mainBound = getBound(mainGroup.getBoundingRect());
  222. var labelBound = getBound(labelGroup.getBoundingRect());
  223. var mainPosition = [mainGroup.x, mainGroup.y];
  224. var labelsPosition = [labelGroup.x, labelGroup.y];
  225. labelsPosition[0] = mainPosition[0] = viewBound[0][0];
  226. var labelPosOpt = layoutInfo.labelPosOpt;
  227. if (labelPosOpt == null || isString(labelPosOpt)) {
  228. // '+' or '-'
  229. var mainBoundIdx = labelPosOpt === '+' ? 0 : 1;
  230. toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx);
  231. toBound(labelsPosition, labelBound, viewBound, 1, 1 - mainBoundIdx);
  232. } else {
  233. var mainBoundIdx = labelPosOpt >= 0 ? 0 : 1;
  234. toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx);
  235. labelsPosition[1] = mainPosition[1] + labelPosOpt;
  236. }
  237. mainGroup.setPosition(mainPosition);
  238. labelGroup.setPosition(labelsPosition);
  239. mainGroup.rotation = labelGroup.rotation = layoutInfo.rotation;
  240. setOrigin(mainGroup);
  241. setOrigin(labelGroup);
  242. function setOrigin(targetGroup) {
  243. targetGroup.originX = viewBound[0][0] - targetGroup.x;
  244. targetGroup.originY = viewBound[1][0] - targetGroup.y;
  245. }
  246. function getBound(rect) {
  247. // [[xmin, xmax], [ymin, ymax]]
  248. return [[rect.x, rect.x + rect.width], [rect.y, rect.y + rect.height]];
  249. }
  250. function toBound(fromPos, from, to, dimIdx, boundIdx) {
  251. fromPos[dimIdx] += to[dimIdx][boundIdx] - from[dimIdx][boundIdx];
  252. }
  253. };
  254. SliderTimelineView.prototype._createAxis = function (layoutInfo, timelineModel) {
  255. var data = timelineModel.getData();
  256. var axisType = timelineModel.get('axisType');
  257. var scale = createScaleByModel(timelineModel, axisType); // Customize scale. The `tickValue` is `dataIndex`.
  258. scale.getTicks = function () {
  259. return data.mapArray(['value'], function (value) {
  260. return {
  261. value: value
  262. };
  263. });
  264. };
  265. var dataExtent = data.getDataExtent('value');
  266. scale.setExtent(dataExtent[0], dataExtent[1]);
  267. scale.calcNiceTicks();
  268. var axis = new TimelineAxis('value', scale, layoutInfo.axisExtent, axisType);
  269. axis.model = timelineModel;
  270. return axis;
  271. };
  272. SliderTimelineView.prototype._createGroup = function (key) {
  273. var newGroup = this[key] = new graphic.Group();
  274. this.group.add(newGroup);
  275. return newGroup;
  276. };
  277. SliderTimelineView.prototype._renderAxisLine = function (layoutInfo, group, axis, timelineModel) {
  278. var axisExtent = axis.getExtent();
  279. if (!timelineModel.get(['lineStyle', 'show'])) {
  280. return;
  281. }
  282. var line = new graphic.Line({
  283. shape: {
  284. x1: axisExtent[0],
  285. y1: 0,
  286. x2: axisExtent[1],
  287. y2: 0
  288. },
  289. style: extend({
  290. lineCap: 'round'
  291. }, timelineModel.getModel('lineStyle').getLineStyle()),
  292. silent: true,
  293. z2: 1
  294. });
  295. group.add(line);
  296. var progressLine = this._progressLine = new graphic.Line({
  297. shape: {
  298. x1: axisExtent[0],
  299. x2: this._currentPointer ? this._currentPointer.x : axisExtent[0],
  300. y1: 0,
  301. y2: 0
  302. },
  303. style: defaults({
  304. lineCap: 'round',
  305. lineWidth: line.style.lineWidth
  306. }, timelineModel.getModel(['progress', 'lineStyle']).getLineStyle()),
  307. silent: true,
  308. z2: 1
  309. });
  310. group.add(progressLine);
  311. };
  312. SliderTimelineView.prototype._renderAxisTick = function (layoutInfo, group, axis, timelineModel) {
  313. var _this = this;
  314. var data = timelineModel.getData(); // Show all ticks, despite ignoring strategy.
  315. var ticks = axis.scale.getTicks();
  316. this._tickSymbols = []; // The value is dataIndex, see the customized scale.
  317. each(ticks, function (tick) {
  318. var tickCoord = axis.dataToCoord(tick.value);
  319. var itemModel = data.getItemModel(tick.value);
  320. var itemStyleModel = itemModel.getModel('itemStyle');
  321. var hoverStyleModel = itemModel.getModel(['emphasis', 'itemStyle']);
  322. var progressStyleModel = itemModel.getModel(['progress', 'itemStyle']);
  323. var symbolOpt = {
  324. x: tickCoord,
  325. y: 0,
  326. onclick: bind(_this._changeTimeline, _this, tick.value)
  327. };
  328. var el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt);
  329. el.ensureState('emphasis').style = hoverStyleModel.getItemStyle();
  330. el.ensureState('progress').style = progressStyleModel.getItemStyle();
  331. enableHoverEmphasis(el);
  332. var ecData = getECData(el);
  333. if (itemModel.get('tooltip')) {
  334. ecData.dataIndex = tick.value;
  335. ecData.dataModel = timelineModel;
  336. } else {
  337. ecData.dataIndex = ecData.dataModel = null;
  338. }
  339. _this._tickSymbols.push(el);
  340. });
  341. };
  342. SliderTimelineView.prototype._renderAxisLabel = function (layoutInfo, group, axis, timelineModel) {
  343. var _this = this;
  344. var labelModel = axis.getLabelModel();
  345. if (!labelModel.get('show')) {
  346. return;
  347. }
  348. var data = timelineModel.getData();
  349. var labels = axis.getViewLabels();
  350. this._tickLabels = [];
  351. each(labels, function (labelItem) {
  352. // The tickValue is dataIndex, see the customized scale.
  353. var dataIndex = labelItem.tickValue;
  354. var itemModel = data.getItemModel(dataIndex);
  355. var normalLabelModel = itemModel.getModel('label');
  356. var hoverLabelModel = itemModel.getModel(['emphasis', 'label']);
  357. var progressLabelModel = itemModel.getModel(['progress', 'label']);
  358. var tickCoord = axis.dataToCoord(labelItem.tickValue);
  359. var textEl = new graphic.Text({
  360. x: tickCoord,
  361. y: 0,
  362. rotation: layoutInfo.labelRotation - layoutInfo.rotation,
  363. onclick: bind(_this._changeTimeline, _this, dataIndex),
  364. silent: false,
  365. style: createTextStyle(normalLabelModel, {
  366. text: labelItem.formattedLabel,
  367. align: layoutInfo.labelAlign,
  368. verticalAlign: layoutInfo.labelBaseline
  369. })
  370. });
  371. textEl.ensureState('emphasis').style = createTextStyle(hoverLabelModel);
  372. textEl.ensureState('progress').style = createTextStyle(progressLabelModel);
  373. group.add(textEl);
  374. enableHoverEmphasis(textEl);
  375. labelDataIndexStore(textEl).dataIndex = dataIndex;
  376. _this._tickLabels.push(textEl);
  377. });
  378. };
  379. SliderTimelineView.prototype._renderControl = function (layoutInfo, group, axis, timelineModel) {
  380. var controlSize = layoutInfo.controlSize;
  381. var rotation = layoutInfo.rotation;
  382. var itemStyle = timelineModel.getModel('controlStyle').getItemStyle();
  383. var hoverStyle = timelineModel.getModel(['emphasis', 'controlStyle']).getItemStyle();
  384. var playState = timelineModel.getPlayState();
  385. var inverse = timelineModel.get('inverse', true);
  386. makeBtn(layoutInfo.nextBtnPosition, 'next', bind(this._changeTimeline, this, inverse ? '-' : '+'));
  387. makeBtn(layoutInfo.prevBtnPosition, 'prev', bind(this._changeTimeline, this, inverse ? '+' : '-'));
  388. makeBtn(layoutInfo.playPosition, playState ? 'stop' : 'play', bind(this._handlePlayClick, this, !playState), true);
  389. function makeBtn(position, iconName, onclick, willRotate) {
  390. if (!position) {
  391. return;
  392. }
  393. var iconSize = parsePercent(retrieve2(timelineModel.get(['controlStyle', iconName + 'BtnSize']), controlSize), controlSize);
  394. var rect = [0, -iconSize / 2, iconSize, iconSize];
  395. var btn = makeControlIcon(timelineModel, iconName + 'Icon', rect, {
  396. x: position[0],
  397. y: position[1],
  398. originX: controlSize / 2,
  399. originY: 0,
  400. rotation: willRotate ? -rotation : 0,
  401. rectHover: true,
  402. style: itemStyle,
  403. onclick: onclick
  404. });
  405. btn.ensureState('emphasis').style = hoverStyle;
  406. group.add(btn);
  407. enableHoverEmphasis(btn);
  408. }
  409. };
  410. SliderTimelineView.prototype._renderCurrentPointer = function (layoutInfo, group, axis, timelineModel) {
  411. var data = timelineModel.getData();
  412. var currentIndex = timelineModel.getCurrentIndex();
  413. var pointerModel = data.getItemModel(currentIndex).getModel('checkpointStyle');
  414. var me = this;
  415. var callback = {
  416. onCreate: function (pointer) {
  417. pointer.draggable = true;
  418. pointer.drift = bind(me._handlePointerDrag, me);
  419. pointer.ondragend = bind(me._handlePointerDragend, me);
  420. pointerMoveTo(pointer, me._progressLine, currentIndex, axis, timelineModel, true);
  421. },
  422. onUpdate: function (pointer) {
  423. pointerMoveTo(pointer, me._progressLine, currentIndex, axis, timelineModel);
  424. }
  425. }; // Reuse when exists, for animation and drag.
  426. this._currentPointer = giveSymbol(pointerModel, pointerModel, this._mainGroup, {}, this._currentPointer, callback);
  427. };
  428. SliderTimelineView.prototype._handlePlayClick = function (nextState) {
  429. this._clearTimer();
  430. this.api.dispatchAction({
  431. type: 'timelinePlayChange',
  432. playState: nextState,
  433. from: this.uid
  434. });
  435. };
  436. SliderTimelineView.prototype._handlePointerDrag = function (dx, dy, e) {
  437. this._clearTimer();
  438. this._pointerChangeTimeline([e.offsetX, e.offsetY]);
  439. };
  440. SliderTimelineView.prototype._handlePointerDragend = function (e) {
  441. this._pointerChangeTimeline([e.offsetX, e.offsetY], true);
  442. };
  443. SliderTimelineView.prototype._pointerChangeTimeline = function (mousePos, trigger) {
  444. var toCoord = this._toAxisCoord(mousePos)[0];
  445. var axis = this._axis;
  446. var axisExtent = numberUtil.asc(axis.getExtent().slice());
  447. toCoord > axisExtent[1] && (toCoord = axisExtent[1]);
  448. toCoord < axisExtent[0] && (toCoord = axisExtent[0]);
  449. this._currentPointer.x = toCoord;
  450. this._currentPointer.markRedraw();
  451. var progressLine = this._progressLine;
  452. if (progressLine) {
  453. progressLine.shape.x2 = toCoord;
  454. progressLine.dirty();
  455. }
  456. var targetDataIndex = this._findNearestTick(toCoord);
  457. var timelineModel = this.model;
  458. if (trigger || targetDataIndex !== timelineModel.getCurrentIndex() && timelineModel.get('realtime')) {
  459. this._changeTimeline(targetDataIndex);
  460. }
  461. };
  462. SliderTimelineView.prototype._doPlayStop = function () {
  463. var _this = this;
  464. this._clearTimer();
  465. if (this.model.getPlayState()) {
  466. this._timer = setTimeout(function () {
  467. // Do not cache
  468. var timelineModel = _this.model;
  469. _this._changeTimeline(timelineModel.getCurrentIndex() + (timelineModel.get('rewind', true) ? -1 : 1));
  470. }, this.model.get('playInterval'));
  471. }
  472. };
  473. SliderTimelineView.prototype._toAxisCoord = function (vertex) {
  474. var trans = this._mainGroup.getLocalTransform();
  475. return graphic.applyTransform(vertex, trans, true);
  476. };
  477. SliderTimelineView.prototype._findNearestTick = function (axisCoord) {
  478. var data = this.model.getData();
  479. var dist = Infinity;
  480. var targetDataIndex;
  481. var axis = this._axis;
  482. data.each(['value'], function (value, dataIndex) {
  483. var coord = axis.dataToCoord(value);
  484. var d = Math.abs(coord - axisCoord);
  485. if (d < dist) {
  486. dist = d;
  487. targetDataIndex = dataIndex;
  488. }
  489. });
  490. return targetDataIndex;
  491. };
  492. SliderTimelineView.prototype._clearTimer = function () {
  493. if (this._timer) {
  494. clearTimeout(this._timer);
  495. this._timer = null;
  496. }
  497. };
  498. SliderTimelineView.prototype._changeTimeline = function (nextIndex) {
  499. var currentIndex = this.model.getCurrentIndex();
  500. if (nextIndex === '+') {
  501. nextIndex = currentIndex + 1;
  502. } else if (nextIndex === '-') {
  503. nextIndex = currentIndex - 1;
  504. }
  505. this.api.dispatchAction({
  506. type: 'timelineChange',
  507. currentIndex: nextIndex,
  508. from: this.uid
  509. });
  510. };
  511. SliderTimelineView.prototype._updateTicksStatus = function () {
  512. var currentIndex = this.model.getCurrentIndex();
  513. var tickSymbols = this._tickSymbols;
  514. var tickLabels = this._tickLabels;
  515. if (tickSymbols) {
  516. for (var i = 0; i < tickSymbols.length; i++) {
  517. tickSymbols && tickSymbols[i] && tickSymbols[i].toggleState('progress', i < currentIndex);
  518. }
  519. }
  520. if (tickLabels) {
  521. for (var i = 0; i < tickLabels.length; i++) {
  522. tickLabels && tickLabels[i] && tickLabels[i].toggleState('progress', labelDataIndexStore(tickLabels[i]).dataIndex <= currentIndex);
  523. }
  524. }
  525. };
  526. SliderTimelineView.type = 'timeline.slider';
  527. return SliderTimelineView;
  528. }(TimelineView);
  529. function createScaleByModel(model, axisType) {
  530. axisType = axisType || model.get('type');
  531. if (axisType) {
  532. switch (axisType) {
  533. // Buildin scale
  534. case 'category':
  535. return new OrdinalScale({
  536. ordinalMeta: model.getCategories(),
  537. extent: [Infinity, -Infinity]
  538. });
  539. case 'time':
  540. return new TimeScale({
  541. locale: model.ecModel.getLocaleModel(),
  542. useUTC: model.ecModel.get('useUTC')
  543. });
  544. default:
  545. // default to be value
  546. return new IntervalScale();
  547. }
  548. }
  549. }
  550. function getViewRect(model, api) {
  551. return layout.getLayoutRect(model.getBoxLayoutParams(), {
  552. width: api.getWidth(),
  553. height: api.getHeight()
  554. }, model.get('padding'));
  555. }
  556. function makeControlIcon(timelineModel, objPath, rect, opts) {
  557. var style = opts.style;
  558. var icon = graphic.createIcon(timelineModel.get(['controlStyle', objPath]), opts || {}, new BoundingRect(rect[0], rect[1], rect[2], rect[3])); // TODO createIcon won't use style in opt.
  559. if (style) {
  560. icon.setStyle(style);
  561. }
  562. return icon;
  563. }
  564. /**
  565. * Create symbol or update symbol
  566. * opt: basic position and event handlers
  567. */
  568. function giveSymbol(hostModel, itemStyleModel, group, opt, symbol, callback) {
  569. var color = itemStyleModel.get('color');
  570. if (!symbol) {
  571. var symbolType = hostModel.get('symbol');
  572. symbol = createSymbol(symbolType, -1, -1, 2, 2, color);
  573. symbol.setStyle('strokeNoScale', true);
  574. group.add(symbol);
  575. callback && callback.onCreate(symbol);
  576. } else {
  577. symbol.setColor(color);
  578. group.add(symbol); // Group may be new, also need to add.
  579. callback && callback.onUpdate(symbol);
  580. } // Style
  581. var itemStyle = itemStyleModel.getItemStyle(['color']);
  582. symbol.setStyle(itemStyle); // Transform and events.
  583. opt = merge({
  584. rectHover: true,
  585. z2: 100
  586. }, opt, true);
  587. var symbolSize = normalizeSymbolSize(hostModel.get('symbolSize'));
  588. opt.scaleX = symbolSize[0] / 2;
  589. opt.scaleY = symbolSize[1] / 2;
  590. var symbolOffset = normalizeSymbolOffset(hostModel.get('symbolOffset'), symbolSize);
  591. if (symbolOffset) {
  592. opt.x = (opt.x || 0) + symbolOffset[0];
  593. opt.y = (opt.y || 0) + symbolOffset[1];
  594. }
  595. var symbolRotate = hostModel.get('symbolRotate');
  596. opt.rotation = (symbolRotate || 0) * Math.PI / 180 || 0;
  597. symbol.attr(opt); // FIXME
  598. // (1) When symbol.style.strokeNoScale is true and updateTransform is not performed,
  599. // getBoundingRect will return wrong result.
  600. // (This is supposed to be resolved in zrender, but it is a little difficult to
  601. // leverage performance and auto updateTransform)
  602. // (2) All of ancesters of symbol do not scale, so we can just updateTransform symbol.
  603. symbol.updateTransform();
  604. return symbol;
  605. }
  606. function pointerMoveTo(pointer, progressLine, dataIndex, axis, timelineModel, noAnimation) {
  607. if (pointer.dragging) {
  608. return;
  609. }
  610. var pointerModel = timelineModel.getModel('checkpointStyle');
  611. var toCoord = axis.dataToCoord(timelineModel.getData().get('value', dataIndex));
  612. if (noAnimation || !pointerModel.get('animation', true)) {
  613. pointer.attr({
  614. x: toCoord,
  615. y: 0
  616. });
  617. progressLine && progressLine.attr({
  618. shape: {
  619. x2: toCoord
  620. }
  621. });
  622. } else {
  623. var animationCfg = {
  624. duration: pointerModel.get('animationDuration', true),
  625. easing: pointerModel.get('animationEasing', true)
  626. };
  627. pointer.stopAnimation(null, true);
  628. pointer.animateTo({
  629. x: toCoord,
  630. y: 0
  631. }, animationCfg);
  632. progressLine && progressLine.animateTo({
  633. shape: {
  634. x2: toCoord
  635. }
  636. }, animationCfg);
  637. }
  638. }
  639. export default SliderTimelineView;