1. /*
    2. * 简易的拖拽插件
    3. * new Drag([selector],[options]);
    4. * SELECTOR
    5. * 按住谁来实现拖拽
    6. * OPTIONS = {}
    7. * element:拖拽中要移动的元素(默认值:当前按住的元素)
    8. * boundary:是否进行边界校验 (默认值:true,不能超过要移动元素所在容器的范围,需要开发者保证:
    9. 当前移动的元素是相对于它所在容器定位的)
    10. *
    11. * 声明周期函数(钩子函数)
    12. * dragstart:拖拽开始
    13. * dragmove:拖拽中
    14. * dragend:拖拽结束
    15. */
    16. ~ function () {
    17. /*
    18. * 拖拽插件封装
    19. */
    20. class Drag {
    21. constructor(selector, options) {
    22. this.initParams(selector, options);
    23. this._selector.addEventListener('mousedown', this.down.bind(this));
    24. }
    25. // 参数初始化(尽可能把一切信息都挂载到实例上,这样在其它方法中,只要能获取到实例,这些信息都可以调用 => 我们尽可能保证每个方法中的 THIS 都是实例)
    26. initParams(selector, options = {}) {
    27. this._selector = document.querySelector(selector);
    28. // 配置项的默认值信息
    29. let defaultParams = {
    30. element: this._selector,
    31. boundary: true,
    32. dragstart: null,
    33. dragmove: null,
    34. dragend: null
    35. };
    36. defaultParams = Object.assign(defaultParams, options);
    37. // 把配置项信息都挂载到实例上
    38. Drag.each(defaultParams, (value, key) => {
    39. this['_' + key] = value;
    40. });
    41. }
    42. // 实现拖拽的效果
    43. down(ev) {
    44. let {
    45. _element
    46. } = this;
    47. this.startX = ev.pageX;
    48. this.startY = ev.pageY;
    49. this.startL = Drag.queryCss(_element, 'left');
    50. this.startT = Drag.queryCss(_element, 'top');
    51. this._move = this.move.bind(this);
    52. this._up = this.up.bind(this);
    53. document.addEventListener('mousemove', this._move);
    54. document.addEventListener('mouseup', this._up);
    55. // 钩子函数处理
    56. this._dragstart && this._dragstart(this, ev);
    57. }
    58. move(ev) {
    59. let {_element, _boundary, startX, startY, startL, startT} = this;
    60. let curL = ev.pageX - startX + startL,
    61. curT = ev.pageY - startY + startT;
    62. if (_boundary) {
    63. // 处理边界
    64. let parent = _element.parentNode,
    65. minL = 0,
    66. minT = 0,
    67. maxL = parent.offsetWidth - _element.offsetWidth,
    68. maxT = parent.offsetHeight - _element.offsetHeight;
    69. curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
    70. curT = curT < minT ? minT : (curT > maxT ? maxT : curT);
    71. }
    72. _element.style.left = curL + 'px';
    73. _element.style.top = curT + 'px';
    74. // 钩子函数处理
    75. this._dragmove && this._dragmove(this, curL, curT, ev);
    76. }
    77. up(ev) {
    78. document.removeEventListener('mousemove', this._move);
    79. document.removeEventListener('mouseup', this._up);
    80. // 钩子函数处理
    81. this._dragend && this._dragend(this, ev);
    82. }
    83. // 设置工具类的方法(把它当做类[普通对象]的私有属性)
    84. static each(arr, callback) {
    85. if ('length' in arr) {
    86. // 数组 || 类数组
    87. for (let i = 0; i < arr.length; i++) {
    88. callback && callback(arr[i], i);
    89. }
    90. return;
    91. }
    92. // 普通对象
    93. for (let key in arr) {
    94. if (!arr.hasOwnProperty(key)) break;
    95. callback && callback(arr[key], key);
    96. }
    97. }
    98. static queryCss(curEle, attr) {
    99. return parseFloat(window.getComputedStyle(curEle)[attr]);
    100. }
    101. }
    102. window.Drag = Drag;
    103. }();