前端区域块拖拽的纯css3、纯js、splitpanes插件的方法

一、纯css3

resize属性的具体用法可见MDN: https://developer.mozilla.org/zh-CN/docs/Web/CSS/resize

效果链接: http://js.jirengu.com/voleracixe/2/edit

利用浏览器非overflow:auto元素设置resize可以拉伸的特性实现无JavaScript的分栏宽度控制。

原理

CSS中有一个resize属性,如果一个元素的overflow属性值不是visible,则通过设置resize属性可以拉伸这个元素尺寸。

如何把拖拽区域变大呢?

后来研究发现,resize属性的拖拽bar和滚动条的拖拽bar是一个体系里面的东西,只需要对滚动条进行自定义,就能间接设置resize bar的尺寸。

.resize-bar::-webkit-scrollbar {
    
    
    width: 200px; height: 200px;
}

一个完整的例子

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>AA-drag</title>
    <style>
      * {
    
    
        padding: 0;
        margin: 0;
      }
      .fl-container {
    
    
        width: 100%;
        height: 100vh;
        overflow: hidden;
      }
      .fl-resize-bar,
      .fl-resize-bar::-webkit-scrollbar {
    
    
        width: 400px;
      }
      .fl-left {
    
    
        position: relative;
        float: left;
        height: 100vh;
        background: pink;
      }
      .fl-right {
    
    
        box-sizing: border-box;
        overflow-x: hidden;
        height: 100vh;
      }
      .fl-cont-right {
    
    
        height: 200vh;
      }
      .fl-resize-bar {
    
    
        height: inherit;
        resize: horizontal;
        cursor: ew-resize;
        cursor: col-resize;
        opacity: 0;
        overflow: scroll;
      }
      .fl-resize-bar::-webkit-scrollbar {
    
    
        width: 400px;
        height: inherit;
      }

      .fl-cont-left {
    
    
        position: absolute;
        top: 0;
        right: 4px; /* 拖拽线的间距 */
        bottom: 0;
        left: 0;
        overflow-x: hidden;
        background: #fff;
      }

      .fl-resize-line {
    
    
        position: absolute;
        right: 1px;
        top: 0;
        bottom: 0;
        border-right: 2px solid #bbb;
        pointer-events: none;
      }
      .fl-resize-bar:hover ~ .fl-resize-line,
      .fl-resize-bar:active ~ .fl-resize-line {
    
    
        border-right: 2px dashed skyblue;
      }

      /* Firefox只有下面一小块区域可以拉伸 */
      @supports (-moz-user-select: none) {
    
    
        .fl-resize-bar:hover ~ .fl-resize-line,
        .fl-resize-bar:active ~ .fl-resize-line {
    
    
          border-right: 2px solid #bbb;
        }
        .fl-resize-bar:hover ~ .fl-resize-line::after,
        .fl-resize-bar:active ~ .fl-resize-line::after {
    
    
          content: '';
          position: absolute;
          width: 16px;
          height: 16px;
          bottom: 0;
          right: -8px;
          background: url(https://www.zhangxinxu.com/study/201903/css-idea/resize.svg);
          background-size: 100% 100%;
          z-index: 1;
        }
      }
    </style>
  </head>
  <body>
    <div class="fl-container">
      <div class="fl-left">
        <div class="fl-resize-bar"></div>
        <div class="fl-resize-line"></div>
        <div class="fl-cont-left">左侧内容</div>
      </div>
      <div class="fl-right">
        <div class="fl-cont-right">
          右侧内容
        </div>
      </div>
    </div>
  </body>
</html>

二、纯js

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>AA-drag</title>
    <style>
      * {
    
    
        padding: 0;
        margin: 0;
      }
      #left,
      #right,
      #middle {
    
    
        height: 100vh;
        position: absolute;
      }
      #left {
    
    
        width: 300px;
        background: #ccc;
      }
      #middle {
    
    
        width: 5px;
        background: #666;
        left: 300px;
      }
      #middle:hover {
    
    
        cursor: col-resize;
      }
      #right {
    
    
        right: 0;
        background: #ccc;
        left: 305px;
        width: auto;
      }
    </style>
  </head>
  <body>
    <div id="left">左侧内容</div>
    <div id="middle"></div>
    <div id="right">右侧内容</div>
  </body>
</html>
<script>
  function getEle(id) {
    
    
    return document.getElementById(id)
}
  window.onload = function () {
    
    
    const left = getEle('left')
  const right = getEle('right')
  const middle = getEle('middle')

  const middleWidth = 5
  middle.onmousedown = function (e) {
    
    
      const disX = (e || event).clientX
      middle.left = middle.offsetLeft
      document.onmousemove = function (e) {
    
    
        let middleLeft = middle.left + ((e || event).clientX - disX)
        const maxWidth = document.body.clientWidth
        middleLeft < 0 && (middleLeft = 0)
        middleLeft > maxWidth && (middleLeft = maxWidth)
        middle.style.left = left.style.width = `${
      
      middleLeft}px`
        right.style.width = `${
      
      maxWidth - middleLeft - middleWidth}px`
        right.style.left = `${
      
      middleLeft + middleWidth}px`
        return false
      }
      document.onmouseup = function () {
    
    
        document.onmousemove = null
        document.onmouseup = null
        middle.releaseCapture && middle.releaseCapture()
      }
      middle.setCapture && middle.setCapture()
      return false
  }
}
</script>

2.1、onmousedown 、 onmousemove 、onmouseup 鼠标按下 / 移动 / 释放

1、onmousedown——选择元素

扫描二维码关注公众号,回复: 16860119 查看本文章
oDiv.onmousedown = function(ev) {
    
    }

2、onmousemove —— 移动元素
触发频率:不是像素,而是间隔时间,在一个指定时间内(很短),如果鼠标的位置和上一次的位置发生了变化,那么就会触发一次

var i = 0;
document.onmousemove = function() {
    
    
    document.title = i++;  //鼠标移动,页面的标题发生变化,移动的越慢数字越大
}

3、onmouseup —— 释放元素

document.onmouseup = function() {
    
    }

4、三者结构关系

oDiv.onmousedown = function() {
    
    
    document.onmousemove = function() {
    
    } 
    //拖动的太快了超出元素的本身的位置会停在半路,所以元素改为文档
    document.onmouseup = function() {
    
    }  
    //如果有别的元素在拖动元素停止的位置之上,松开鼠标则还可以继续拖动,因为不是在拖动元素上松开的,所以元素应改为文档      
}

2.2、注意

1、拖拽的时候,如果有文字被选中,会产生问题

原因:当鼠标按下的时候,如果页面中有文字被选中,那么会触发浏览器默认拖拽文字的效果

解决办法:

(1)标准浏览器:阻止默认行为

return false;

(2)IE678:没法阻止,所以需要设置全局捕获——.setCapture()

if ( obj.setCapture ) {
    
    
       obj.setCapture();
}  

2.3 切换浏览器窗口大小,重新计算大小

onMounted(() => {
    
    
  window.addEventListener('resize', () => {
    
    
    resizeInit()
  })
})
function resizeInit() {
    
    
    const left = getEle('left')
    const right = getEle('right')
    const middle = getEle('middle')
    left.style.width = '300px'
    middle.style.left = '310px'
    const maxWidth = (document.body.clientWidth - 50) * 2/3
    right.style.width = `${
      
      maxWidth - 311 - 20}px`
    right.style.left = '311px'
}

三、splitpanes插件(垂直水平分割窗口)

官网:https://antoniandre.github.io/splitpanes/
在vue3项目中的使用

安装

​​​​​​​pnpm i splitpanes@next

在页面的使用

import {
    
     Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'

html中

min-size=“0” max-size="35"设置左边窗口可调节的最大百分比和最小百分比

<splitpanes class="default-theme" @resize="paneSize = $event[0].size" style="height: 400px">
  <pane :size="paneSize" min-size="0" max-size="35">
    <span>{
    
    {
    
     paneSize }}%</span>
  </pane>
  <pane :size="100 - paneSize">
    <span>{
    
    {
    
     100 - paneSize }}%</span>
  </pane>
</splitpanes>

猜你喜欢

转载自blog.csdn.net/wang13679201813/article/details/130290260
今日推荐