slider.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Slider = void 0;
  4. var tslib_1 = require("tslib");
  5. var util_1 = require("@antv/util");
  6. var group_component_1 = require("../abstract/group-component");
  7. var trend_1 = require("../trend/trend");
  8. var handler_1 = require("./handler");
  9. var constant_1 = require("./constant");
  10. var Slider = /** @class */ (function (_super) {
  11. tslib_1.__extends(Slider, _super);
  12. function Slider() {
  13. var _this = _super !== null && _super.apply(this, arguments) || this;
  14. _this.onMouseDown = function (target) { return function (e) {
  15. _this.currentTarget = target;
  16. // 取出原生事件
  17. var event = e.originalEvent;
  18. // 2. 存储当前点击位置
  19. event.stopPropagation();
  20. event.preventDefault();
  21. // 兼容移动端获取数据
  22. _this.prevX = util_1.get(event, 'touches.0.pageX', event.pageX);
  23. _this.prevY = util_1.get(event, 'touches.0.pageY', event.pageY);
  24. // 3. 开始滑动的时候,绑定 move 和 up 事件
  25. var containerDOM = _this.getContainerDOM();
  26. containerDOM.addEventListener('mousemove', _this.onMouseMove);
  27. containerDOM.addEventListener('mouseup', _this.onMouseUp);
  28. containerDOM.addEventListener('mouseleave', _this.onMouseUp);
  29. // 移动端事件
  30. containerDOM.addEventListener('touchmove', _this.onMouseMove);
  31. containerDOM.addEventListener('touchend', _this.onMouseUp);
  32. containerDOM.addEventListener('touchcancel', _this.onMouseUp);
  33. }; };
  34. _this.onMouseMove = function (event) {
  35. var width = _this.cfg.width;
  36. var originValue = [_this.get('start'), _this.get('end')];
  37. // 滑动过程中,计算偏移,更新滑块,然后 emit 数据出去
  38. event.stopPropagation();
  39. event.preventDefault();
  40. var x = util_1.get(event, 'touches.0.pageX', event.pageX);
  41. var y = util_1.get(event, 'touches.0.pageY', event.pageY);
  42. // 横向的 slider 只处理 x
  43. var offsetX = x - _this.prevX;
  44. var offsetXRange = _this.adjustOffsetRange(offsetX / width);
  45. // 更新 start end range 范围
  46. _this.updateStartEnd(offsetXRange);
  47. // 更新 ui
  48. _this.updateUI(_this.getElementByLocalId('foreground'), _this.getElementByLocalId('minText'), _this.getElementByLocalId('maxText'));
  49. _this.prevX = x;
  50. _this.prevY = y;
  51. _this.draw();
  52. // 因为存储的 start、end 可能不一定是按大小存储的,所以排序一下,对外是 end >= start
  53. _this.emit(constant_1.SLIDER_CHANGE, [_this.get('start'), _this.get('end')].sort());
  54. _this.delegateEmit('valuechanged', {
  55. originValue: originValue,
  56. value: [_this.get('start'), _this.get('end')],
  57. });
  58. };
  59. _this.onMouseUp = function () {
  60. // 结束之后,取消绑定的事件
  61. if (_this.currentTarget) {
  62. _this.currentTarget = undefined;
  63. }
  64. var containerDOM = _this.getContainerDOM();
  65. if (containerDOM) {
  66. containerDOM.removeEventListener('mousemove', _this.onMouseMove);
  67. containerDOM.removeEventListener('mouseup', _this.onMouseUp);
  68. // 防止滑动到 canvas 外部之后,状态丢失
  69. containerDOM.removeEventListener('mouseleave', _this.onMouseUp);
  70. // 移动端事件
  71. containerDOM.removeEventListener('touchmove', _this.onMouseMove);
  72. containerDOM.removeEventListener('touchend', _this.onMouseUp);
  73. containerDOM.removeEventListener('touchcancel', _this.onMouseUp);
  74. }
  75. };
  76. return _this;
  77. }
  78. Slider.prototype.setRange = function (min, max) {
  79. this.set('minLimit', min);
  80. this.set('maxLimit', max);
  81. var oldStart = this.get('start');
  82. var oldEnd = this.get('end');
  83. var newStart = util_1.clamp(oldStart, min, max);
  84. var newEnd = util_1.clamp(oldEnd, min, max);
  85. if (!this.get('isInit') && (oldStart !== newStart || oldEnd !== newEnd)) {
  86. this.setValue([newStart, newEnd]);
  87. }
  88. };
  89. Slider.prototype.getRange = function () {
  90. return {
  91. min: this.get('minLimit') || 0,
  92. max: this.get('maxLimit') || 1,
  93. };
  94. };
  95. Slider.prototype.setValue = function (value) {
  96. var range = this.getRange();
  97. if (util_1.isArray(value) && value.length === 2) {
  98. var originValue = [this.get('start'), this.get('end')];
  99. this.update({
  100. start: util_1.clamp(value[0], range.min, range.max),
  101. end: util_1.clamp(value[1], range.min, range.max),
  102. });
  103. if (!this.get('updateAutoRender')) {
  104. this.render();
  105. }
  106. this.delegateEmit('valuechanged', {
  107. originValue: originValue,
  108. value: value,
  109. });
  110. }
  111. };
  112. Slider.prototype.getValue = function () {
  113. return [this.get('start'), this.get('end')];
  114. };
  115. Slider.prototype.getDefaultCfg = function () {
  116. var cfg = _super.prototype.getDefaultCfg.call(this);
  117. return tslib_1.__assign(tslib_1.__assign({}, cfg), { name: 'slider', x: 0, y: 0, width: 100, height: 16, backgroundStyle: {}, foregroundStyle: {}, handlerStyle: {}, textStyle: {}, defaultCfg: {
  118. backgroundStyle: constant_1.BACKGROUND_STYLE,
  119. foregroundStyle: constant_1.FOREGROUND_STYLE,
  120. handlerStyle: constant_1.HANDLER_STYLE,
  121. textStyle: constant_1.TEXT_STYLE,
  122. } });
  123. };
  124. Slider.prototype.update = function (cfg) {
  125. var start = cfg.start, end = cfg.end;
  126. var validCfg = tslib_1.__assign({}, cfg);
  127. if (!util_1.isNil(start)) {
  128. validCfg.start = util_1.clamp(start, 0, 1);
  129. }
  130. if (!util_1.isNil(end)) {
  131. validCfg.end = util_1.clamp(end, 0, 1);
  132. }
  133. _super.prototype.update.call(this, validCfg);
  134. this.minHandler = this.getChildComponentById(this.getElementId('minHandler'));
  135. this.maxHandler = this.getChildComponentById(this.getElementId('maxHandler'));
  136. this.trend = this.getChildComponentById(this.getElementId('trend'));
  137. };
  138. Slider.prototype.init = function () {
  139. this.set('start', util_1.clamp(this.get('start'), 0, 1));
  140. this.set('end', util_1.clamp(this.get('end'), 0, 1));
  141. _super.prototype.init.call(this);
  142. };
  143. Slider.prototype.render = function () {
  144. _super.prototype.render.call(this);
  145. this.updateUI(this.getElementByLocalId('foreground'), this.getElementByLocalId('minText'), this.getElementByLocalId('maxText'));
  146. };
  147. Slider.prototype.renderInner = function (group) {
  148. var _a = this.cfg, start = _a.start, end = _a.end, width = _a.width, height = _a.height, _b = _a.trendCfg, trendCfg = _b === void 0 ? {} : _b, minText = _a.minText, maxText = _a.maxText, _c = _a.backgroundStyle, backgroundStyle = _c === void 0 ? {} : _c, _d = _a.foregroundStyle, foregroundStyle = _d === void 0 ? {} : _d, _e = _a.textStyle, textStyle = _e === void 0 ? {} : _e;
  149. var handlerStyle = util_1.deepMix({}, handler_1.DEFAULT_HANDLER_STYLE, this.cfg.handlerStyle);
  150. var min = start * width;
  151. var max = end * width;
  152. // 趋势图数据
  153. if (util_1.size(util_1.get(trendCfg, 'data'))) {
  154. this.trend = this.addComponent(group, tslib_1.__assign({ component: trend_1.Trend, id: this.getElementId('trend'), x: 0, y: 0, width: width,
  155. height: height }, trendCfg));
  156. }
  157. // 1. 背景
  158. this.addShape(group, {
  159. id: this.getElementId('background'),
  160. type: 'rect',
  161. attrs: tslib_1.__assign({ x: 0, y: 0, width: width,
  162. height: height }, backgroundStyle),
  163. });
  164. // 2. 左右文字
  165. var minTextShape = this.addShape(group, {
  166. id: this.getElementId('minText'),
  167. type: 'text',
  168. attrs: tslib_1.__assign({
  169. // x: 0,
  170. y: height / 2, textAlign: 'right', text: minText, silent: false }, textStyle),
  171. });
  172. var maxTextShape = this.addShape(group, {
  173. id: this.getElementId('maxText'),
  174. type: 'text',
  175. attrs: tslib_1.__assign({
  176. // x: 0,
  177. y: height / 2, textAlign: 'left', text: maxText, silent: false }, textStyle),
  178. });
  179. // 3. 前景 选中背景框
  180. var foregroundShape = this.addShape(group, {
  181. id: this.getElementId('foreground'),
  182. name: 'foreground',
  183. type: 'rect',
  184. attrs: tslib_1.__assign({
  185. // x: 0,
  186. y: 0,
  187. // width: 0,
  188. height: height }, foregroundStyle),
  189. });
  190. // 滑块相关的大小信息
  191. var handlerWidth = util_1.get(handlerStyle, 'width', constant_1.DEFAULT_HANDLER_WIDTH);
  192. var handlerHeight = util_1.get(handlerStyle, 'height', 24);
  193. // 4. 左右滑块
  194. this.minHandler = this.addComponent(group, {
  195. component: handler_1.Handler,
  196. id: this.getElementId('minHandler'),
  197. name: 'handler-min',
  198. x: 0,
  199. y: (height - handlerHeight) / 2,
  200. width: handlerWidth,
  201. height: handlerHeight,
  202. cursor: 'ew-resize',
  203. style: handlerStyle,
  204. });
  205. this.maxHandler = this.addComponent(group, {
  206. component: handler_1.Handler,
  207. id: this.getElementId('maxHandler'),
  208. name: 'handler-max',
  209. x: 0,
  210. y: (height - handlerHeight) / 2,
  211. width: handlerWidth,
  212. height: handlerHeight,
  213. cursor: 'ew-resize',
  214. style: handlerStyle,
  215. });
  216. };
  217. Slider.prototype.applyOffset = function () {
  218. this.moveElementTo(this.get('group'), {
  219. x: this.get('x'),
  220. y: this.get('y'),
  221. });
  222. };
  223. Slider.prototype.initEvent = function () {
  224. this.bindEvents();
  225. };
  226. Slider.prototype.updateUI = function (foregroundShape, minTextShape, maxTextShape) {
  227. var _a = this.cfg, start = _a.start, end = _a.end, width = _a.width, minText = _a.minText, maxText = _a.maxText, handlerStyle = _a.handlerStyle, height = _a.height;
  228. var min = start * width;
  229. var max = end * width;
  230. if (this.trend) {
  231. this.trend.update({
  232. width: width,
  233. height: height,
  234. });
  235. if (!this.get('updateAutoRender')) {
  236. this.trend.render();
  237. }
  238. }
  239. // 1. foreground
  240. foregroundShape.attr('x', min);
  241. foregroundShape.attr('width', max - min);
  242. // 滑块相关的大小信息
  243. var handlerWidth = util_1.get(handlerStyle, 'width', constant_1.DEFAULT_HANDLER_WIDTH);
  244. // 设置文本
  245. minTextShape.attr('text', minText);
  246. maxTextShape.attr('text', maxText);
  247. var _b = this._dodgeText([min, max], minTextShape, maxTextShape), minAttrs = _b[0], maxAttrs = _b[1];
  248. // 2. 左侧滑块和文字位置
  249. if (this.minHandler) {
  250. this.minHandler.update({
  251. x: min - handlerWidth / 2,
  252. });
  253. if (!this.get('updateAutoRender')) {
  254. this.minHandler.render();
  255. }
  256. }
  257. util_1.each(minAttrs, function (v, k) { return minTextShape.attr(k, v); });
  258. // 3. 右侧滑块和文字位置
  259. if (this.maxHandler) {
  260. this.maxHandler.update({
  261. x: max - handlerWidth / 2,
  262. });
  263. if (!this.get('updateAutoRender')) {
  264. this.maxHandler.render();
  265. }
  266. }
  267. util_1.each(maxAttrs, function (v, k) { return maxTextShape.attr(k, v); });
  268. };
  269. Slider.prototype.bindEvents = function () {
  270. var group = this.get('group');
  271. group.on('handler-min:mousedown', this.onMouseDown('minHandler'));
  272. group.on('handler-min:touchstart', this.onMouseDown('minHandler'));
  273. // 2. 右滑块的滑动
  274. group.on('handler-max:mousedown', this.onMouseDown('maxHandler'));
  275. group.on('handler-max:touchstart', this.onMouseDown('maxHandler'));
  276. // 3. 前景选中区域
  277. var foreground = group.findById(this.getElementId('foreground'));
  278. foreground.on('mousedown', this.onMouseDown('foreground'));
  279. foreground.on('touchstart', this.onMouseDown('foreground'));
  280. };
  281. /**
  282. * 调整 offsetRange,因为一些范围的限制
  283. * @param offsetRange
  284. */
  285. Slider.prototype.adjustOffsetRange = function (offsetRange) {
  286. var _a = this.cfg, start = _a.start, end = _a.end;
  287. // 针对不同的滑动组件,处理的方式不同
  288. switch (this.currentTarget) {
  289. case 'minHandler': {
  290. var min = 0 - start;
  291. var max = 1 - start;
  292. return Math.min(max, Math.max(min, offsetRange));
  293. }
  294. case 'maxHandler': {
  295. var min = 0 - end;
  296. var max = 1 - end;
  297. return Math.min(max, Math.max(min, offsetRange));
  298. }
  299. case 'foreground': {
  300. var min = 0 - start;
  301. var max = 1 - end;
  302. return Math.min(max, Math.max(min, offsetRange));
  303. }
  304. }
  305. };
  306. Slider.prototype.updateStartEnd = function (offsetRange) {
  307. var _a = this.cfg, start = _a.start, end = _a.end;
  308. // 操作不同的组件,反馈不一样
  309. switch (this.currentTarget) {
  310. case 'minHandler':
  311. start += offsetRange;
  312. break;
  313. case 'maxHandler':
  314. end += offsetRange;
  315. break;
  316. case 'foreground':
  317. start += offsetRange;
  318. end += offsetRange;
  319. break;
  320. }
  321. this.set('start', start);
  322. this.set('end', end);
  323. };
  324. /**
  325. * 调整 text 的位置,自动躲避
  326. * 根据位置,调整返回新的位置
  327. * @param range
  328. */
  329. Slider.prototype._dodgeText = function (range, minTextShape, maxTextShape) {
  330. var _a, _b;
  331. var _c = this.cfg, handlerStyle = _c.handlerStyle, width = _c.width;
  332. var PADDING = 2;
  333. var handlerWidth = util_1.get(handlerStyle, 'width', constant_1.DEFAULT_HANDLER_WIDTH);
  334. var min = range[0], max = range[1];
  335. var sorted = false;
  336. // 如果交换了位置,则对应的 min max 也交互
  337. if (min > max) {
  338. _a = [max, min], min = _a[0], max = _a[1];
  339. _b = [maxTextShape, minTextShape], minTextShape = _b[0], maxTextShape = _b[1];
  340. sorted = true;
  341. }
  342. // 避让规则,优先显示在两侧,只有显示不下的时候,才显示在中间
  343. var minBBox = minTextShape.getBBox();
  344. var maxBBox = maxTextShape.getBBox();
  345. var minAttrs = minBBox.width > min - PADDING
  346. ? { x: min + handlerWidth / 2 + PADDING, textAlign: 'left' }
  347. : { x: min - handlerWidth / 2 - PADDING, textAlign: 'right' };
  348. var maxAttrs = maxBBox.width > width - max - PADDING
  349. ? { x: max - handlerWidth / 2 - PADDING, textAlign: 'right' }
  350. : { x: max + handlerWidth / 2 + PADDING, textAlign: 'left' };
  351. return !sorted ? [minAttrs, maxAttrs] : [maxAttrs, minAttrs];
  352. };
  353. Slider.prototype.draw = function () {
  354. var container = this.get('container');
  355. var canvas = container && container.get('canvas');
  356. if (canvas) {
  357. canvas.draw();
  358. }
  359. };
  360. Slider.prototype.getContainerDOM = function () {
  361. var container = this.get('container');
  362. var canvas = container && container.get('canvas');
  363. return canvas && canvas.get('container');
  364. };
  365. return Slider;
  366. }(group_component_1.default));
  367. exports.Slider = Slider;
  368. exports.default = Slider;
  369. //# sourceMappingURL=slider.js.map