js 实现对一个元素得拉伸

54 篇文章 3 订阅
29 篇文章 1 订阅

前言:

最近写一个项目遇到了需要拉伸调整一个元素得大小(宽高)。所以打算实现一下。

思路就是用 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

这个库提供了拖动和调整大小的能力,可以用于在元素上实现拉伸和调整大小的效果。

总结:

这种功能建议使用 成熟的库来实现,兼容性什么的一般都会适配。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

崽崽的谷雨

漫漫前端路,摸爬滚打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值