draggable.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /**
  2. * Simple draggable tool, just for demo or testing.
  3. * Use jquery.
  4. */
  5. (function (global) {
  6. var BORDER_WIDTH = 4;
  7. var $ = global.jQuery;
  8. global.draggable = {
  9. /**
  10. * @param {HTMLElement} mainEl
  11. * @param {module:echarts/echarts~EChart} chart
  12. * @param {Object} [opt] {width: ..., height: ...}
  13. * @param {number} [opt.width] If not specified, use mainEl current width.
  14. * @param {number} [opt.height] If not specified, use mainEl current height.
  15. * @param {boolean} [opt.lockX=false]
  16. * @param {boolean} [opt.lockY=false]
  17. * @param {number} [opt.throttle=false]
  18. * @return {type} description
  19. */
  20. init: function (mainEl, chart, opt) {
  21. opt = opt || {};
  22. var chartResize = chart ? $.proxy(chart.resize, chart) : function () {};
  23. if (opt.throttle) {
  24. chartResize = throttle(chartResize, opt.throttle, true, false);
  25. }
  26. var mainEl = $(mainEl);
  27. $('.draggable-control').remove();
  28. var controlEl = $(
  29. '<div class="draggable-control">DRAG<span class="draggable-label"></span></div>'
  30. );
  31. controlEl.css({
  32. 'position': 'absolute',
  33. 'border-radius': '30px',
  34. 'width': '60px',
  35. 'height': '60px',
  36. 'line-height': '60px',
  37. 'text-align': 'center',
  38. 'background': '#333',
  39. 'color': '#fff',
  40. 'cursor': 'pointer',
  41. 'font-size': '18px',
  42. 'box-shadow': '0 0 5px #333',
  43. '-webkit-user-select': 'none',
  44. 'user-select': 'none'
  45. });
  46. var label = controlEl.find('.draggable-label');
  47. label.css({
  48. 'display': 'block',
  49. 'position': 'absolute',
  50. 'color': '#000',
  51. 'font-size': '12px',
  52. 'text-align': 'center',
  53. 'left': 0,
  54. 'top': '65px',
  55. 'width': '60px',
  56. 'line-height': 1
  57. });
  58. mainEl.css({
  59. 'position': 'absolute',
  60. 'left': mainEl[0].offsetLeft + 'px',
  61. 'top': mainEl[0].offsetTop + 'px',
  62. 'width': mainEl[0].offsetWidth + 'px',
  63. 'height': mainEl[0].offsetHeight + 'px',
  64. 'border-style': 'solid',
  65. 'border-color': '#ddd',
  66. 'border-width': BORDER_WIDTH + 'px',
  67. 'padding': 0,
  68. 'margin': 0
  69. });
  70. mainEl.parent().append(controlEl);
  71. var controlSize = controlEl[0].offsetWidth;
  72. var boxSizing = mainEl.css('box-sizing');
  73. var borderBoxBroder = boxSizing === 'border-box' ? 2 * BORDER_WIDTH : 0;
  74. var mainContentWidth = opt.width || (mainEl.width() + borderBoxBroder);
  75. var mainContentHeight = opt.height || (mainEl.height() + borderBoxBroder);
  76. var mainOffset = mainEl.offset();
  77. resize(
  78. mainOffset.left + mainContentWidth + BORDER_WIDTH,
  79. mainOffset.top + mainContentHeight + BORDER_WIDTH,
  80. true
  81. );
  82. var dragging = false;
  83. controlEl.on('mousedown', function () {
  84. dragging = true;
  85. });
  86. $(document).on('mousemove', function (e) {
  87. if (dragging) {
  88. resize(e.pageX, e.pageY);
  89. }
  90. });
  91. $(document).on('mouseup', function () {
  92. dragging = false;
  93. });
  94. function resize(x, y, isInit) {
  95. var mainOffset = mainEl.offset();
  96. var mainPosition = mainEl.position();
  97. var mainContentWidth = x - mainOffset.left - BORDER_WIDTH;
  98. var mainContentHeight = y - mainOffset.top - BORDER_WIDTH;
  99. if (isInit || !opt.lockX) {
  100. controlEl.css(
  101. 'left',
  102. (mainPosition.left + mainContentWidth + BORDER_WIDTH - controlSize / 2) + 'px'
  103. );
  104. mainEl.css(
  105. 'width',
  106. (mainContentWidth + borderBoxBroder) + 'px'
  107. );
  108. }
  109. if (isInit || !opt.lockY) {
  110. controlEl.css(
  111. 'top',
  112. (mainPosition.top + mainContentHeight + BORDER_WIDTH - controlSize / 2) + 'px'
  113. );
  114. mainEl.css(
  115. 'height',
  116. (mainContentHeight + borderBoxBroder) + 'px'
  117. );
  118. }
  119. label.text(Math.round(mainContentWidth) + ' x ' + Math.round(mainContentHeight));
  120. chartResize();
  121. }
  122. }
  123. };
  124. function throttle(fn, delay, trailing, debounce) {
  125. var currCall = (new Date()).getTime();
  126. var lastCall = 0;
  127. var lastExec = 0;
  128. var timer = null;
  129. var diff;
  130. var scope;
  131. var args;
  132. var isSingle = typeof fn === 'function';
  133. delay = delay || 0;
  134. if (isSingle) {
  135. return createCallback();
  136. }
  137. else {
  138. var ret = [];
  139. for (var i = 0; i < fn.length; i++) {
  140. ret[i] = createCallback(i);
  141. }
  142. return ret;
  143. }
  144. function createCallback(index) {
  145. function exec() {
  146. lastExec = (new Date()).getTime();
  147. timer = null;
  148. (isSingle ? fn : fn[index]).apply(scope, args || []);
  149. }
  150. var cb = function () {
  151. currCall = (new Date()).getTime();
  152. scope = this;
  153. args = arguments;
  154. diff = currCall - (debounce ? lastCall : lastExec) - delay;
  155. clearTimeout(timer);
  156. if (debounce) {
  157. if (trailing) {
  158. timer = setTimeout(exec, delay);
  159. }
  160. else if (diff >= 0) {
  161. exec();
  162. }
  163. }
  164. else {
  165. if (diff >= 0) {
  166. exec();
  167. }
  168. else if (trailing) {
  169. timer = setTimeout(exec, -diff);
  170. }
  171. }
  172. lastCall = currCall;
  173. };
  174. /**
  175. * Clear throttle.
  176. * @public
  177. */
  178. cb.clear = function () {
  179. if (timer) {
  180. clearTimeout(timer);
  181. timer = null;
  182. }
  183. };
  184. return cb;
  185. }
  186. }
  187. })(window);