AutoScroll.js 2.8 KB

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