js 实现对一个元素得拉伸

news2024/11/28 6:26:14

前言:

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

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

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

总结:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2062589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CentOS7发送邮件如何配置SMTP服务器发信?

CentOS7发送邮件安全设置&#xff1f;CentOS7发信性能优化方法&#xff1f; 对于使用CentOS7操作系统的用户而言&#xff0c;配置SMTP服务器以发送邮件是一个关键步骤。AokSend将详细介绍如何在CentOS7中配置SMTP服务器发信的方法和注意事项。 CentOS7发送邮件&#xff1a;准…

C#发邮件时如何确保邮件内容的安全和隐私?

C#发邮件性能优化的策略&#xff1f;如何设置C#发邮件的功能&#xff1f; 在使用C#发邮件时&#xff0c;如何确保邮件内容不被泄露、篡改或非法访问&#xff0c;已成为开发者需要面对的关键问题。AokSend将探讨在C#发邮件过程中&#xff0c;确保邮件内容安全和隐私的几种有效方…

你也想转行成为一名程序员吗?作为过来人的我希望你想清楚这几个问题再做决定

1 有个朋友突然找我&#xff1a;“现在的工作不想干了&#xff0c;我现在转行搞IT能不能行&#xff1f;学哪个编程语言比较有前景&#xff1f;现在去搞网络安全应该没问题吧&#xff1f;”我相信&#xff0c;很多人出于各种原因都在考虑要不要进行职业转换&#xff0c;迷茫又焦…

2024年最新Pycharm专业版激活码+Pycharm详细安装汉化教程

一、PyCharm激活 激活码&#xff1a; KQ8KMJ77TY-eyJsaWNlbnNlSWQiOiJLUThLTUo3N1RZIiwibGljZW5zZWVOYW1lIjoiVW5pdmVyc2l0YXMgTmVnZXJpIE1hbGFuZyIsImxpY2Vuc2VlVHlwZSI6IkNMQVNTUk9PTSIsImFzc2lnbmVlTmFtZSI6IkpldOWFqOWutuahtiDorqTlh4blupflkI0iLCJhc3NpZ25lZUVtYWlsIjoi…

动态规划part13

647. 回文子串 给定一个字符串&#xff0c;你的任务是计算这个字符串中有多少个回文子串。 具有不同开始位置或结束位置的子串&#xff0c;即使是由相同的字符组成&#xff0c;也会被视作不同的子串。 class Solution:def countSubstrings(self, s: str) -> int:dp [[Fa…

Chat App 项目之解析(九)

Chat App 项目介绍与解析&#xff08;一&#xff09;-CSDN博客文章浏览阅读468次&#xff0c;点赞12次&#xff0c;收藏3次。Chat App 是一个实时聊天应用程序&#xff0c;旨在为用户提供一个简单、直观的聊天平台。该应用程序不仅支持普通用户的注册和登录&#xff0c;还提供了…

ArcGIS小技巧:编辑一个面的边界时,如何让相邻面同步修改

欢迎关注同名微信公众号&#xff0c;更多文章推送&#xff1a; 在ArcGIS中手动编辑2个相邻面的共同边界时&#xff0c;通常需要2个面都跟着修改&#xff1a; 一般做法是用【整形要素工具】&#xff0c;但是【整形要素工具】不能选择多个要素执行&#xff0c;所以需要执行2次&am…

GoFly框架登录Token使用

token是验证请求接口用户身份的标识&#xff0c;框架建议开发者在识别用户身份时使用token尽量不要明文传用户标识数据。 一、生成用户登录token 通过routeuse.GenerateToken生成登录token&#xff0c;方法返回生成的token字符串和err错误提示&#xff0c;其中routeuse.UserC…

删除或丢失的移动硬盘数据如何恢复?三种办法助你找回宝贵资料

在数字化时代&#xff0c;移动硬盘已成为我们存储重要数据不可或缺的工具。然而&#xff0c;数据丢失或误删除的情况时有发生&#xff0c;让人倍感焦虑。别担心&#xff0c;本文将为你详细介绍如何恢复删除或丢失的移动硬盘数据&#xff0c;帮助你找回那些宝贵的资料。 一、检…

太仓自闭症谱系(ASD)儿童

在我国&#xff0c;自闭症谱系&#xff08;ASD&#xff09;儿童被称为“星星的孩子”&#xff0c;他们犹如夜空中闪烁的星星&#xff0c;孤独而遥远。为了关爱这些特殊的孩子&#xff0c;让他们更好地融入社会&#xff0c;太仓市星星雨特殊儿童康复中心应运而生。这家康复中心致…

【YashanDB认证】YCA学习记录

第一章&#xff1a;YashanDB基础介绍 国产化数据库的发展及未来 崖山数据库系统&#xff1a;YashanDB是【深圳计算科学研究院】完全自主研发设计的新型数据库系统&#xff0c;经过工信部下述机构权威检测&#xff0c;内核代码自主率100%。 YashanDB 核心交易型数据库 企业级…

拆卸并简单分析一个充电宝线路板

原因 一个很久的充电宝&#xff0c;电量完全不能满足使用&#xff0c;拆解下来的保护板分析 结构图解 除了下图&#xff0c;还有一些外围电路 工作原理图解 电池保护芯片XB8606A&#xff08;停产&#xff09; VM连接的是充电口的负极&#xff0c;而这个芯片通过控制电池…

IEEEtran类模板中算法Algorithm的写法

1、注释掉默认的引用 % \usepackage{algorithmic} % \usepackage{algorithm}2、在\begin{document}之前加以下内容 \usepackage[ruled,norelsize,vlined,linesnumbered]{algorithm2e} \makeatletter \newcommand{\removelatexerror}{\let\latexerror\gobble} \makeatother3、…

2 kubeflow系统架构 学习笔记

1 Kubeflow生态系统 2 生态系统说明 2.1. Hardware&#xff08;硬件层&#xff09; 提供计算资源的底层硬件支持。GPU&#xff08;如NVIDIA&#xff09;通常用于加速机器学习和深度学习的计算任务&#xff0c;而Intel和AMD则可能提供CPU计算资源。 2.2. Infrastructure&…

线程池【详解】

线程池 1、 线程池概念 如果有非常多的任务需要非常多的线程来完成,每个线程的工作时间不长,就需要创建很多线程,工作完又立即销毁[线程频繁创建和销毁线程] 频繁创建和销毁线程非常消耗性能,那么线程池,就是可以创建一些线程,放在"池子"中,用的时候去池子取一个线…

RJ45网口链接器和PCB板结构再生产上需要注意那些方面

华强盛电子导读&#xff1a;工程技术前面199中间2643后面0038 关于网口和PCB板板结合插件会出现几个问题 ...网口的尺寸结构&#xff0c;PCB板板的孔位小&#xff0c;这里强调&#xff0c;建议孔位开大一点&#xff0c;便于生产插件方便。 在插件生产过程中&#xff0c;RJ45网…

免费批量自动校正图片、PDF文档方向工具

功能介绍&#xff1a;批量自动识别图片和PDF文档页面方向&#xff0c;并校正为正确阅读方向&#xff08;非倾斜纠偏&#xff09; jpg校正演示 #修复exif信息导致的jpg图像显示和实际旋转不一致问题 #增加图像DPI选项,优先原图或者固定DPI&#xff0c;但这些只会对产生旋转的图…

qss的border-image和background-image和background-coloor和color

如果你的图片和按钮一样大&#xff0c;譬如40X40&#xff0c;那么两者都可以。 如果你的图片和按钮不一样大&#xff0c;用border-image会填充或者拉伸缩放以自适应按钮。 background-image则不会。 所以一般情况下&#xff0c;使用border-image会更合适。 border-image&…

深度学习入门:卷积神经网络 | CNN概述,图像基础知识,卷积层,池化层(超详解!!!)

目录 &#x1f354; 前言 &#x1f354; 图像基础知识 1. 像素和通道的理解 2. 小节 &#x1f354; 卷积层 1. 卷积计算 2. Padding 3. Stride 4. 多通道卷积计算 5. 多卷积核卷积计算 6. 特征图大小 7. PyTorch 卷积层 API 7. 小节 &#x1f354; 池化层 1. 池…

openlayers+vite+vue3加载离线地图并实现初始化(一)

前景提示&#xff1a;本文主要讲解使用vite工具构建的项目&#xff0c;利用openlayers实现离线地图的主要一些功能&#xff0c;包括初始化地图、打点、画线、弹窗等等&#xff0c;这些后续有时间会持续为大家更新&#xff0c;本文主要阐述如何实现其首要功能离线地图的初始化。…