scrollbar.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. import { __assign, __extends } from "tslib";
  2. import { addEventListener } from '@antv/dom-util';
  3. import { clamp, deepMix, get, noop } from '@antv/util';
  4. import GroupComponent from '../abstract/group-component';
  5. var DEFAULT_STYLE = {
  6. trackColor: 'rgba(0,0,0,0)',
  7. thumbColor: 'rgba(0,0,0,0.15)',
  8. size: 8,
  9. lineCap: 'round',
  10. };
  11. export var DEFAULT_THEME = {
  12. // 默认样式
  13. default: DEFAULT_STYLE,
  14. // 鼠标 hover 的样式
  15. hover: {
  16. thumbColor: 'rgba(0,0,0,0.2)',
  17. },
  18. };
  19. var Scrollbar = /** @class */ (function (_super) {
  20. __extends(Scrollbar, _super);
  21. function Scrollbar() {
  22. var _this = _super !== null && _super.apply(this, arguments) || this;
  23. _this.clearEvents = noop;
  24. _this.onStartEvent = function (isMobile) { return function (e) {
  25. _this.isMobile = isMobile;
  26. e.originalEvent.preventDefault();
  27. var clientX = isMobile ? get(e.originalEvent, 'touches.0.clientX') : e.clientX;
  28. var clientY = isMobile ? get(e.originalEvent, 'touches.0.clientY') : e.clientY;
  29. // 将开始的点记录下来
  30. _this.startPos = _this.cfg.isHorizontal ? clientX : clientY;
  31. _this.bindLaterEvent();
  32. }; };
  33. _this.bindLaterEvent = function () {
  34. var containerDOM = _this.getContainerDOM();
  35. var events = [];
  36. if (_this.isMobile) {
  37. events = [
  38. addEventListener(containerDOM, 'touchmove', _this.onMouseMove),
  39. addEventListener(containerDOM, 'touchend', _this.onMouseUp),
  40. addEventListener(containerDOM, 'touchcancel', _this.onMouseUp),
  41. ];
  42. }
  43. else {
  44. events = [
  45. addEventListener(containerDOM, 'mousemove', _this.onMouseMove),
  46. addEventListener(containerDOM, 'mouseup', _this.onMouseUp),
  47. // 为了保证划出 canvas containerDom 时还没触发 mouseup
  48. addEventListener(containerDOM, 'mouseleave', _this.onMouseUp),
  49. ];
  50. }
  51. _this.clearEvents = function () {
  52. events.forEach(function (e) {
  53. e.remove();
  54. });
  55. };
  56. };
  57. // 拖拽滑块的事件回调
  58. // 这里是 dom 原生事件,绑定在 dom 元素上的
  59. _this.onMouseMove = function (e) {
  60. var _a = _this.cfg, isHorizontal = _a.isHorizontal, thumbOffset = _a.thumbOffset;
  61. e.preventDefault();
  62. var clientX = _this.isMobile ? get(e, 'touches.0.clientX') : e.clientX;
  63. var clientY = _this.isMobile ? get(e, 'touches.0.clientY') : e.clientY;
  64. // 鼠标松开的位置
  65. var endPos = isHorizontal ? clientX : clientY;
  66. // 滑块需要移动的距离, 由于这里是对滑块监听,所以移动的距离就是 diffDis, 如果监听对象是 container dom,则需要算比例
  67. var diff = endPos - _this.startPos;
  68. // 更新 _startPos
  69. _this.startPos = endPos;
  70. _this.updateThumbOffset(thumbOffset + diff);
  71. };
  72. _this.onMouseUp = function (e) {
  73. e.preventDefault();
  74. _this.clearEvents();
  75. };
  76. // 点击滑道的事件回调,移动滑块位置
  77. _this.onTrackClick = function (e) {
  78. var _a = _this.cfg, isHorizontal = _a.isHorizontal, x = _a.x, y = _a.y, thumbLen = _a.thumbLen;
  79. var containerDOM = _this.getContainerDOM();
  80. var rect = containerDOM.getBoundingClientRect();
  81. var clientX = e.clientX, clientY = e.clientY;
  82. var offset = isHorizontal ? clientX - rect.left - x - thumbLen / 2 : clientY - rect.top - y - thumbLen / 2;
  83. var newOffset = _this.validateRange(offset);
  84. _this.updateThumbOffset(newOffset);
  85. };
  86. _this.onThumbMouseOver = function () {
  87. var thumbColor = _this.cfg.theme.hover.thumbColor;
  88. _this.getElementByLocalId('thumb').attr('stroke', thumbColor);
  89. _this.draw();
  90. };
  91. _this.onThumbMouseOut = function () {
  92. var thumbColor = _this.cfg.theme.default.thumbColor;
  93. _this.getElementByLocalId('thumb').attr('stroke', thumbColor);
  94. _this.draw();
  95. };
  96. return _this;
  97. }
  98. Scrollbar.prototype.setRange = function (min, max) {
  99. this.set('minLimit', min);
  100. this.set('maxLimit', max);
  101. var curValue = this.getValue();
  102. var newValue = clamp(curValue, min, max);
  103. if (curValue !== newValue && !this.get('isInit')) {
  104. this.setValue(newValue);
  105. }
  106. };
  107. Scrollbar.prototype.getRange = function () {
  108. var min = this.get('minLimit') || 0;
  109. var max = this.get('maxLimit') || 1;
  110. return { min: min, max: max };
  111. };
  112. Scrollbar.prototype.setValue = function (value) {
  113. var range = this.getRange();
  114. var originalValue = this.getValue();
  115. this.update({
  116. thumbOffset: (this.get('trackLen') - this.get('thumbLen')) * clamp(value, range.min, range.max),
  117. });
  118. this.delegateEmit('valuechange', {
  119. originalValue: originalValue,
  120. value: this.getValue(),
  121. });
  122. };
  123. Scrollbar.prototype.getValue = function () {
  124. return clamp(this.get('thumbOffset') / (this.get('trackLen') - this.get('thumbLen')), 0, 1);
  125. };
  126. Scrollbar.prototype.getDefaultCfg = function () {
  127. var cfg = _super.prototype.getDefaultCfg.call(this);
  128. return __assign(__assign({}, cfg), { name: 'scrollbar', isHorizontal: true, minThumbLen: 20, thumbOffset: 0, theme: DEFAULT_THEME });
  129. };
  130. Scrollbar.prototype.renderInner = function (group) {
  131. this.renderTrackShape(group);
  132. this.renderThumbShape(group);
  133. };
  134. Scrollbar.prototype.applyOffset = function () {
  135. this.moveElementTo(this.get('group'), {
  136. x: this.get('x'),
  137. y: this.get('y'),
  138. });
  139. };
  140. Scrollbar.prototype.initEvent = function () {
  141. this.bindEvents();
  142. };
  143. // 创建滑道的 shape
  144. Scrollbar.prototype.renderTrackShape = function (group) {
  145. var _a = this.cfg, trackLen = _a.trackLen, _b = _a.theme, theme = _b === void 0 ? { default: {} } : _b;
  146. var _c = deepMix({}, DEFAULT_THEME, theme).default, lineCap = _c.lineCap, trackColor = _c.trackColor, themeSize = _c.size;
  147. var size = get(this.cfg, 'size', themeSize);
  148. var attrs = this.get('isHorizontal')
  149. ? {
  150. x1: 0 + size / 2,
  151. y1: size / 2,
  152. x2: trackLen - size / 2,
  153. y2: size / 2,
  154. lineWidth: size,
  155. stroke: trackColor,
  156. lineCap: lineCap,
  157. }
  158. : {
  159. x1: size / 2,
  160. y1: 0 + size / 2,
  161. x2: size / 2,
  162. y2: trackLen - size / 2,
  163. lineWidth: size,
  164. stroke: trackColor,
  165. lineCap: lineCap,
  166. };
  167. return this.addShape(group, {
  168. id: this.getElementId('track'),
  169. name: 'track',
  170. type: 'line',
  171. attrs: attrs,
  172. });
  173. };
  174. // 创建滑块的 shape
  175. Scrollbar.prototype.renderThumbShape = function (group) {
  176. var _a = this.cfg, thumbOffset = _a.thumbOffset, thumbLen = _a.thumbLen, theme = _a.theme;
  177. var _b = deepMix({}, DEFAULT_THEME, theme).default, themeSize = _b.size, lineCap = _b.lineCap, thumbColor = _b.thumbColor;
  178. var size = get(this.cfg, 'size', themeSize);
  179. var attrs = this.get('isHorizontal')
  180. ? {
  181. x1: thumbOffset + size / 2,
  182. y1: size / 2,
  183. x2: thumbOffset + thumbLen - size / 2,
  184. y2: size / 2,
  185. lineWidth: size,
  186. stroke: thumbColor,
  187. lineCap: lineCap,
  188. cursor: 'default',
  189. }
  190. : {
  191. x1: size / 2,
  192. y1: thumbOffset + size / 2,
  193. x2: size / 2,
  194. y2: thumbOffset + thumbLen - size / 2,
  195. lineWidth: size,
  196. stroke: thumbColor,
  197. lineCap: lineCap,
  198. cursor: 'default',
  199. };
  200. return this.addShape(group, {
  201. id: this.getElementId('thumb'),
  202. name: 'thumb',
  203. type: 'line',
  204. attrs: attrs,
  205. });
  206. };
  207. Scrollbar.prototype.bindEvents = function () {
  208. var group = this.get('group');
  209. group.on('mousedown', this.onStartEvent(false));
  210. group.on('mouseup', this.onMouseUp);
  211. group.on('touchstart', this.onStartEvent(true));
  212. group.on('touchend', this.onMouseUp);
  213. var trackShape = group.findById(this.getElementId('track'));
  214. trackShape.on('click', this.onTrackClick);
  215. var thumbShape = group.findById(this.getElementId('thumb'));
  216. thumbShape.on('mouseover', this.onThumbMouseOver);
  217. thumbShape.on('mouseout', this.onThumbMouseOut);
  218. };
  219. Scrollbar.prototype.getContainerDOM = function () {
  220. var container = this.get('container');
  221. var canvas = container && container.get('canvas');
  222. return canvas && canvas.get('container');
  223. };
  224. Scrollbar.prototype.validateRange = function (offset) {
  225. var _a = this.cfg, thumbLen = _a.thumbLen, trackLen = _a.trackLen;
  226. var newOffset = offset;
  227. if (offset + thumbLen > trackLen) {
  228. newOffset = trackLen - thumbLen;
  229. }
  230. else if (offset + thumbLen < thumbLen) {
  231. newOffset = 0;
  232. }
  233. return newOffset;
  234. };
  235. Scrollbar.prototype.draw = function () {
  236. var container = this.get('container');
  237. var canvas = container && container.get('canvas');
  238. if (canvas) {
  239. canvas.draw();
  240. }
  241. };
  242. Scrollbar.prototype.updateThumbOffset = function (offset) {
  243. var _a = this.cfg, thumbOffset = _a.thumbOffset, isHorizontal = _a.isHorizontal, thumbLen = _a.thumbLen, size = _a.size;
  244. var newOffset = this.validateRange(offset);
  245. if (newOffset === thumbOffset) {
  246. // 如果更新后的 offset 与原值相同,则不改变
  247. return;
  248. }
  249. var thumbShape = this.getElementByLocalId('thumb');
  250. if (isHorizontal) {
  251. thumbShape.attr({
  252. x1: newOffset + size / 2,
  253. x2: newOffset + thumbLen - size / 2,
  254. });
  255. }
  256. else {
  257. thumbShape.attr({
  258. y1: newOffset + size / 2,
  259. y2: newOffset + thumbLen - size / 2,
  260. });
  261. }
  262. this.emitOffsetChange(newOffset);
  263. };
  264. Scrollbar.prototype.emitOffsetChange = function (offset) {
  265. var _a = this.cfg, originalValue = _a.thumbOffset, trackLen = _a.trackLen, thumbLen = _a.thumbLen;
  266. this.cfg.thumbOffset = offset;
  267. // 发送事件
  268. this.emit('scrollchange', {
  269. thumbOffset: offset,
  270. ratio: clamp(offset / (trackLen - thumbLen), 0, 1),
  271. });
  272. this.delegateEmit('valuechange', {
  273. originalValue: originalValue,
  274. value: offset,
  275. });
  276. };
  277. return Scrollbar;
  278. }(GroupComponent));
  279. export { Scrollbar };
  280. //# sourceMappingURL=scrollbar.js.map