资讯专栏INFORMATION COLUMN

简单的支持网页画框拖拽缩放功能的js插件

Sunxb / 2601人阅读

摘要:我就不提除此以外还需要实现的一些业务上的细节交互了,本篇文章只讲讲我实现的拖拽功能的原理。这里其实大家就可以看出来了,得益于面向对象的机制,我们可以很简单的实现一些画框拖拽功能。

引言

前不久,老大给我分配一个比较吊炸天的任务。要我实现:在一张图片上,可以用鼠标画框。除此以外,画出来的框,可以实现resize,也就是说可以通过鼠标操作缩放,也可以进行拖拽。我就不提除此以外还需要实现的一些业务上的细节交互了,本篇文章只讲讲我实现的拖拽功能的原理。

初始画框对象

由于也是上的需求,要求不止画一个框,有可能用户会画好多框,如果只是简单的检测鼠标事件定位一个个框,很容易导致缩放和拖拽功能的紊乱,因此,运用面向对象的思想,将拖拽和缩放的框变成一个对象,其所有其他鼠标事件的绑定都在这个对象上。

废话不多说,直接上源码,思路很简单。

function newBox(options) {
    this.container = $("
"); this.dragLeft = $("
"); this.dragTop = $("
"); this.dragRight = $("
"); this.dragBottom = $("
"); this.dragTopLeft = $("
"); this.dragTopRight = $("
"); this.dragBottomLeft = $("
"); this.dragBottomRight = $("
"); this.sureBtn = $("
"); this.cancelBtn = $("
"); this.enableEdit = true; this.init(); this.options = options; } newBox.prototype = { init: function() { this.container.append(this.dragLeft); this.container.append(this.dragTop); this.container.append(this.dragRight); this.container.append(this.dragBottom); this.container.append(this.dragTopLeft); this.container.append(this.dragTopRight); this.container.append(this.dragBottomLeft); this.container.append(this.dragBottomRight); this.container.append(this.sureBtn); this.container.append(this.cancelBtn); this.container.on({ "mousedown": this.containerMouseDown.bind(this), "click": this.enableEditFunc.bind(this) }); this.dragRight.on("mousedown", this.dragRightMouseDown.bind(this)); this.dragLeft.on("mousedown", this.dragLeftMouseDown.bind(this)); this.dragTop.on("mousedown", this.dragTopMouseDown.bind(this)); this.dragBottom.on("mousedown", this.dragBottomMouseDown.bind(this)); this.dragTopLeft.on("mousedown", this.dragTopLeftMouseDown.bind(this)); this.dragTopRight.on("mousedown", this.dragTopRightMouseDown.bind(this)); this.dragBottomRight.on("mousedown", this.dragBottomRightMouseDown.bind(this)); this.dragBottomLeft.on("mousedown", this.dragBottomLeftMouseDown.bind(this)); this.sureBtn.on("click", this.sureFunc.bind(this)); this.cancelBtn.on("click", this.cancelFunc.bind(this)); }, sureFunc: function() { this.disableEditFunc(); if(this.options.sureFunc) this.options.sureFunc(this.container); return false; }, cancelFunc: function() { this.container.remove(); if(this.options.cancelFunc) this.options.cancelFunc(this.container); }, enableEditFunc: function() { var sureBtn = this.sureBtn; // 设置正在编辑的框的zindex为最大 this.container.css("z-index","100000000") // 先保存未保存的 $(".new_rect .sureBtn").each(function() { if($(this)[0] == sureBtn[0]){ return; } $(this).is(":visible") && $(this).click() && $(this).mouseleave(); }) this.enableEdit = true; this.container.find(".new_react-dots, .dots").show(); this.sureBtn.show(); this.cancelBtn.show(); }, disableEditFunc: function() { var width=this.container.width(); var height=this.container.height(); var area=parseInt(width*height); this.container.css("z-index",100000000-area); this.enableEdit = false; this.container.find(".new_react-dots, .dots").hide(); this.sureBtn.hide(); this.cancelBtn.hide(); }, setPosition: function(position) { this.container.css(position) }, dragRightMouseDown: function(ev) { if(!this.enableEdit) return false; var rightElem = this.dragRight; var o_x = ev.pageX; var o_width = this.container.width(); var o_right = parseFloat(this.container.css("right")); if(rightElem.setCapture) { rightElem.setCapture(); } $(document).on("mousemove.dragRight", doDragRight.bind(this)); $(document).on("mouseup.dragRight", stopDragRight.bind(this)); return false; function doDragRight(e) { var right = o_right - e.pageX + o_x; if(right < 0) right = 0; if(right > o_width + o_right) right = o_width + o_right this.setPosition({ right: right }); return false; } function stopDragRight(e) { if(rightElem.releaseCapture) { rightElem.releaseCapture(); } $(document).off("mousemove.dragRight"); $(document).off("mouseup.dragRight"); return false; } }, dragLeftMouseDown: function(ev) { if(!this.enableEdit) return false; var leftElem = this.dragLeft; var o_x = ev.pageX; var o_width = this.container.width(); var o_left = parseFloat(this.container.css("left")); if(leftElem.setCapture) { leftElem.setCapture(); } $(document).on("mousemove.dragLeft", doDragLeft.bind(this)); $(document).on("mouseup.dragLeft", stopDragLeft.bind(this)); return false; function doDragLeft(e) { var left = o_left + e.pageX - o_x; if(left < 0) left = 0; if(left > o_width + o_left) left = o_width + o_left this.setPosition({ left: left }); return false; } function stopDragLeft(e) { if(leftElem.releaseCapture) { leftElem.releaseCapture(); } $(document).off("mousemove.dragLeft"); $(document).off("mouseup.dragLeft"); return false; } }, dragTopMouseDown: function(ev) { if(!this.enableEdit) return false; var topElem = this.dragTop; var o_y = ev.pageY; var o_height = this.container.height(); var o_top = parseFloat(this.container.css("top")); if(topElem.setCapture) { topElem.setCapture(); } $(document).on("mousemove.dragTop", doDragTop.bind(this)); $(document).on("mouseup.dragTop", stopDragTop.bind(this)); return false; function doDragTop(e) { var top = o_top + e.pageY - o_y; if(top < 0) top = 0; if(top > o_top + o_height) top = o_top + o_height this.setPosition({ top: top }); return false; } function stopDragTop(e) { if(topElem.releaseCapture) { topElem.releaseCapture(); } $(document).off("mousemove.dragTop"); $(document).off("mouseup.dragTop"); return false; } }, dragBottomMouseDown: function(ev) { if(!this.enableEdit) return false; var bottomElem = this.dragBottom; var o_y = ev.pageY; var o_height = this.container.height(); var o_bottom = parseFloat(this.container.css("bottom")); if(bottomElem.setCapture) { bottomElem.setCapture(); } $(document).on("mousemove.dragBottom", doDragBottom.bind(this)); $(document).on("mouseup.dragBottom", stopDragBottom.bind(this)); return false; function doDragBottom(e) { var bottom = o_bottom - e.pageY + o_y; if(bottom < 0) bottom = 0; if(bottom > o_bottom + o_height) bottom = o_bottom + o_height this.setPosition({ bottom: bottom }); return false; } function stopDragBottom(e) { if(bottomElem.releaseCapture) { bottomElem.releaseCapture(); } $(document).off("mousemove.dragBottom"); $(document).off("mouseup.dragBottom"); return false; } }, dragTopLeftMouseDown: function(ev) { if(!this.enableEdit) return false; var topLeftElem = this.dragTopLeft; var o_y = ev.pageY; var o_x = ev.pageX; var o_height = this.container.height(); var o_width = this.container.width(); var o_top = parseFloat(this.container.css("top")); var o_left = parseFloat(this.container.css("left")); if(topLeftElem.setCapture) { topLeftElem.setCapture(); } $(document).on("mousemove.dragTopLeft", doDragTopLeft.bind(this)); $(document).on("mouseup.dragTopLeft", stopDragTopLeft.bind(this)); return false; function doDragTopLeft(e) { var top = o_top + e.pageY - o_y; var left = o_left + e.pageX - o_x; if(top < 0) top = 0; if(top > o_top + o_height) top = o_top + o_height; if(left < 0) left = 0; if(left > o_width + o_left) left = o_width + o_left; this.setPosition({ top: top, left: left }); return false; } function stopDragTopLeft(e) { if(topLeftElem.releaseCapture) { topLeftElem.releaseCapture(); } $(document).off("mousemove.dragTopLeft"); $(document).off("mouseup.dragTopLeft"); return false; } }, dragTopRightMouseDown: function(ev) { if(!this.enableEdit) return false; var topRightElem = this.dragTopRight; var o_y = ev.pageY; var o_x = ev.pageX; var o_height = this.container.height(); var o_width = this.container.width(); var o_top = parseFloat(this.container.css("top")); var o_right = parseFloat(this.container.css("right")); if(topRightElem.setCapture) { topRightElem.setCapture(); } $(document).on("mousemove.dragTopRight", doDragTopRight.bind(this)); $(document).on("mouseup.dragTopRight", stopDragTopRight.bind(this)); return false; function doDragTopRight(e) { var top = o_top + e.pageY - o_y; var right = o_right - e.pageX + o_x; if(top < 0) top = 0; if(top > o_top + o_height) top = o_top + o_height; if(right < 0) right = 0; if(right > o_width + o_right) right = o_width + o_right; this.setPosition({ top: top, right: right }); return false; } function stopDragTopRight(e) { if(topRightElem.releaseCapture) { topRightElem.releaseCapture(); } $(document).off("mousemove.dragTopRight"); $(document).off("mouseup.dragTopRight"); return false; } }, dragBottomRightMouseDown: function(ev) { if(!this.enableEdit) return false; var bottomRightElem = this.dragBottomRight; var o_y = ev.pageY; var o_x = ev.pageX; var o_height = this.container.height(); var o_width = this.container.width(); var o_bottom = parseFloat(this.container.css("bottom")); var o_right = parseFloat(this.container.css("right")); if(bottomRightElem.setCapture) { bottomRightElem.setCapture(); } $(document).on("mousemove.dragBottomRight", doDragTopRight.bind(this)); $(document).on("mouseup.dragBottomRight", stopDragTopRight.bind(this)); return false; function doDragTopRight(e) { var bottom = o_bottom - e.pageY + o_y; var right = o_right - e.pageX + o_x; if(bottom < 0) bottom = 0; if(bottom > o_bottom + o_height) bottom = o_bottom + o_height; if(right < 0) right = 0; if(right > o_width + o_right) right = o_width + o_right; this.setPosition({ bottom: bottom, right: right }); return false; } function stopDragTopRight(e) { if(bottomRightElem.releaseCapture) { bottomRightElem.releaseCapture(); } $(document).off("mousemove.dragBottomRight"); $(document).off("mouseup.dragBottomRight"); return false; } }, dragBottomLeftMouseDown: function(ev) { if(!this.enableEdit) return false; var bottomLeftElem = this.dragBottomLeft; var o_y = ev.pageY; var o_x = ev.pageX; var o_height = this.container.height(); var o_width = this.container.width(); var o_bottom = parseFloat(this.container.css("bottom")); var o_left = parseFloat(this.container.css("left")); if(bottomLeftElem.setCapture) { bottomLeftElem.setCapture(); } $(document).on("mousemove.dragBottomLeft", doDragTopLeft.bind(this)); $(document).on("mouseup.dragBottomLeft", stopDragTopLeft.bind(this)); return false; function doDragTopLeft(e) { var bottom = o_bottom - e.pageY + o_y; var left = o_left + e.pageX - o_x; if(bottom < 0) bottom = 0; if(bottom > o_bottom + o_height) bottom = o_bottom + o_height; if(left < 0) left = 0; if(left > o_width + o_left) left = o_width + o_left; this.setPosition({ bottom: bottom, left: left }); return false; } function stopDragTopLeft(e) { if(bottomLeftElem.releaseCapture) { bottomLeftElem.releaseCapture(); } $(document).off("mousemove.dragBottomLeft"); $(document).off("mouseup.dragBottomLeft"); return false; } }, containerMouseDown: function(ev) { if(!this.enableEdit) return false; var o_x = ev.pageX; var o_y = ev.pageY; var containerWidth = this.container.width(); var containerHeight = this.container.height(); var o_top = parseFloat(this.container.css("top")); var o_left = parseFloat(this.container.css("left")); var o_right = parseFloat(this.container.css("right")); var o_bottom = parseFloat(this.container.css("bottom")); if(this.container.setCapture) { this.container.setCapture(); } $(document).on("mousemove.container", doDrag.bind(this)); $(document).on("mouseup.container", stopDrag.bind(this)); return false; function doDrag(e) { var disY = e.pageY - o_y; var disX = e.pageX - o_x; var top = o_top + disY; var left = o_left + disX; var right = o_right - disX; var bottom = o_bottom - disY; if(top < 0) { top = 0; bottom = o_bottom + o_top; } if(bottom < 0) { bottom = 0; top = o_top + o_bottom; } if(left < 0) { left = 0; right = o_right + o_left; } if(right < 0) { right = 0; left = o_right + o_left; } this.setPosition({top: top, bottom: bottom, left: left, right: right}); return false; } function stopDrag(ev) { if(this.container.releaseCapture) { this.container.releaseCapture(); } $(document).off("mousemove.container"); $(document).off("mouseup.container"); return false; } } }

至此,一个支持缩放和拖拽功能的box对象已经创建好了,但是,还没有实现初始画框功能,其实画初始框的思路更加简单,就是记录mousedown的时候鼠标地的x,y坐标和mouseup时鼠标的x,y坐标,然后根据坐标值,设置新建的div的宽度和高度和定位就可以了。下面是源码,我直接把它做成了jquery插件。

$.fn.draw_drag_test = function(options) {
    var position = {}
    var elemWidth, elemHeight, o_x, o_y, d_x, d_y, rect, o_left, o_top;

    var mouseDown = function(e) {
      $(this).on({
        "mousemove": mouseMove,
        "mouseup": mouseUp
      })

      var elemLeft = $(this).offset().left,
          elemTop = $(this).offset().top;

      elemWidth = $(this).width();
      elemHeight = $(this).height();
      o_x = e.pageX;
      o_y = e.pageY;

      position.left = o_left = o_x - elemLeft;
      position.top = o_top = o_y - elemTop;

      rect = new newBox(options);
      rect.container.css("z-index","100000000");
      $(this).append(rect.container);

    }

    var mouseMove = function(e) {
      var m_x = e.pageX,
          m_y = e.pageY;

      d_x = m_x - o_x;
      d_y = m_y - o_y;

      position.right = elemWidth - position.left - d_x;
      position.bottom = elemHeight - position.top - d_y;

      if(d_x < 0) {
          position.right = elemWidth - o_left;
          position.left = o_left + d_x;
      }else {
          position.left = o_left;
      }

      if(d_y < 0) {
          position.bottom = elemHeight - o_top;
          position.top = o_top + d_y;
      }else {
          position.top = o_top;
      }

      rect.setPosition(position);
    }

    var mouseUp = function(e) {
      $(this).off("mouseup", mouseUp);
      $(this).off("mousemove", mouseMove);
      $(this).off("mousedown", mouseDown);
    }

    return this.each(function() {
      $(this).off("mousedown").on({
        "mousedown": mouseDown
      })
      return this;
    })

}

这里其实大家就可以看出来了,得益于面向对象的机制,我们可以很简单的实现一些画框拖拽功能。并且该方法还留了回调的接口,方便根据不同的业务需求进行一些交互操作。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80265.html

相关文章

  • 简单支持网页画框拖拽缩放功能js插件

    摘要:我就不提除此以外还需要实现的一些业务上的细节交互了,本篇文章只讲讲我实现的拖拽功能的原理。这里其实大家就可以看出来了,得益于面向对象的机制,我们可以很简单的实现一些画框拖拽功能。 引言 前不久,老大给我分配一个比较吊炸天的任务。要我实现:在一张图片上,可以用鼠标画框。除此以外,画出来的框,可以实现resize,也就是说可以通过鼠标操作缩放,也可以进行拖拽。我就不提除此以外还需要实现的一...

    oneasp 评论0 收藏0
  • 简单支持网页画框拖拽缩放功能js插件

    摘要:我就不提除此以外还需要实现的一些业务上的细节交互了,本篇文章只讲讲我实现的拖拽功能的原理。这里其实大家就可以看出来了,得益于面向对象的机制,我们可以很简单的实现一些画框拖拽功能。 引言 前不久,老大给我分配一个比较吊炸天的任务。要我实现:在一张图片上,可以用鼠标画框。除此以外,画出来的框,可以实现resize,也就是说可以通过鼠标操作缩放,也可以进行拖拽。我就不提除此以外还需要实现的一...

    MangoGoing 评论0 收藏0
  • 原生js实现拖拽缩放预览图片插件

    摘要:插件只预览该容器下的所有图片。指定该容器里的图片点击预览键的值就是容器的如果觉得样式不满意什么的,可以直接覆盖就可以了。预览总结如有疏忽或错误,希望您及时指出,我会尽早修改。有什么需要交流的可在评论区与我交流 原生js实现拖拽缩放预览图片插件 前言 插件功能暂只满足我司业务需求,如果希望有更多的功能,可在下方留言,我尽量扩展!如果你有需要或者喜欢的话,可以给我github来个star ...

    zhonghanwen 评论0 收藏0
  • 前端插件

    摘要:原文链接前端插件库站点前端开发文档博客前端插件库前端插件库官网是的函数库,目的是强化表格操作如搜索排序,并自动加入组件引入表格中,使用非常灵活简便。由推出,灵活扎实的建议列表函数库。 原文链接:前端插件库站点:前端开发文档博客:前端插件库 前端插件库 DataTables 官网:https://www.datatables.net/ DataTables是jQuery的JavaScr...

    高胜山 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<