前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端实现伸缩框

前端实现伸缩框

作者头像
Jimmy_is_jimmy
发布2024-01-08 09:36:35
1590
发布2024-01-08 09:36:35
举报
文章被收录于专栏:call_me_Rcall_me_R

本文,我们讲讲前端怎么实现伸缩框的功能,类似下面👇

案例验证的浏览器为 - Google Chrome 版本 119.0.6045.123(正式版本)(arm64)

前言

在实际的工作中,我们有遇到这么一个实用的需求:

允许用户对内容框进行伸缩

咦,这不是很简单的事情?

So EASY~

我们使用 resize 这个 css 样式不就得了。

CSS 中使用 resize

是的,我们可以通过 resize 这个属性来实现伸缩框的功能。比如这样👇我们设定 resize: both;

代码语言:javascript
复制
<div class="resize-both">
  resize both
</div>
代码语言:javascript
复制
:root {
  --primary-color: #3498db;
}
.resize-both {
  width: 100px;
  height: 100px;
  border: 1px solid var(--primary-color);
  /* resize */
  resize: both;
  overflow: hidden;
}

resize 需要配合 overflow 属性来使用,属性值为 visible 不生效

实现的效果如下:

当然,我们这里只是以 resize: both; 为案例,我们可以设定其横向或者竖向的伸缩 - mdn web docs - resize

嗯,resize 确实实现了我们的伸缩框功能。但是,我们是否可以改变下右下角的 icon 图表呢?是否可以更改图标所在的位置呢?这对我们很不友好 -> Is there a way to change the CSS resize corner's position?

So,目前来看,我们只能接受使用 resize 的默认。

那么,我们能否自己来编写伸缩款呢?

能的,我们用 javascript 来实现个 resize bothgif 图的功能。

JS 实现伸缩框

我们的思路是这样子的:

  • 实现右下角的三角拖动图标
  • 计算伸缩框距离左边和顶部的距离
  • 监听鼠标的点击、拖动、抬起事件,记录鼠标当前相对视窗左上角点的左侧距离和顶部距离
  • 计算鼠标距离边框左侧的距离,即边框的新宽度
  • 计算鼠标距离边框顶部的距离,即边框的新高度
  • 限定边框的最小距离,防止 icon 拖动隐藏

我们需要跟浏览器的事件打交道,这里引入 RxJS ,(当然,读者可以手写原生 javascript)。

RxJS 是一个用于处理异步事件流的库。

在开始之前,我们还得熟悉下juejin.cn/post/708512…中的 Element.getBoundingClientRect() 方法:

我们可以通过这个方法获取元素其左上角顶点相对可视窗口的坐标(x, y)及其元素的宽度和高度。

当然,我们还需要通过 event.clienXevent.clientY 获取当前鼠标距离可视窗口的坐标(clientX, clientY)

Ok,万事俱备,我们来实现下:

代码语言:javascript
复制
<div class="rxjs-both" id="rxjs-both">
  rxjs both
  <div class="icon-resize" id="icon-resize"></div>
</div>

类名为 icon-resize 的元素是用来实现右下角的三角图标的,这里我们结合 css 中的伪元素来实现:

代码语言:javascript
复制
:root {
  --primary-color: #3498db;
  --icon-color: #666;
}
.rxjs-both {
  width: 100px;
  height: 100px;
  border: 1px solid var(--primary-color);
  margin-left: 400px;
  position: relative;
  overflow: hidden;
}
.icon-resize {
  width: 10px;
  height: 10px;
  position: absolute;
  bottom: 0;
  right: 0;
  /* 更改了 cusor 图标 */
  cursor: nwse-resize;
}
.icon-resize::before {
  content: "";
  display: block;
  width: 10px;
  height: 1px;
  background-color: var(--icon-color);
  position: absolute;
  top: 50%;
  transform: translateY(-50%) rotate(135deg);
}
.icon-resize::after {
  content: "";
  display: block;
  width: 5px;
  height: 1px;
  background-color: var(--icon-color);
  position: absolute;
  top: 75%;
  left: 75%;
  transform: translate(-50%, -50%) rotate(135deg);
}

页面的效果如下:

接着,我们添加 javascript 让页面动起来:

代码语言:javascript
复制
const { fromEvent } = rxjs;
const { mergeMap, takeUntil } = rxjs.operators;

const resizableDiv = document.getElementById('rxjs-both');

function handleMouseMove(event) {
  let boundingEl = resizableDiv.getBoundingClientRect();
  let _width = event.clientX - boundingEl.left; // 获取拖动后的宽度
  let _height = event.clientY - boundingEl.top; // 获取拖动后的高度
  resizableDiv.style.width = (_width >= 20 ? _width : 20) + 'px';
  resizableDiv.style.height = (_height >= 20 ? _height : 20) + 'px';
}

const mouseMove$ = fromEvent(document, 'mousemove'); // fromEvent 创建可观察对象 Observable
const mouseUp$ = fromEvent(document, 'mouseup');

const drag$ = fromEvent(document.getElementById('icon-resize'), 'mousedown').pipe(
  mergeMap(() => mouseMove$.pipe(takeUntil(mouseUp$))) // 鼠标抬起结束监听
);

drag$.subscribe(handleMouseMove); // 观察者 -> 鼠标拖动的过程中监听

这里我们引入的 rxjs7.8.1 版本,读者可以直接使用 cdn -> https://cdn.bootcdn.net/ajax/libs/rxjs/7.8.1/rxjs.umd.js。当鼠标按下拖动的时候,触发对伸缩框的宽度和高度的重新计算并赋值。当鼠标抬起后,结束监听。

实现的效果可以说和 CSS 实现的 resize: both 的大同小异,优雅且丝滑~ 如下:

是的,这里我们实现了拉取右下角的图标实现对伸缩框的高度和宽度做了更改。其实,是否更改宽度或者高度,是否更改图标的位置,或者是否通过拉取边框进行伸缩?原理都一样,读者感兴趣的话,可以自行实现~

总结

我们实验了两种的伸缩方法:

  • CSSresize 结合 overflow 来实现,虽然能够完成任务,但是太固化,适合不讲究页面布局的时候实现
  • JS 方式实现,引入了 RxJS 优雅实现,可对 UI 高度定制化
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-01-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • CSS 中使用 resize
  • JS 实现伸缩框
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档