index.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Slider = void 0;
  4. var tslib_1 = require("tslib");
  5. var g_1 = require("@antv/g");
  6. var animation_1 = require("../../animation");
  7. var core_1 = require("../../core");
  8. var shapes_1 = require("../../shapes");
  9. var util_1 = require("../../util");
  10. var sparkline_1 = require("../sparkline");
  11. var constant_1 = require("./constant");
  12. var handle_1 = require("./handle");
  13. var Slider = /** @class */ (function (_super) {
  14. tslib_1.__extends(Slider, _super);
  15. function Slider(options) {
  16. var _this = _super.call(this, options, tslib_1.__assign(tslib_1.__assign(tslib_1.__assign({ animate: { duration: 100, fill: 'both' }, brushable: true, formatter: function (val) { return val.toString(); }, handleSpacing: 2, orientation: 'horizontal', padding: 0, autoFitLabel: true, scrollable: true, selectionCursor: 'move', selectionFill: '#5B8FF9', selectionFillOpacity: 0.45, selectionZIndex: 2, showHandle: true, showLabel: true, slidable: true, trackFill: '#416180', trackLength: 200, trackOpacity: 0.05, trackSize: 20, trackZIndex: -1, values: [0, 1] }, (0, util_1.superStyleProps)(constant_1.HANDLE_DEFAULT_CFG, 'handle')), (0, util_1.superStyleProps)(constant_1.HANDLE_ICON_DEFAULT_CFG, 'handleIcon')), (0, util_1.superStyleProps)(constant_1.HANDLE_LABEL_DEFAULT_CFG, 'handleLabel'))) || this;
  17. _this.range = [0, 1];
  18. _this.onDragStart = function (target) { return function (e) {
  19. e.stopPropagation();
  20. _this.target = target;
  21. _this.prevPos = _this.getOrientVal((0, util_1.getEventPos)(e));
  22. var _a = _this.availableSpace, x = _a.x, y = _a.y;
  23. var _b = _this.attributes, X = _b.x, Y = _b.y;
  24. _this.selectionStartPos = _this.getRatio(_this.prevPos - _this.getOrientVal([x, y]) - _this.getOrientVal([+X, +Y]));
  25. _this.selectionWidth = 0;
  26. document.addEventListener('mousemove', _this.onDragging);
  27. document.addEventListener('touchmove', _this.onDragging);
  28. document.addEventListener('mouseup', _this.onDragEnd);
  29. document.addEventListener('touchend', _this.onDragEnd);
  30. }; };
  31. _this.onDragging = function (e) {
  32. var _a = _this.attributes, slidable = _a.slidable, brushable = _a.brushable;
  33. e.stopPropagation();
  34. var currPos = _this.getOrientVal((0, util_1.getEventPos)(e));
  35. var diffPos = currPos - _this.prevPos;
  36. if (!diffPos)
  37. return;
  38. var deltaVal = _this.getRatio(diffPos);
  39. switch (_this.target) {
  40. case 'start':
  41. if (slidable)
  42. _this.setValuesOffset(deltaVal);
  43. break;
  44. case 'end':
  45. if (slidable)
  46. _this.setValuesOffset(0, deltaVal);
  47. break;
  48. case 'selection':
  49. if (slidable)
  50. _this.setValuesOffset(deltaVal, deltaVal);
  51. break;
  52. case 'track':
  53. if (!brushable)
  54. return;
  55. // 绘制蒙板
  56. _this.selectionWidth += deltaVal;
  57. _this.innerSetValues([_this.selectionStartPos, _this.selectionStartPos + _this.selectionWidth].sort(), true);
  58. break;
  59. default:
  60. break;
  61. }
  62. _this.prevPos = currPos;
  63. };
  64. _this.onDragEnd = function () {
  65. document.removeEventListener('mousemove', _this.onDragging);
  66. document.removeEventListener('mousemove', _this.onDragging);
  67. document.removeEventListener('mouseup', _this.onDragEnd);
  68. document.removeEventListener('touchend', _this.onDragEnd);
  69. };
  70. _this.onValueChange = function (oldValue) {
  71. var evt = new g_1.CustomEvent('valuechange', {
  72. detail: {
  73. oldValue: oldValue,
  74. value: _this.getValues(),
  75. },
  76. });
  77. _this.dispatchEvent(evt);
  78. };
  79. _this.selectionStartPos = 0;
  80. _this.selectionWidth = 0;
  81. _this.prevPos = 0;
  82. _this.target = '';
  83. return _this;
  84. }
  85. Object.defineProperty(Slider.prototype, "values", {
  86. get: function () {
  87. return this.attributes.values;
  88. },
  89. set: function (values) {
  90. this.attributes.values = this.clampValues(values);
  91. },
  92. enumerable: false,
  93. configurable: true
  94. });
  95. Object.defineProperty(Slider.prototype, "sparklineStyle", {
  96. get: function () {
  97. var orientation = this.attributes.orientation;
  98. if (orientation !== 'horizontal')
  99. return null;
  100. var attr = (0, util_1.subStyleProps)(this.attributes, 'sparkline');
  101. return tslib_1.__assign(tslib_1.__assign({ zIndex: 0 }, this.availableSpace), attr);
  102. },
  103. enumerable: false,
  104. configurable: true
  105. });
  106. Object.defineProperty(Slider.prototype, "shape", {
  107. get: function () {
  108. var _a = this.attributes, trackLength = _a.trackLength, trackSize = _a.trackSize;
  109. var _b = tslib_1.__read(this.getOrientVal([
  110. [trackLength, trackSize],
  111. [trackSize, trackLength],
  112. ]), 2), width = _b[0], height = _b[1];
  113. return { width: width, height: height };
  114. },
  115. enumerable: false,
  116. configurable: true
  117. });
  118. Object.defineProperty(Slider.prototype, "availableSpace", {
  119. get: function () {
  120. var padding = this.attributes.padding;
  121. var _a = tslib_1.__read((0, util_1.parseSeriesAttr)(padding), 4), top = _a[0], right = _a[1], bottom = _a[2], left = _a[3];
  122. var _b = this.shape, width = _b.width, height = _b.height;
  123. return {
  124. x: left,
  125. y: top,
  126. width: width - (left + right),
  127. height: height - (top + bottom),
  128. };
  129. },
  130. enumerable: false,
  131. configurable: true
  132. });
  133. Slider.prototype.getValues = function () {
  134. return this.values;
  135. };
  136. /** 不触发重绘 */
  137. Slider.prototype.setValues = function (values, animate) {
  138. if (values === void 0) { values = [0, 0]; }
  139. if (animate === void 0) { animate = false; }
  140. this.attributes.values = values;
  141. var animation = animate === false ? false : this.attributes.animate;
  142. (0, animation_1.transition)(this.selectionShape.node(), this.selectionStyle, animation);
  143. this.updateHandlesPosition(animation);
  144. };
  145. Slider.prototype.updateHandlesPosition = function (animation) {
  146. if (!this.attributes.showHandle)
  147. return;
  148. (0, animation_1.transition)(this.startHandle, this.getHandleStyle('start'), animation);
  149. (0, animation_1.transition)(this.endHandle, this.getHandleStyle('end'), animation);
  150. };
  151. Slider.prototype.innerSetValues = function (values, trigger) {
  152. if (values === void 0) { values = [0, 0]; }
  153. if (trigger === void 0) { trigger = false; }
  154. var oldValues = this.values;
  155. var newValues = this.clampValues(values);
  156. this.attr('values', newValues);
  157. this.setValues(newValues);
  158. if (trigger) {
  159. this.onValueChange(oldValues);
  160. }
  161. };
  162. Slider.prototype.renderTrack = function (container) {
  163. var brushable = this.attributes.brushable;
  164. var style = (0, util_1.subStyleProps)(this.attributes, 'track');
  165. this.trackShape = (0, util_1.select)(container)
  166. .maybeAppendByClassName(constant_1.CLASS_NAMES.track, 'rect')
  167. .styles(tslib_1.__assign(tslib_1.__assign({ cursor: brushable ? 'crosshair' : 'default' }, this.shape), style));
  168. };
  169. Slider.prototype.renderSparkline = function (container) {
  170. var _this = this;
  171. var orientation = this.attributes.orientation;
  172. var sparklineGroup = (0, util_1.select)(container).maybeAppendByClassName(constant_1.CLASS_NAMES.sparklineGroup, 'g');
  173. (0, util_1.ifShow)(orientation === 'horizontal', sparklineGroup, function (group) {
  174. var style = _this.sparklineStyle;
  175. group.maybeAppendByClassName(constant_1.CLASS_NAMES.sparkline, function () { return new sparkline_1.Sparkline({ style: style }); }).update(style);
  176. });
  177. };
  178. Object.defineProperty(Slider.prototype, "selectionStyle", {
  179. get: function () {
  180. var style = (0, util_1.subStyleProps)(this.attributes, 'selection');
  181. return tslib_1.__assign(tslib_1.__assign({}, style), this.calcMask());
  182. },
  183. enumerable: false,
  184. configurable: true
  185. });
  186. Slider.prototype.renderHandles = function () {
  187. var _this = this;
  188. var _a;
  189. var showHandle = this.attributes.showHandle;
  190. var data = (showHandle ? ['start', 'end'] : []).map(function (type) { return ({ type: type }); });
  191. var that = this;
  192. (_a = this.foregroundGroup) === null || _a === void 0 ? void 0 : _a.selectAll(constant_1.CLASS_NAMES.handle.class).data(data, function (d) { return d.type; }).join(function (enter) {
  193. return enter
  194. .append(function (_a) {
  195. var type = _a.type;
  196. return new handle_1.Handle({ style: _this.getHandleStyle(type) });
  197. })
  198. .each(function (_a) {
  199. var type = _a.type;
  200. this.attr('class', "".concat(constant_1.CLASS_NAMES.handle.name, " ").concat(type, "-handle"));
  201. var name = "".concat(type, "Handle");
  202. that[name] = this;
  203. this.addEventListener('pointerdown', function (e) {
  204. that.onDragStart(type)(e);
  205. });
  206. });
  207. }, function (update) {
  208. return update.each(function (_a) {
  209. var type = _a.type;
  210. this.update(that.getHandleStyle(type));
  211. });
  212. }, function (exit) {
  213. return exit
  214. .each(function (_a) {
  215. var type = _a.type;
  216. var name = "".concat(type, "Handle");
  217. that[name] = undefined;
  218. })
  219. .remove();
  220. });
  221. };
  222. Slider.prototype.renderSelection = function (container) {
  223. this.foregroundGroup = (0, util_1.select)(container).maybeAppendByClassName(constant_1.CLASS_NAMES.foreground, 'g');
  224. this.selectionShape = this.foregroundGroup
  225. .maybeAppendByClassName(constant_1.CLASS_NAMES.selection, 'rect')
  226. .styles(this.selectionStyle);
  227. this.renderHandles();
  228. };
  229. Slider.prototype.render = function (attributes, container) {
  230. this.renderTrack(container);
  231. this.renderSparkline(container);
  232. this.renderSelection(container);
  233. };
  234. Slider.prototype.clampValues = function (values, precision) {
  235. var _a;
  236. if (precision === void 0) { precision = 4; }
  237. var _b = tslib_1.__read(this.range, 2), min = _b[0], max = _b[1];
  238. var _c = tslib_1.__read(this.getValues().map(function (num) { return (0, util_1.toPrecision)(num, precision); }), 2), prevStart = _c[0], prevEnd = _c[1];
  239. var _d = tslib_1.__read((values || [prevStart, prevEnd]).map(function (num) { return (0, util_1.toPrecision)(num, precision); }), 2), startVal = _d[0], endVal = _d[1];
  240. // 交换startVal endVal
  241. if (startVal > endVal) {
  242. _a = tslib_1.__read([endVal, startVal], 2), startVal = _a[0], endVal = _a[1];
  243. }
  244. var range = endVal - startVal;
  245. // 超出范围就全选
  246. if (range > max - min)
  247. return [min, max];
  248. if (startVal < min) {
  249. if (prevStart === min && prevEnd === endVal)
  250. return [min, endVal];
  251. return [min, range + min];
  252. }
  253. if (endVal > max) {
  254. if (prevEnd === max && prevStart === startVal)
  255. return [startVal, max];
  256. return [max - range, max];
  257. }
  258. // 保留小数
  259. return [startVal, endVal];
  260. };
  261. /**
  262. * 计算蒙板坐标和宽高
  263. * 默认用来计算前景位置大小
  264. */
  265. Slider.prototype.calcMask = function (values) {
  266. var _a = tslib_1.__read(this.clampValues(values), 2), start = _a[0], end = _a[1];
  267. var _b = this.availableSpace, x = _b.x, y = _b.y, width = _b.width, height = _b.height;
  268. return this.getOrientVal([
  269. {
  270. y: y,
  271. height: height,
  272. x: start * width + x,
  273. width: (end - start) * width,
  274. },
  275. {
  276. x: x,
  277. width: width,
  278. y: start * height + y,
  279. height: (end - start) * height,
  280. },
  281. ]);
  282. };
  283. /**
  284. * 计算手柄的x y
  285. */
  286. Slider.prototype.calcHandlePosition = function (handleType) {
  287. var _a = this.availableSpace, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
  288. var _b = tslib_1.__read(this.clampValues(), 2), stVal = _b[0], endVal = _b[1];
  289. var L = (handleType === 'start' ? stVal : endVal) * this.getOrientVal([width, height]);
  290. return {
  291. x: x + this.getOrientVal([L, width / 2]),
  292. y: y + this.getOrientVal([height / 2, L]),
  293. };
  294. };
  295. /**
  296. * 计算手柄应当处于的位置
  297. * @param handleType start手柄还是end手柄
  298. * @returns
  299. */
  300. Slider.prototype.calcHandleText = function (handleType) {
  301. var _a;
  302. var _b = this.attributes, orientation = _b.orientation, formatter = _b.formatter, autoFitLabel = _b.autoFitLabel;
  303. var handleStyle = (0, util_1.subStyleProps)(this.attributes, 'handle');
  304. var labelStyle = (0, util_1.subStyleProps)(handleStyle, 'label');
  305. var spacing = handleStyle.spacing;
  306. var size = this.getHandleSize();
  307. var values = this.clampValues();
  308. var value = handleType === 'start' ? values[0] : values[1];
  309. var text = formatter(value);
  310. var temp = new shapes_1.Text({
  311. style: tslib_1.__assign(tslib_1.__assign({}, labelStyle), { text: text }),
  312. });
  313. // 文字包围盒的宽高
  314. var _c = temp.getBBox(), textWidth = _c.width, textHeight = _c.height;
  315. temp.destroy();
  316. if (!autoFitLabel) {
  317. var finaleWidth = spacing + size + (orientation === 'horizontal' ? textWidth / 2 : 0);
  318. return _a = { text: text }, _a[orientation === 'horizontal' ? 'x' : 'y'] = handleType === 'start' ? -finaleWidth : finaleWidth, _a;
  319. }
  320. var x = 0;
  321. var y = 0;
  322. // 相对于获取两端可用空间
  323. var _d = this.availableSpace, iW = _d.width, iH = _d.height;
  324. var _e = this.calcMask(), fX = _e.x, fY = _e.y, fW = _e.width, fH = _e.height;
  325. if (orientation === 'horizontal') {
  326. var totalSpacing = spacing + size;
  327. var finalWidth = totalSpacing + textWidth / 2;
  328. if (handleType === 'start') {
  329. var left = fX - totalSpacing - textWidth;
  330. x = left > 0 ? -finalWidth : finalWidth;
  331. }
  332. else {
  333. var sign = iW - fX - fW - totalSpacing > textWidth;
  334. x = sign ? finalWidth : -finalWidth;
  335. }
  336. }
  337. else {
  338. var finalWidth = spacing + size;
  339. if (handleType === 'start') {
  340. y = fY - size > textHeight ? -finalWidth : finalWidth;
  341. }
  342. else {
  343. y = iH - fY - fH - size > textHeight ? finalWidth : -finalWidth;
  344. }
  345. }
  346. return { x: x, y: y, text: text };
  347. };
  348. Slider.prototype.getHandleLabelStyle = function (handleType) {
  349. var showLabel = this.attributes.showLabel;
  350. if (!showLabel)
  351. return {};
  352. var style = (0, util_1.subStyleProps)(this.attributes, 'handleLabel');
  353. return tslib_1.__assign(tslib_1.__assign({}, style), this.calcHandleText(handleType));
  354. };
  355. Slider.prototype.getHandleIconStyle = function () {
  356. var shape = this.attributes.handleIconShape;
  357. var style = (0, util_1.subStyleProps)(this.attributes, 'handleIcon');
  358. var cursor = this.getOrientVal(['ew-resize', 'ns-resize']);
  359. var size = this.getHandleSize();
  360. return tslib_1.__assign({ cursor: cursor, shape: shape, size: size }, style);
  361. };
  362. Slider.prototype.getHandleStyle = function (handleType) {
  363. var _a = this.attributes, showLabel = _a.showLabel, orientation = _a.orientation;
  364. var handlePosition = this.calcHandlePosition(handleType);
  365. var textStyle = this.calcHandleText(handleType);
  366. return tslib_1.__assign(tslib_1.__assign(tslib_1.__assign(tslib_1.__assign({}, (0, util_1.superStyleProps)(this.getHandleIconStyle(), 'icon')), (0, util_1.superStyleProps)(tslib_1.__assign(tslib_1.__assign({}, this.getHandleLabelStyle(handleType)), textStyle), 'label')), handlePosition), { orientation: orientation, showLabel: showLabel, type: handleType, zIndex: 3 });
  367. };
  368. Slider.prototype.getHandleSize = function () {
  369. var _a = this.attributes, size = _a.handleIconSize, width = _a.width, height = _a.height;
  370. if (size)
  371. return size;
  372. // 没设置 size 的话,高度就取 height + 4 高度,手柄宽度是高度的 1/ 2.4
  373. return Math.floor((this.getOrientVal([+height, +width]) + 4) / 2.4);
  374. };
  375. Slider.prototype.getOrientVal = function (_a) {
  376. var _b = tslib_1.__read(_a, 2), x = _b[0], y = _b[1];
  377. var orientation = this.attributes.orientation;
  378. return orientation === 'horizontal' ? x : y;
  379. };
  380. Slider.prototype.setValuesOffset = function (stOffset, endOffset, animate) {
  381. if (endOffset === void 0) { endOffset = 0; }
  382. if (animate === void 0) { animate = false; }
  383. var _a = tslib_1.__read(this.getValues(), 2), oldStartVal = _a[0], oldEndVal = _a[1];
  384. var values = [oldStartVal + stOffset, oldEndVal + endOffset].sort();
  385. if (animate)
  386. this.setValues(values);
  387. else
  388. this.innerSetValues(values, true);
  389. };
  390. Slider.prototype.getRatio = function (val) {
  391. var _a = this.availableSpace, width = _a.width, height = _a.height;
  392. return val / this.getOrientVal([width, height]);
  393. };
  394. Slider.prototype.dispatchCustomEvent = function (target, event, name) {
  395. var _this = this;
  396. target.on(event, function (e) {
  397. e.stopPropagation();
  398. _this.dispatchEvent(new g_1.CustomEvent(name, { detail: e }));
  399. });
  400. };
  401. Slider.prototype.bindEvents = function () {
  402. var selection = this.selectionShape;
  403. // scroll 事件
  404. this.addEventListener('wheel', this.onScroll);
  405. // 选区drag事件
  406. selection.on('mousedown', this.onDragStart('selection'));
  407. selection.on('touchstart', this.onDragStart('selection'));
  408. // 选区hover事件
  409. this.dispatchCustomEvent(selection, 'mouseenter', 'selectionMouseenter');
  410. this.dispatchCustomEvent(selection, 'mouseleave', 'selectionMouseleave');
  411. this.dispatchCustomEvent(selection, 'click', 'selectionClick');
  412. var track = this.trackShape;
  413. this.dispatchCustomEvent(track, 'click', 'trackClick');
  414. this.dispatchCustomEvent(track, 'mouseenter', 'trackMouseenter');
  415. this.dispatchCustomEvent(track, 'mouseleave', 'trackMouseleave');
  416. // Drag and brush
  417. track.on('mousedown', this.onDragStart('track'));
  418. track.on('touchstart', this.onDragStart('track'));
  419. };
  420. Slider.prototype.onScroll = function (event) {
  421. var scrollable = this.attributes.scrollable;
  422. if (scrollable) {
  423. var deltaX = event.deltaX, deltaY = event.deltaY;
  424. var offset = deltaY || deltaX;
  425. var deltaVal = this.getRatio(offset);
  426. this.setValuesOffset(deltaVal, deltaVal, true);
  427. }
  428. };
  429. Slider.tag = 'slider';
  430. return Slider;
  431. }(core_1.GUI));
  432. exports.Slider = Slider;
  433. //# sourceMappingURL=index.js.map