使用resize属性实现元素拖拉改变宽度

1.背景

地图页面左侧全量树新需求,想要实现左侧树的拖拉效果,方便用户使用。

查阅资料发现使用js逻辑,通过监听鼠标按下、移动、抬起事件等进行处理可以实现,但是考虑到地图页面的性能已经吃不消了,于是不使用此方法实现。

之前看过相关css中的resize属性使用的文章,查看有关博客感觉可以实现元素的拖拉效果,于是使用resize属性进行功能实现。

2.小demo热身

参考了张鑫旭老师的纯CSS实现分栏宽度拉伸调整demo。

https://www.zhangxinxu.com/study/201903/css-idea/behavior-stretch.php?aside=0

自己动手试了一下,发现了一些小问题,示例如下。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    html, body {
      height: 100%;
    }
    .box {
      display: flex;
      overflow: hidden;
      height: 100%;
    }
    .left, .right {
      height: 100%;
      position: relative;
    }
    .left-reisze {
      width: 200px;
      height: inherit;
      resize: horizontal;
      overflow: scroll;
      cursor: col-resize;
      opacity: 0;
    }
    .resize-save {
      position: absolute;
      top: 0; right: 8px; bottom: 0; left: 0;
      padding: 16px;
      overflow-x: hidden;
    }
    .resize-line {
      position: absolute;
      width: 4px;
      right: 0; top: 0; bottom: 0;
      border-right: 2px solid #eee;
      border-left: 1px solid #bbb;
      pointer-events: none;
    }
    .left-reisze:hover ~ .resize-line,
    .left-reisze:active ~ .resize-line {
      border-left: 1px dashed skyblue;
    }
    .left-reisze::-webkit-scrollbar {
      width: 200px;
      height: inherit;
    }
  </style>
</head>
<body>
  <div class="box">
    <div class="left">
      <div class="left-reisze"></div>
      <div class="resize-line"></div>
      <div class="resize-save">Left</div>
    </div>
    <div class="right">Right</div>
  </div>
</body>
</html>

发现当父容器leftheight设置为100%时,webkit-scrollbar的高度设置为inherit时不生效,感觉高度变为0了。只有父容器left设置为固定高度时,webkit-scrollbar的高度设置为inherit时才能正常继承。

这里有个简单的解决方法,不考虑大屏展示时可以给webkit-scrollbar设置个固定高度2000px,考虑大屏展示再设置大一些。

还有个解决方法,要结合js使用,强行塞个高度。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    html, body {
      height: 100%;
    }
    .box {
      display: flex;
      overflow: hidden;
      height: 100%;
    }
    .left, .right {
      height: 100%;
      position: relative;
    }
    .left-reisze {
      width: 200px;
      // max-width: 750px; 这里可以设置最大、最小拖拉宽度
      height: inherit;
      resize: horizontal;
      overflow: scroll;
      cursor: col-resize;
      opacity: 0;
    }
    .resize-save {
      position: absolute;
      top: 0; right: 4px; bottom: 0; left: 0;
      padding: 16px;
      overflow-x: hidden;
    }
    .resize-line {
      position: absolute;
      width: 4px;
      right: 0; top: 0; bottom: 0;
      border-right: 2px solid #eee;
      border-left: 1px solid #bbb;
      pointer-events: none;
    }
    .left-reisze:hover ~ .resize-line,
    .left-reisze:active ~ .resize-line {
      border-left: 1px dashed skyblue;
    }
    .left-reisze::-webkit-scrollbar {
      width: 200px;
      height: inherit;
    }
  </style>
</head>
<body>
  <div class="box">
    <div class="left">
      <div class="left-reisze"></div>
      <div class="resize-line"></div>
      <div class="resize-save">Left</div>
    </div>
    <div class="right">Right</div>
  </div>
  <script>
    const node = document.querySelector('.left')
    node.setAttribute('style',`height:${node.clientHeight}px`)
  </script>
</body>
</html>

3.项目上使用

项目上使用的布局与上面的demo类似,只是在使用js处理webkit-scrollbar的高度时监听了浏览器的reisze事件。

mounted() {
  this.updateHeight();
  window.onresize = () => {
    this.$nextTick(() => {
      this.updateHeight();
    });
  };
},
 
updateHeight() {
  const node = document.querySelector('.rel-tree');
  node.setAttribute('style', '');
  this.$nextTick(() => {
    node.setAttribute('style', `height:${node.clientHeight}px`);
  });
},

4.注意点

1.resize-save盒子中内容超出left盒子宽度时,会被遮盖(更新:这里傻了,因为设置了 overflow-x:hidden;)

.test {
      width: 400px;
      height: 400px;
      background-color: pink;
}

<div class="box">
  <div class="left">
    <div class="left-reisze"></div>
    <div class="resize-line"></div>
    <div class="resize-save">
      Left
      <div class="test"></div>
    </div>
  </div>
  <div class="right">Right</div>
</div>

2.绝对定位问题

resize-save绝对定位盒子中的元素,使用绝对定位时,当超出left盒子显示区域时发现会被遮挡不可见,怎么改变z-index都无法全部显示,类似上面的第一种情况,有点不知道原因,这里的解决方式是改用了fixed固定定位。
(更新:这里也是因为设置了 overflow-x:hidden 导致的)

3.滚动条无限滚动问题

就是横向滚动条进行滚动时,滚的没完没了了,分明内容滚到底了,但是还能横向滚动,此时页面上展示的全是空白内容。

这是一个无法理解的问题,使用中没碰到正好,碰到时可以使用一个骚操作解决。我的理解是resize-save盒子的right为4px,给有滚动条的元素设置宽度是不直接设置100%,而是设置为width:calc(100% + 4px);,让此滚动元素与left盒子宽度相同或者大于left盒子宽度,就解决了,不知道问题的所在。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue 3中实现拖动改变元素宽度实现宽度自适应的方法如下: 1. 首先,创建一个可拖动的元素,可以使用HTML的`<div>`标签,并给它一个固定的宽度。 2. 在Vue组件中,使用`@mousedown`事件监听鼠标按下的动作,并绑定一个方法来处理拖动事件。 3. 在这个方法中,使用`@mousemove`和`@mouseup`事件来监听鼠标移动和释放的动作,并绑定对应的方法来处理。 4. 在鼠标按下时,记录下鼠标的初始位置和元素的初始宽度。 5. 在鼠标移动时,计算鼠标移动的距离,并根据这个距离计算出新的元素宽度。 6. 更新元素宽度,可以使用Vue的响应式数据或者直接操作DOM元素。 下面是一个示例代码: ```html <template> <div class="draggable" :style="{ width: width + 'px' }" @mousedown="startDragging"> <!-- 内容 --> </div> </template> <script> export default { data() { return { startX: 0, startWidth: 0, width: 200, // 初始宽度 }; }, methods: { startDragging(event) { this.startX = event.clientX; this.startWidth = this.width; document.addEventListener('mousemove', this.drag); document.addEventListener('mouseup', this.stopDragging); }, drag(event) { const dx = event.clientX - this.startX; this.width = this.startWidth + dx; }, stopDragging() { document.removeEventListener('mousemove', this.drag); document.removeEventListener('mouseup', this.stopDragging); }, }, }; </script> <style scoped> .draggable { border: 1px solid #ccc; cursor: col-resize; } </style> ``` 这样,当你拖动可拖动元素时,它的宽度会随着鼠标的移动而改变,并实现宽度自适应效果。注意,在实际项目中,你可能需要根据需求对代码进行适当的修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值