自定义弹窗

项目场景:

提示:自用方法,有改进的地方请指正

可以拖拽,改变大小,不超出父div


解决方案:

<template>
  <div class="window" :style="`top:${top};left:${left};right:${right};`">
    <div class="titlebar">
      <slot name="header">
      </slot>
    </div>
    <div style="height: fit-content;width: 100%;  background: rgba(71,71,71,.8);">
      <slot name="header2">
      </slot>
    </div>
    <div class="content" ref="boxContent">
      <slot name="body">
      </slot>
      <div style="width: 100%;height: 30px;"></div>
    </div>
    <div class="foot">
      <slot name="foot">
      </slot>
    </div>
  </div>
</template>

<script setup>
import {onMounted, ref, toRefs, defineProps} from "vue";
import { useElementSize } from '@vueuse/core'
const props = defineProps({
  //子组件接收父组件传递过来的值
  top: String,
  left: String,
  right: String,
})
const { top } = toRefs(props)
const { left } = toRefs(props)
const { right } = toRefs(props)

const boxContent = ref()
const { width, height } = useElementSize(boxContent)
const contentShowType = ref('visible')


onMounted(() => {
  const windows = document.querySelectorAll('.window');
  [].forEach.call(windows,function(win){
    // …find the title bar inside it and do something onmousedown
    var title = win.querySelector('.titlebar');
    title.addEventListener('mousedown',function(evt){

      let rangWidth = win.parentNode.clientWidth; //父元素宽度,即 移动范围
      let rangHeight = win.parentNode.clientHeight; //父元素高度

      // boxContent.value.style.maxHeight = (rangHeight - 120) + 'px'
      // boxContent.value.style.maxWidth = rangWidth + 'px'


      const real = window.getComputedStyle(win),
          winX = parseFloat(real.left), // 距父元素距离
          winY = parseFloat(real.top);
      // Record where the mouse started

      const mX = evt.clientX,
          mY = evt.clientY;
      // console.log(evt)

      // When moving anywhere on the page, drag the window
      // …until the mouse button comes up
      document.body.addEventListener('mousemove',drag,false);
      document.body.addEventListener('mouseup',function(){
        document.body.removeEventListener('mousemove',drag,false);
      },false);

      let disX = evt.clientX - winX // 鼠标距边
      let disY = evt.clientY - winY
      const dWdith = win.clientWidth // 组件尺寸
      const dHeight = win.clientHeight

      const dMoveLeft = rangWidth - dWdith // 最大移动距离
      const dMoveTop = rangHeight - dHeight

      function drag(e){

        //通过事件委托,计算移动的距离
        let left = e.clientX - disX;
        let top = e.clientY - disY;
        //移动当前元素
        //如果元素的移动位置大于窗口位置,则不再移动
        if(left > dMoveLeft){
          win.style.left = `${dMoveLeft}px`;
        }else{
          win.style.left = `${left}px`;
        }
        if(left <0){
          win.style.left = `0px`;
        }
        if(top > dMoveTop){
          win.style.top = `${dMoveTop}px`;
        }else{
          win.style.top = `${top}px`;
        }
        if(top < 0){
          win.style.top = `0px`;
        }
      }
    },false);
  });
})
</script>

<style scoped>
.window {
  position:absolute;
  width:fit-content;
  height:fit-content;
  background:#fff00000;
  user-select:none;
  -webkit-user-select:none;
  -moz-user-select:none;
  z-index: 1;
}
.window .titlebar {
  width: 100%;
  height: 36px;
  line-height: 36px;
  color: white;
  background: rgba(71,71,71,.8);
  border-bottom: 4px solid rgba(0,0,0,.4);
  text-align:center;
  cursor:move;
  display: flex;
}
.window .content {
  resize: both;
  width: 500px;
  height: fit-content;
  min-width: 300px;
  max-height: 60vh;
  max-width: 80vw;

  overflow: auto;
  outline: none;
  white-space: pre;
  overflow-wrap: normal;
  position: relative;
  background: rgba(71,71,71,.8);
  border: 1px solid rgba(91, 123, 235, 0.3);
}
.window .foot {
  text-align: right;
  padding-right: 20px;
  margin-top: -36px;
  height: 36px;
  width: 100%;
}


</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值