图形四边伸缩可拖拽

视频或图片上方选区功能 矩形可修改大小和位置 如图:
视频选区

原生HTML版本

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>四边伸缩可拖拽可限制最小宽高又不超浏览器范围</title>
    <style>
        body {background: #f9f9f9;}
        .block {width: 300px; height: 300px; min-width: 200px; min-height: 200px; background: #fff; position: absolute; left: calc(50% - 150px); top: calc(50% - 150px); box-shadow: 0 10px 20px -10px rgba(0,0,0,0.3);}
        header {height: 40px; background: rgba(63, 81, 181, 0.8); line-height: 40px; text-align: center; color: #fff; cursor: pointer; font-size: 14px;}
        header:hover {background: rgba(63, 81, 181, 1);}
        article {padding: 20px; font-size: 14px;}
        .border {position: absolute; z-index: 9999; background: rgba(233, 30, 99, 0.2); cursor: pointer;}
        .border:hover {background: rgba(233, 30, 99, 0.5);}
        #border-top,#border-bottom {width: 100%; height: 10px; cursor: ns-resize;}
        #border-right,#border-left {width: 10px; height: 100%; cursor: ew-resize;}
        #border-right-top,#border-right-bottom,#border-left-bottom,#border-left-top {width: 10px; height: 10px;}
        #border-top,#border-left-top {top: 0; left: 0;}
        #border-right,#border-right-top {top: 0; right: 0;}
        #border-bottom,#border-left-bottom {left: 0; bottom: 0;}
        #border-left {top: 0; left: 0;}
        #border-right-bottom {right: 0; bottom: 0;}
        #border-left-top,#border-right-bottom {cursor: nwse-resize;}
        #border-right-top,#border-left-bottom {cursor: nesw-resize;}
    </style>
    <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script>
</head>
<body>

    <div class="block">
        <div class="border" id="border-top"></div>
        <div class="border" id="border-right"></div>
        <div class="border" id="border-bottom"></div>
        <div class="border" id="border-left"></div>
        <div class="border" id="border-right-top"></div>
        <div class="border" id="border-right-bottom"></div>
        <div class="border" id="border-left-bottom"></div>
        <div class="border" id="border-left-top"></div>
        <header>拖拽区域</header>
        <article>我是内容我是内容我是内容我是内容我是内容我是内容我是内容</article>
    </div>

    <script>

        var thisBlock = $('.block');

        $(document).mousemove(function(e) {
            if (!!this.move) {
                var posix = !document.move_target ? {'x': 0, 'y': 0} : document.move_target.posix,
                callback = document.call_down || function() {
                    $(this.move_target).css({
                        'top': e.pageY - posix.y,
                        'left': e.pageX - posix.x
                    });
                };
                
                callback.call(this, e, posix);
            }
        }).mouseup(function(e) {
            if (!!this.move) {
                var callback = document.call_up || function(){};
                callback.call(this, e);
                $.extend(this, {
                    'move': false,
                    'move_target': null,
                    'call_down': false,
                    'call_up': false
                });
            }
        });

        $('header').mousedown(function(e) {
            e.stopPropagation();
            var drag = thisBlock[0]; 
            var e = e || window.event;
            var diffX = e.clientX - drag.offsetLeft;
            var diffY = e.clientY - drag.offsetTop; 
            if(drag.setCapture){ 
                drag.setCapture(); 
            }else{
                e.preventDefault()?e.preventDefault():returnValue=false;
            }
            document.onmousemove = function(e) { 
                var e = e || window.event;
                var left=e.clientX-diffX; 
                var top=e.clientY-diffY; 
                if(left<0){ 
                    left=0; 
                }else if(left >window.innerWidth-drag.offsetWidth){ 
                    left = window.innerWidth-drag.offsetWidth; 
                } 
                if(top<0){ 
                    top=0; 
                }else if(top >window.innerHeight-drag.offsetHeight){ 
                    top = window.innerHeight-drag.offsetHeight; 
                } 
                drag.style.left = left+ 'px'; 
                drag.style.top = top + 'px'; 
            }; 
            document.onmouseup = function(e) {
                this.onmousemove = null; 
                this.onmouseup = null;
                if(drag.releaseCapture){ 
                    drag.releaseCapture(); 
                } 
            }; 
        })

        $('.border').on('mousedown',function(e){
            var oDiv = thisBlock[0];
            e = e || event;
            var disX = e.clientX - oDiv.offsetLeft;
            var disY = e.clientY - oDiv.offsetTop;
            var oldX = e.clientX;
            var oldY = e.clientY;
            var chatWidth = oDiv.offsetWidth;
            var chatHeight = oDiv.offsetHeight;
            var chatMinWidth = Number(thisBlock.css('min-width').split('px')[0]);
            var chatMinHeight = Number(thisBlock.css('min-height').split('px')[0]);
            $.extend(document, {'move': true, 'call_down': function(ev) {
                ev = ev || event;
                ev.preventDefault()?ev.preventDefault():returnValue=false;
                if (disX <= 10) { // 左
                    if(ev.clientX <= 0){
                        ev.clientX = 0;
                    }
                    oDiv.style.width = oDiv.offsetWidth - (ev.clientX - oldX) + 'px';
                    if(oDiv.offsetWidth <= chatMinWidth){
                        ev.clientX = e.clientX + chatWidth - chatMinWidth;
                    }
                    oDiv.style.left = oDiv.offsetLeft + (ev.clientX - oldX) + 'px';
                } else if (disX >= (oDiv.offsetWidth - 10)) { // 右
                    if(ev.clientX >= $(window).width()){
                        ev.clientX = $(window).width();
                    }
                    oDiv.style.width = oDiv.offsetWidth + (ev.clientX - oldX) + 'px';
                    if(oDiv.offsetWidth <= chatMinWidth){
                        ev.clientX = e.clientX - chatWidth + chatMinWidth;
                    }
                    disX = ev.clientX - oDiv.offsetLeft;
                }
                if (disY <= 10) { // 上
                    if(ev.clientY <= 0){
                        ev.clientY = 0;
                    }
                    oDiv.style.height = oDiv.offsetHeight - (ev.clientY - oldY) + 'px';
                    if(oDiv.offsetHeight <= chatMinHeight){
                        ev.clientY = e.clientY + chatHeight - chatMinHeight;
                    }
                    oDiv.style.top = oDiv.offsetTop + (ev.clientY - oldY) + 'px';
                } else if (disY >= (oDiv.offsetHeight - 10)) { // 下
                    if(ev.clientY >= $(window).height()){
                        ev.clientY = $(window).height();
                    }
                    oDiv.style.height = oDiv.offsetHeight + (ev.clientY - oldY) + 'px';
                    if(oDiv.offsetHeight <= chatMinHeight){
                        ev.clientY = e.clientY - chatHeight + chatMinHeight;
                    }
                    disY = ev.clientY - oDiv.offsetTop;
                }
                oldX = ev.clientX;
                oldY = ev.clientY;
            }});
        })
            
        $('.border').onmouseup = function () {
            document.onmouseup = document.onmousemove = null;
        }

    </script>

</body>
</html>

vue版本

<template>
  <div>
    <div class="block" id="dragbox">
      <div class="border" id="border-top" @mousedown="handleDragPer"></div>
      <div class="border" id="border-right" @mousedown="handleDragPer"></div>
      <div class="border" id="border-bottom" @mousedown="handleDragPer"></div>
      <div class="border" id="border-left" @mousedown="handleDragPer"></div>
      <div class="border border-dot" id="border-right-top" @mousedown="handleDragPer"></div>
      <div class="border border-dot" id="border-right-bottom" @mousedown="handleDragPer"></div>
      <div class="border border-dot" id="border-left-bottom" @mousedown="handleDragPer"></div>
      <div class="border border-dot" id="border-left-top" @mousedown="handleDragPer"></div>

      <div class="drag-content" @mousedown="handleDragAll"></div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'drag-drop',
  props: {
    vWidth: { default: 600 },
    vHeight: { default: 337 },
  },
  data() {
    return {};
  },
  mounted() {
    this.setInitMouse();
    this.resetDragBox();

    window.onresize = () => {
      this.resetDragBox();
    };

    //监听页面滚动
    // window.addEventListener('scroll', () => {});
  },
  methods: {
    resetDragBox() {
      let vPos = $('#videoCol').offset();
      $('#dragbox').css('left', vPos.left + 60);
      $('#dragbox').css('top', vPos.top);
      $('#dragbox').css('width', '100px');
      $('#dragbox').css('height', '70px');
      // this.setInitMouse();
    },
    setInitMouse() {
      $(document)
        .mousemove(function(e) {
          if (!!this.move) {
            var posix = !document.move_target ? { x: 0, y: 0 } : document.move_target.posix,
              callback =
                document.call_down ||
                function() {
                  $(this.move_target).css({
                    top: e.pageY - posix.y,
                    left: e.pageX - posix.x,
                  });
                };

            callback.call(this, e, posix);
          }
        })
        .mouseup(function(e) {
          if (!!this.move) {
            var callback = document.call_up || function() {};
            callback.call(this, e);
            $.extend(this, {
              move: false,
              move_target: null,
              call_down: false,
              call_up: false,
            });
          }
        });

      $('.border').onmouseup = function() {
        document.onmouseup = document.onmousemove = null;
      };
    },
    handleDragAll(e) {
      e.stopPropagation();

      var thisBlock = $('.block');
      var drag = thisBlock[0];
      var e = e || window.event;
      var diffX = e.clientX - drag.offsetLeft;
      var diffY = e.clientY - drag.offsetTop;

      if (drag.setCapture) {
        drag.setCapture();
      } else {
        e.preventDefault && e.preventDefault();
      }
      document.onmousemove = (e) => {
        var e = e || window.event;
        // TODO: 限定有效区域 videoCol位置
        var nowX = thisBlock.offset().left;
        var nowY = thisBlock.offset().top;
        var diffRelateX = nowX - drag.offsetLeft + 1.5;
        var diffRelateY = nowY - drag.offsetTop + 2;

        var minX = $('#videoCol').offset().left + 5 - diffRelateX;
        var maxX = minX + this.vWidth - thisBlock.width() + 1 - diffRelateX;
        var minY = $('#videoCol').offset().top + 3 - diffRelateY;
        var maxY = minY + this.vHeight - thisBlock.height() + 74 - 4 - diffRelateY;

        var left = e.clientX - diffX;
        var top = e.clientY - diffY;
        // if (left < 0) {
        //   left = 0;
        // } else
        if (left < minX) {
          left = minX;
        } else if (left > maxX) {
          left = maxX;
        } else if (left > window.innerWidth - drag.offsetWidth) {
          left = window.innerWidth - drag.offsetWidth;
        }

        // if (top < 0) {
        //   top = 0;
        // } else
        if (top < minY) {
          top = minY;
        } else if (top > maxY) {
          top = maxY;
        } else if (top > window.innerHeight - drag.offsetHeight) {
          top = window.innerHeight - drag.offsetHeight;
        }
        drag.style.left = left + 'px';
        drag.style.top = top + 'px';
      };
      document.onmouseup = function(e) {
        this.onmousemove = null;
        this.onmouseup = null;
        if (drag.releaseCapture) {
          drag.releaseCapture();
        }
      };
    },
    handleDragPer(e) {
      let topHide = $(document).scrollTop();
      let leftHide = $(document).scrollLeft();
      if (topHide !== 0 || leftHide !== 0) {
        console.log('偏移===>', topHide, leftHide); // 偏移 204 0
        scrollTo(0, 0);
      }

      var thisBlock = $('.block');
      var oDiv = thisBlock[0];
      // e = e || event;

      var disX = e.clientX - oDiv.offsetLeft - 10;
      var disY = e.clientY - oDiv.offsetTop - 74;
      var oldX = e.clientX;
      var oldY = e.clientY;
      var chatWidth = oDiv.offsetWidth;
      var chatHeight = oDiv.offsetHeight;
      var chatMinWidth = Number(thisBlock.css('min-width').split('px')[0]);
      var chatMinHeight = Number(thisBlock.css('min-height').split('px')[0]);
      $.extend(document, {
        move: true,
        call_down: (ev) => {
          // ev = ev || event;
          e.preventDefault && e.preventDefault();

          // TODO: 限定有效区域 videoCol位置
          var nowX = thisBlock.offset().left;
          var diffRelateX = nowX - oDiv.offsetLeft + 1.5;
          var nowY = thisBlock.offset().top;
          var diffRelateY = nowY - oDiv.offsetTop;
          // console.log('nowY', nowY, oDiv.offsetTop, diffRelateY); // 271 196 77

          var minX = $('#videoCol').offset().left + 9 - diffRelateX;
          var maxX = minX + this.vWidth;
          var minY = $('#videoCol').offset().top + 1;
          var maxY = minY + this.vHeight - 8;

          if (disX <= 10) {
            // 左
            // if (ev.clientX <= 0) {
            //   ev.clientX = 0;
            // }
            if (ev.clientX <= minX + 10) {
              ev.clientX = minX + 10;
            }
            oDiv.style.width = oDiv.offsetWidth - (ev.clientX - oldX) + 'px';
            if (oDiv.offsetWidth <= chatMinWidth) {
              ev.clientX = e.clientX + chatWidth - chatMinWidth;
            }
            oDiv.style.left = oDiv.offsetLeft + (ev.clientX - oldX) + 'px';
          } else if (disX >= oDiv.offsetWidth - 10) {
            // 右
            // if (ev.clientX >= $(window).width()) {
            //   ev.clientX = $(window).width();
            // }
            if (ev.clientX >= maxX) {
              ev.clientX = maxX;
            }
            oDiv.style.width = oDiv.offsetWidth + (ev.clientX - oldX) + 'px';
            if (oDiv.offsetWidth <= chatMinWidth) {
              ev.clientX = e.clientX - chatWidth + chatMinWidth;
            }
            disX = ev.clientX - oDiv.offsetLeft;
          }

          if (disY <= 10) {
            // 上
            // if (ev.clientY <= 0) {
            //   ev.clientY = 0;
            // }
            if (ev.clientY <= minY) {
              ev.clientY = minY;
            }
            oDiv.style.height = oDiv.offsetHeight - (ev.clientY - oldY) + 'px';
            if (oDiv.offsetHeight <= chatMinHeight) {
              ev.clientY = e.clientY + chatHeight - chatMinHeight;
            }
            oDiv.style.top = oDiv.offsetTop + (ev.clientY - oldY) + 'px';
          } else if (disY >= oDiv.offsetHeight - 10) {
            // 下
            // if (ev.clientY >= $(window).height()) {
            //   ev.clientY = $(window).height();
            // }

            if (ev.clientY >= maxY) {
              ev.clientY = maxY;
            }
            oDiv.style.height = oDiv.offsetHeight + (ev.clientY - oldY) + 'px';
            if (oDiv.offsetHeight <= chatMinHeight) {
              ev.clientY = e.clientY - chatHeight + chatMinHeight;
            }
            disY = ev.clientY - oDiv.offsetTop;
          }
          oldX = ev.clientX;
          oldY = ev.clientY;
        },
      });
    },
  },
};
</script>
<style lang="scss">
// body {
//   background: #f9f9f9;
// }
.block {
  width: 100px;
  height: 70px;
  min-width: 30px;
  min-height: 30px;
  position: absolute;
  // left: 300px;
  // top: 400px;
  box-shadow: 0 6px 20px -6px rgba(0, 0, 0, 0.3);
  outline: rgba(255, 255, 255, 0.5) dashed 1px;
  z-index: 10000;
  background: none;

  padding: 2px;
  // background: #fff;
  // opacity: 0.3;
}

.drag-content {
  cursor: move;
  height: 98%;
  width: 98%;
}

.border {
  position: absolute;
  z-index: 9999;
  // background: rgba(70, 66, 68, 0.493);
  cursor: pointer;
  border: 1px dashed rgba(0, 0, 0, 0.5);
  // background-color: rgba(0, 0, 0, 0.5);
}
// .border:hover {
//   background: rgba(116, 114, 114, 0.5);
// }
#border-top,
#border-bottom {
  width: 100%;
  height: 0;
  cursor: ns-resize;
}
#border-right,
#border-left {
  width: 0;
  height: 100%;
  cursor: ew-resize;
}

#border-top,
#border-left-top {
  top: 0;
  left: 0;
}
#border-right,
#border-right-top {
  top: 0;
  right: 0;
}
#border-bottom,
#border-left-bottom {
  left: 0;
  bottom: 0;
}
#border-left {
  top: 0;
  left: 0;
}
#border-right-bottom {
  right: 0;
  bottom: 0;
}
#border-left-top,
#border-right-bottom {
  cursor: nwse-resize;
}
#border-right-top,
#border-left-bottom {
  cursor: nesw-resize;
}

.border-dot {
  width: 8px;
  height: 8px;
  background: none;
  // border: 1px solid rgba(70, 66, 68, 0.493);
  outline: rgba(0, 0, 0, 0.5) solid 1px;
  border: 1px solid rgba(255, 255, 255, 0.5);
}

#border-left-top {
  left: -3px;
  top: -3px;
}
#border-right-bottom {
  right: -3px;
  bottom: -3px;
}
#border-right-top {
  right: -3px;
  top: -3px;
}
#border-left-bottom {
  left: -3px;
  bottom: -3px;
}
</style>

使用

               <drag-drop
                  v-if="choosing"
                  ref="dragDom"
                  :vWidth="vWidth"
                  :vHeight="vHeight"
                ></drag-drop>

传参是背景框区域的宽高 选区时展示虚线矩形框

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值