前言:
最近写一个项目遇到了需要拉伸调整一个元素得大小(宽高)。所以打算实现一下。
思路就是用 mousedown、mousemove、mouseup 来实现。
 mousemove是动态获取坐标,然后 动态改变元素宽度
js自己实现:
html里实现:
<!DOCTYPE html>
<html>
<head>
  <style>
    .container {
      width: 400px;
      height: 300px;
      border: 1px solid #000;
      position: relative;
    }
    .box {
      width: 300px;
      height: 200px;
      border: 1px solid #000;
      resize: horizontal;
      overflow: auto;
      position: relative;
    }
    .button {
      width: 8px;
      height: 8px;
      background-color: #f00;
      cursor: pointer;
      position: absolute;
    }
    .right-button {
      right: -4px;
      top: 50%;
      transform: translateY(-50%);
    }
    .bottom-button {
      bottom: -4px;
      left: 50%;
      transform: translateX(-50%);
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="box">
      Content
      <div class="button right-button"></div>
    </div>
    <div class="button bottom-button"></div>
  </div>
  <script>
    const box = document.querySelector('.box');
    const rightButton = document.querySelector('.right-button');
    const bottomButton = document.querySelector('.bottom-button');
    let startX = 0;
    let startY = 0;
    let initialWidth = 0;
    let initialHeight = 0;
    function startResize(event) {
        event.preventDefault();
        startX = event.clientX;
        startY = event.clientY;
        initialWidth = parseInt(document.defaultView.getComputedStyle(box).width, 10);
        initialHeight = parseInt(document.defaultView.getComputedStyle(box).height, 10);
        document.documentElement.addEventListener('mousemove', resize);
        document.documentElement.addEventListener('mouseup', stopResize);
    }
    function resize(event) {
      const deltaX = event.clientX - startX;
      const deltaY = event.clientY - startY;
      const newWidth = initialWidth + deltaX;
      const newHeight = initialHeight + deltaY;
      box.style.width = `${newWidth}px`;
      box.style.height = `${newHeight}px`;
    }
    function stopResize() {
      document.documentElement.removeEventListener('mousemove', resize);
      document.documentElement.removeEventListener('mouseup', stopResize);
    }
    rightButton.addEventListener('mousedown', startResize);
    bottomButton.addEventListener('mousedown', startResize);
  </script>
</body>
</html>

react里封装一个组件
hook 语法组件:
import React, { ReactNode, useState, useEffect } from 'react';
import styles from "./index.less";
interface ResizableBoxProps {
    /**
     * 盒子的宽度 默认100
     */
    widthNum?: number;
    /**
    * 盒子的高度 默认50
    */
    heightNum?: number;
    /**
     * 内容
     */
    content?: string | ReactNode;
}
const ResizableBox: React.FC<ResizableBoxProps> = ({
    widthNum,
    heightNum,
    content,
    children,
    ...props
}) => {
    // 根据优先级选择要渲染的标题
    const contentRender = content || children;
    // 定义状态变量,使用useState
    const [width, setWidth] = useState(widthNum || 100); // 宽度
    const [height, setHeight] = useState(heightNum || 50); // 高度
    const [startX, setStartX] = useState(0); // 鼠标点击时的起始X坐标
    const [startY, setStartY] = useState(0); // 鼠标点击时的起始Y坐标
    const [initialWidth, setInitialWidth] = useState(0); // 调整大小前的初始宽度
    const [initialHeight, setInitialHeight] = useState(0); // 调整大小前的初始高度
    const [isResizing, setIsResizing] = useState(false); // 是否正在调整大小
    /**开始调整大小时的事件处理函数 高度*/
    const startResizeY = (event: any) => {
        event.preventDefault();
        const { clientX, clientY } = event;
        setStartY(clientY);
        setInitialHeight(height);
        setIsResizing(true);
        document.documentElement.addEventListener('mousemove', resizeY);
        document.documentElement.addEventListener('mouseup', stopResize);
    };
    /**开始调整大小时的事件处理函数 宽度*/
    const startResizeX = (event: any) => {
        event.preventDefault();
        const { clientX, clientY } = event;
        setStartX(clientX);
        setInitialWidth(width);
        setIsResizing(true);
        document.documentElement.addEventListener('mousemove', resizeX);
        document.documentElement.addEventListener('mouseup', stopResize);
    };
    /** 宽度调整大小 */
    const resizeX = (event: any) => {
        const { clientX } = event;
        const deltaX = clientX - startX;
        const newWidth = initialWidth + deltaX;
        setWidth(newWidth);
    };
    /**高度调整大小 */
    const resizeY = (event: any) => {
        const { clientY } = event;
        const deltaY = clientY - startY;
        const newHeight = initialHeight + deltaY;
        setHeight(newHeight);
    };
    // 停止调整大小时的事件处理函数
    const stopResize = () => {
        setIsResizing(false);
        document.documentElement.removeEventListener('mousemove', resizeX);
        document.documentElement.removeEventListener('mousemove', resizeY);
        document.documentElement.removeEventListener('mouseup', stopResize);
    };
    // useEffect用于设置鼠标样式
    useEffect(() => {
        if (isResizing) {
            // document.documentElement.style.cursor = 'nwse-resize';
        } else {
            document.documentElement.style.cursor = 'default';
        }
    }, [isResizing]);
    // 返回可调整大小的组件
    return (
        <div
            className={styles.resizable_box}
            style={{ width: `${width}px`, height: `${height}px` }} // 使用状态变量控制宽度和高度
        >
            <div className={styles.container}>
                {contentRender}
            </div>
            <div className={`${styles.button} ${styles.right_button}`} onMouseDown={startResizeX}></div>
            <div className={`${styles.button} ${styles.bottom_button}`} onMouseDown={startResizeY}></div>
        </div>
    );
};
export default ResizableBox;
样式less:
.resizable_box {
    position: relative;
}
.container {
    width: 100%;
    height: 100%;
}
// .button {
//     width: 8px;
//     height: 8px;
//     background-color: #f00;
//     /* cursor: pointer; */
//     position: absolute;
// }
.button {
    // width: 2px;
    // height: 100%;
    background: none;
    position: absolute;
}
.right_button {
    width: 2px;
    height: 100%;
    right: -2px;
    top: 0;
    // top: 50%;
    // transform: translateY(-50%);
    cursor: e-resize;
}
.bottom_button {
    width: 100%;
    height: 2px;
    bottom: -2px;
    // left: 50%;
    // transform: translateX(-50%);
    cursor: n-resize;
}
使用 方式:
//换成自己的
import ResizableBox from "xxx/components/ResizableBox";
<ResizableBox widthNum={220} heightNum={300}>
  <div style={{width:"100%",background:"red",height:"100%"}}>
          ttt
   </div>
 </ResizableBox>
使用插件:
js:
Interact.js
一个现代、强大的拖放、调整大小和手势识别的JavaScript库。
 提供了许多可定制的选项和事件回调。
 https://interactjs.io/ 官网
jQuery UI
jQuery的UI组件库,包括可拖拽(Draggable)和可调整大小(Resizable)的组件。
 提供了丰富的配置选项和事件处理。
 示例:使用jQuery UI的Resizable
react:
react-resizable
特点:专为React设计的,允许你轻松地为React组件添加拖拽调整大小的功能。
 安装:通过npm或yarn安装,如npm install react-resizable。
 使用:
 引入Resizable组件。
 在你的React组件中包裹需要拉伸的元素。
 通过props配置拉伸的初始大小、最小和最大尺寸等。
re-resizable(注意:这可能与react-resizable不同,但同样适用于React)
特点:类似于react-resizable,但可能提供了一些额外的功能或定制选项。
 安装:通过npm或yarn安装,如npm install --save re-resizable。
 使用:
 引入Resizable组件。
 在你的React组件中使用Resizable来包裹需要拉伸的元素。
 可以通过props配置拉伸的默认大小、最小和最大尺寸、拉伸手柄的样式等。
react-rnd
特点:除了提供拉伸功能外,还允许你通过拖拽来移动元素。
 安装:通过npm或yarn安装,如npm install react-rnd。
 使用:
 引入Rnd组件。
 在你的React组件中使用Rnd来包裹需要拉伸和移动的元素。
 可以通过props配置元素的初始位置、大小、移动和拉伸的限制等。
 示例:参考文章3提供了一个使用react-rnd实现元素拖动和缩放的实例。
vue:
Vue-Resizable
这个库提供了一个可调整大小的组件,可以用于实现元素的拉伸和调整大小功能。
Vue-Draggable-Resizable
这个库结合了拖动和调整大小的功能,可以让你通过拖动和拉伸来改变元素的尺寸。
Vue-Resize-Handle
这个库提供了一个可自定义样式的调整大小的手柄,可以用于在元素上添加拉伸功能。
Vue-Drag-Resize
这个库提供了拖动和调整大小的能力,可以用于在元素上实现拉伸和调整大小的效果。
总结:
这种功能建议使用 成熟的库来实现,兼容性什么的一般都会适配。



















