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

实现效果

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

解决方案

方案中使用的是 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>

你可能感兴趣的:(javascript,vue.js,前端)