【已解决】JS/Vue实现拖拽调整窗体大小(右侧、底部、右下角)

实现效果

在这里插入图片描述

解决方案

方案中使用的是 vue指令 来实现的,如果是 js 的话,可以更换成 js dom 事件绑定来实现。

directive.js 文件,要在 main.js 引入该文件

import Vue from 'vue'

Vue.directive('dialogDragWidth', {
  inserted(el, binding) {
	// 由于使用 binding 获取不到 dom 元素,所以我就改用了 固定布局的方式来获取窗体元素。
    const dragDom = el.parentNode.parentNode // 窗体中间嵌套了一层:dialog -> div -> dragDom
    // 由于使用的是一个指令绑定到了三个 dragdom 上面,所以做了参数判断。
    // corner: 右下角;right: 右侧;bottom:底部;
    // 参数可根据自身编码习惯修改
    const value = binding.value || 'corner'
    if (!dragDom) return // 错误处理
    el.onmousedown = (e) => {
      // 鼠标按下,在原来页面上增加透明遮罩,防止部分元素例如iframe监听不到鼠标事件
      const mask = document.createElement('div')
      mask.setAttribute('style', 'position:fixed;top:0px;bottom:0px;left:0px;right:0px;background:rgba(0,0,0,0)')
      document.body.appendChild(mask)
      // 计算当前元素距离可视区的距离
      const disX = e.clientX - el.offsetLeft
      const disY = e.clientY - el.offsetTop

      document.body.onmousemove = function (e) {
        e.preventDefault() // 移动时禁用默认事件

        // 通过事件委托,计算移动的距离
        const l = e.clientX - disX
        const h = e.clientY - disY
        
        // 一个方法实现三种方式,所以根据参数来判断 size 方向
        if (value === 'right' || value === 'corner') {
          dragDom.style.width = `${l}px`
        }
        // 判断弹窗高度,防止用于拖动的点移出可视区
        if (value === 'bottom' || value === 'corner') {
          dragDom.style.height = `${h > document.body.offsetHeight ? document.body.offsetHeight : h}px`
        }
      }

      document.body.onmouseup = function (e) {
        document.body.removeChild(mask) // 移除mask遮罩
        document.body.onmousemove = null
        document.body.onmouseup = null
      }
    }
  }
})

dragSize.vue

<template>
  <div class="sd-drag-size-box">
  	<!-- 指令的参数是字符串,一定不要少了 外面的 单引号 '' -->
    <div v-dialogDragWidth="'right'" class="sd-drag-item sd-drag-item-right"></div>
    <div v-dialogDragWidth="'corner'" class="sd-drag-item sd-drag-item-corner"></div>
    <div v-dialogDragWidth="'bottom'" class="sd-drag-item sd-drag-item-bottom"></div>
  </div>
</template>

<style lang="scss" scoped>
.sd-drag-size-box {
  .sd-drag-item {
    position: absolute;
    z-index: 2;
    &-right {
      height: 98%;
      width: 2px;
      right: -1px;
      top: 0;
      cursor: col-resize;
      background: red;
    }
    &-corner {
      width: 5px;
      height: 5px;
      position: absolute;
      right: -2px;
      bottom: -2px;
      cursor: se-resize;
      background: black;
    }
    &-bottom {
      height: 2px;
      width: 98%;
      left: 0;
      bottom: -1px;
      cursor: row-resize;
      background: #096;
    }
  }
}
</style>

使用方式
index.vue

<template>
	<div class="box">
		<!-- 放在窗体子级 -->
		<DragSize />
	</div>
</template>

<style>
import DragSize from './dragSize.vue'

export default {
	name: 'Demo',
	components: { DragSize }
}
</style>

<style lang="scss" scoped>
.box {
  position: absolute;
  left: 20px;
  top: 50px;
  // 我是拖动的右侧,和底部,所以 根据处理逻辑,不能向这两个方向设置 定位
  right: unset;
  bottom: unset;
  border-radius: 8px;
  width: 452px;
  height: 650px;
}
</style>
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值