AutoScroll.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import { assign } from 'min-dash';
  2. import {
  3. toPoint
  4. } from '../../util/Event';
  5. /**
  6. * Initiates canvas scrolling if current cursor point is close to a border.
  7. * Cancelled when current point moves back inside the scrolling borders
  8. * or cancelled manually.
  9. *
  10. * Default options :
  11. * scrollThresholdIn: [ 20, 20, 20, 20 ],
  12. * scrollThresholdOut: [ 0, 0, 0, 0 ],
  13. * scrollRepeatTimeout: 15,
  14. * scrollStep: 10
  15. *
  16. * Threshold order:
  17. * [ left, top, right, bottom ]
  18. */
  19. export default function AutoScroll(config, eventBus, canvas, mouseTracking) {
  20. this._canvas = canvas;
  21. this._mouseTracking = mouseTracking;
  22. this._opts = assign({
  23. scrollThresholdIn: [ 20, 20, 20, 20 ],
  24. scrollThresholdOut: [ 0, 0, 0, 0 ],
  25. scrollRepeatTimeout: 15,
  26. scrollStep: 10
  27. }, config);
  28. var self = this;
  29. eventBus.on('drag.move', function(e) {
  30. var point = self._toBorderPoint(e);
  31. self.startScroll(point);
  32. });
  33. eventBus.on([ 'drag.cleanup' ], function() {
  34. self.stopScroll();
  35. });
  36. }
  37. AutoScroll.$inject = [
  38. 'config.autoScroll',
  39. 'eventBus',
  40. 'canvas',
  41. 'mouseTracking'
  42. ];
  43. /**
  44. * Starts scrolling loop.
  45. * Point is given in global scale in canvas container box plane.
  46. *
  47. * @param {Object} point { x: X, y: Y }
  48. */
  49. AutoScroll.prototype.startScroll = function(point) {
  50. var canvas = this._canvas;
  51. var opts = this._opts;
  52. var self = this;
  53. var clientRect = canvas.getContainer().getBoundingClientRect();
  54. var diff = [
  55. point.x,
  56. point.y,
  57. clientRect.width - point.x,
  58. clientRect.height - point.y
  59. ];
  60. this.stopScroll();
  61. var dx = 0,
  62. dy = 0;
  63. for (var i = 0; i < 4; i++) {
  64. if (between(diff[i], opts.scrollThresholdOut[i], opts.scrollThresholdIn[i])) {
  65. if (i === 0) {
  66. dx = opts.scrollStep;
  67. } else if (i == 1) {
  68. dy = opts.scrollStep;
  69. } else if (i == 2) {
  70. dx = -opts.scrollStep;
  71. } else if (i == 3) {
  72. dy = -opts.scrollStep;
  73. }
  74. }
  75. }
  76. if (dx !== 0 || dy !== 0) {
  77. canvas.scroll({ dx: dx, dy: dy });
  78. this._scrolling = setTimeout(function() {
  79. self.startScroll(point);
  80. }, opts.scrollRepeatTimeout);
  81. }
  82. };
  83. function between(val, start, end) {
  84. if (start < val && val < end) {
  85. return true;
  86. }
  87. return false;
  88. }
  89. /**
  90. * Stops scrolling loop.
  91. */
  92. AutoScroll.prototype.stopScroll = function() {
  93. clearTimeout(this._scrolling);
  94. };
  95. /**
  96. * Overrides defaults options.
  97. *
  98. * @param {Object} options
  99. */
  100. AutoScroll.prototype.setOptions = function(options) {
  101. this._opts = assign({}, this._opts, options);
  102. };
  103. /**
  104. * Converts event to a point in canvas container plane in global scale.
  105. *
  106. * @param {Event} event
  107. * @return {Point}
  108. */
  109. AutoScroll.prototype._toBorderPoint = function(event) {
  110. var clientRect = this._canvas._container.getBoundingClientRect();
  111. var globalPosition = toPoint(event.originalEvent);
  112. return {
  113. x: globalPosition.x - clientRect.left,
  114. y: globalPosition.y - clientRect.top
  115. };
  116. };