react里实现左右拉伸实战

封装组件:

我自己写的一个简单的组件,可能有bug。不想自己写,建议用第三方库实现。

新建一个resizeBox.tsx文件写上代码如下:

import React, { ReactNode, useState, useEffect, useRef } from 'react';
import styles from "./resizeBox.less";
interface ResizableBoxProps {/*** 盒子的宽度*/widthNum?: number;/*** 盒子的高度*/heightNum?: number;/*** 内容*/content?: string | ReactNode;/*** 可以传入自己的类名*/className: string;/** 左右是否可以拉伸 左边框拉伸 默认为true*/isLeftFlex: boolean;/** 上下是否可以拉伸  右边框拉伸 默认为true*/isBottomFlex: boolean;
}
const ResizableBox: React.FC<ResizableBoxProps> = ({widthNum,heightNum,content,children,className,isLeftFlex = true,isBottomFlex = true,...props
}) => {const boxRef = useRef<HTMLDivElement>(null);// 根据优先级选择要渲染的标题const contentRender = content || children;// 定义状态变量,使用useStateconst [width, setWidth] = useState(widthNum); // 宽度const [height, setHeight] = useState(heightNum); // 高度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); // 是否正在调整大小useEffect(() => {if (boxRef?.current) {let boxWidth = boxRef?.current?.clientWidth;let boxHeight = boxRef?.current?.clientHeight;console.log(boxRef, boxRef?.current?.clientWidth, "890")setWidth(boxWidth);setHeight(boxHeight);}}, []);/**开始调整大小时的事件处理函数 高度*/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 (<divclassName={`${className} ${styles.resizable_box}`}style={{ width: !isLeftFlex ? "100%" : `${width}px`, height: !isBottomFlex ? "100%" : `${height}px` }} // 使用状态变量控制宽度和高度ref={boxRef}><div className={styles.container}>{contentRender}</div>{isLeftFlex && <div className={`${styles.button} ${styles.right_button}`} onMouseDown={startResizeX}></div>}{isBottomFlex && <div className={`${styles.button} ${styles.bottom_button}`} onMouseDown={startResizeY}></div>}</div>);
};
export default ResizableBox;

新建一个resizeBox.less:

这里我用的是style Module 如果你不用这个请自行转换语法。只需要把resizeBox.tsx里的styles.去掉。并且直接引入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;background: blue;
}.bottom_button {width: 100%;height: 2px;bottom: -2px;// left: 50%;// transform: translateX(-50%);cursor: n-resize;background: blue;
}

组件使用文档:

interface ResizableBoxProps {/*** 盒子的宽度*/widthNum?: number;/*** 盒子的高度*/heightNum?: number;/*** 内容*/content?: string | ReactNode;/*** 可以传入自己的类名*/className?: string;/** 左右是否可以拉伸 左边框拉伸 默认为true*/isLeftFlex?: boolean;/** 上下是否可以拉伸  右边框拉伸 默认为true*/isBottomFlex?: boolean;
}
参数名类型描述
widthNumnumber (可选)盒子的宽度
heightNumnumber (可选)盒子的高度
content`stringReactNode` (可选)
classNamestring (可选)自定义的类名
isLeftFlexboolean (可选)左右是否可以拉伸,左边框拉伸,默认为 true
isBottomFlexboolean (可选)上下是否可以拉伸,底边框拉伸,默认为 true

实际用法:

左右拉伸,左边拉伸右边跟着变动:

这里使用了flex巧妙的实现了这个效果,左边div设置一个宽度,右边的flex:1即可。

左右设置width

import React, { useEffect, useState, useRef } from "react";
import styles from "./index.less";
import ResizeBox from "./resizeBox";
const EtfManager: React.FC = () => {// const myRef = useRef(null);return (<div style={{ marginTop: 40, background: "#fff", height: 800, display: "flex",flexDirection: "row"}}><ResizeBox className={styles.left}><div></div></ResizeBox><div className={styles.right}></div></div>);
};
export default EtfManager;

index.less:

.left {width: 40%;background: red;height: 100%;
}.right {flex: 1;width: 200px;background: green;height: 100%;
}

效果图如下:
鼠标放到蓝色的线上即可拖动。
左右效果图

上下拉伸,上边拉伸下边跟着变动:

上下设置height,且 flex-direction:column 设置纵向布局。

import React, { useEffect, useState, useRef } from "react";
import styles from "./index.less";
import ResizeBox from "./resizeBox";
const EtfManager: React.FC = () => {// const myRef = useRef(null);return (<div style={{ marginTop: 40, background: "#fff", height: 800, display: "flex",flexDirection: "column"}}><ResizeBox className={styles.left}><div></div></ResizeBox><div className={styles.right}></div></div>);
};
export default EtfManager;

index.less:

.left{width:100%;background: red;height: 50%;}.right{flex: 1;background: green;width: 100%;}

上下效果图

其他用法 可以自行拓展和嵌套 resizeBox组件使用:

其他用法可以自行拓展组件和嵌套resizeBox组件使用。我只是提供一个思路。
比如 左右拉伸 和上下拉伸组合:

import React, { useEffect, useState, useRef } from "react";
import styles from "./index.less";
import ResizeBox from "./resizeBox";
const EtfManager: React.FC = () => {// const myRef = useRef(null);return (<div style={{ display: "flex", marginTop: 40, background: "#fff", height: 800, width: "100%" }}><ResizeBox className={styles.vv}><ResizeBox className={styles.left} isLeftFlex={false}><div></div></ResizeBox><div className={styles.right}></div></ResizeBox><div style={{ flex: 1 }}>888</div></div>);
};
export default EtfManager;

less:

.left {width: 100%;background: red;height: 50%;
}.right {flex: 1;background: green;width: 100%;
}.vv {display: flex;flex-direction: column;width: 30%;border: 1px solid yellow;
}

左边上下拉,黄色的线左右拉。
在这里插入图片描述

盒子带滚动条就需要 动态加上或减去滚动的高度

resizeBox.tsx使用以下代码即可:

import React, { ReactNode, useState, useEffect, useRef } from 'react';
import styles from "./resizeBox.less";
interface ResizableBoxProps {/*** 盒子的宽度*/widthNum?: number;/*** 盒子的高度*/heightNum?: number;/*** 内容*/content?: string | ReactNode;/*** 可以传入自己的类名*/className?: string;/** 左右是否可以拉伸 左边框拉伸 默认为true*/isLeftFlex?: boolean;/** 上下是否可以拉伸  右边框拉伸 默认为true*/isBottomFlex?: boolean;
}
const ResizableBox: React.FC<ResizableBoxProps> = ({widthNum,heightNum,content,children,className,isLeftFlex = true,isBottomFlex = true,...props
}) => {const boxRef = useRef<HTMLDivElement>(null);// 根据优先级选择要渲染的标题const contentRender = content || children;// 定义状态变量,使用useStateconst [width, setWidth] = useState(widthNum); // 宽度const [height, setHeight] = useState(heightNum); // 高度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 [xMoveing, setXMoveing] = useState(false); // 是否正在调整大小const getScrollTop = () => {var scrollTop = 0;if (typeof window.pageYOffset === "number") {// 支持 pageYOffset 属性(IE9+,最新浏览器)scrollTop = window.pageYOffset;} else if (document.documentElement &&document.documentElement.scrollTop) {// 支持 document.documentElement.scrollTop 属性(IE8+)scrollTop = document.documentElement.scrollTop;} else if (document.body && document.body.scrollTop) {// 支持 document.body.scrollTop 属性(IE6, IE7)scrollTop = document.body.scrollTop;}return scrollTop;};const getScrollLeft = () => {let scrollLeft = 0;if (typeof window.pageXOffset === "number") {// 支持 pageXOffset 属性(IE9+,最新浏览器)scrollLeft = window.pageXOffset;} else if (document.documentElement &&document.documentElement.scrollLeft) {// 支持 document.documentElement.scrollLeft 属性(IE8+)scrollLeft = document.documentElement.scrollLeft;} else if (document.body && document.body.scrollLeft) {// 支持 document.body.scrollLeft 属性(IE6, IE7)scrollLeft = document.body.scrollLeft;}return scrollLeft;};// 使用示例useEffect(() => {if (boxRef?.current) {let boxWidth = boxRef?.current?.clientWidth;let boxHeight = boxRef?.current?.clientHeight;// 获取元素位置信息let boxClientRect = boxRef?.current?.getBoundingClientRect();let boxLeft = boxClientRect?.left;let boxTop = boxClientRect?.top;setWidth(boxWidth);setHeight(boxHeight);setStartX(boxLeft);setStartY(boxTop);}const getScrollTop = () => {var scrollTop = 0;if (typeof window.pageYOffset === "number") {// 支持 pageYOffset 属性(IE9+,最新浏览器)scrollTop = window.pageYOffset;} else if (document.documentElement &&document.documentElement.scrollTop) {// 支持 document.documentElement.scrollTop 属性(IE8+)scrollTop = document.documentElement.scrollTop;} else if (document.body && document.body.scrollTop) {// 支持 document.body.scrollTop 属性(IE6, IE7)scrollTop = document.body.scrollTop;}return scrollTop;};}, []);/**开始调整大小时的事件处理函数 高度*/const startResizeY = (event: any) => {event.preventDefault();const { clientX, clientY } = event;setStartY(clientY + getScrollTop());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 + getScrollLeft());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 + getScrollLeft();setWidth(newWidth);setXMoveing(true);};/**高度调整大小 */const resizeY = (event: any) => {const { clientY } = event;const deltaY = clientY - startY;const newHeight = initialHeight + deltaY + getScrollTop();console.log(newHeight, getScrollTop(), initialHeight, "newHeight");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]);// 返回可调整大小的组件const xMove = (event: any) => {if (isResizing) {event.preventDefault();const { clientX, clientY } = event;setStartX(clientX);setInitialWidth(width);resizeX(event);}}return (<divclassName={`${className} ${styles.resizable_box}`}style={{ width: !isLeftFlex ? "100%" : `${width}px`, height: !isBottomFlex ? "100%" : `${height}px` }} // 使用状态变量控制宽度和高度ref={boxRef}><div className={styles.container}>{contentRender}</div>{isLeftFlex && <div className={`${styles.button} ${styles.right_button}`} onMouseDown={startResizeX}></div>}{isBottomFlex && <div className={`${styles.button} ${styles.bottom_button}`} onMouseDown={startResizeY}></div>}</div>);
};
export default ResizableBox;

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

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

相关文章

【中危】Oracle TNS Listener SID 可以被猜测

一、漏洞详情 Oracle 打补丁后&#xff0c;复测出一处中危漏洞&#xff1a;Oracle TNS Listener SID 可以被猜测。 可以通过暴力猜测的方法探测出Oracle TNS Listener SID&#xff0c;探测出的SID可以用于进一步探测Oracle 数据库的口令。 建议解决办法&#xff1a; 1. 不应该使…

【某农业大学计算机网络实验报告】实验四 路由信息协议RIP

实验目的&#xff1a; 1&#xff0e;深入了解RIP协议的特点和配置方法&#xff1a;通过此次实验&#xff0c;掌握RIP协议作为一种动态路由协议的基本工作原理&#xff0c;了解其距离向量算法的核心概念&#xff0c;以及如何在网络设备上配置RIP协议&#xff1b; 2.验证RIP协议…

基于微信小程序的电影交流平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

【Next.js 项目实战系列】02-创建 Issue

原文链接 CSDN 的排版/样式可能有问题&#xff0c;去我的博客查看原文系列吧&#xff0c;觉得有用的话&#xff0c;给我的库点个star&#xff0c;关注一下吧 上一篇【Next.js 项目实战系列】01-创建项目 创建 Issue 配置 MySQL 与 Prisma​ 在数据库中可以找到相关内容&…

Java项目-基于Springboot的招生管理系统项目(源码+说明).zip

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

智联云采 SRM2.0 testService SQL注入漏洞复现

0x01 产品简介 智联云采是一款针对企业供应链管理难题及智能化转型升级需求而设计的解决方案,针对企业供应链管理难题,及智能化转型升级需求,智联云采依托人工智能、物联网、大数据、云等技术,通过软硬件系统化方案,帮助企业实现供应商关系管理和采购线上化、移动化、智能…

求助,宠物空气净化器该怎么选?双十一有什么推荐购买的吗?

今晚就要付双十一尾款了&#xff0c;拖延症晚期的我还没做什么功课。本来不打算消费的&#xff0c;看了眼购物车&#xff0c;之前想买的宠物空气净化器降价了不少&#xff0c;不想错失这次优惠。 我家猫孩子之前不怎么掉毛的&#xff0c;连日常的梳毛我都经常偷懒&#xff0c;…

WordPress+Nginx 安装教程

WordPress 是一个开源的网站建设工具&#xff0c;可以用它来“快速”搭建个人博客&#xff0c;官网等等。它本身是用 php 开发的&#xff0c;本身部署不复杂&#xff0c;主要是需要一些配套的东西才能跑起来&#xff0c;网上的一些教程也是写的不清不楚&#xff0c;本文针对非 …

Centos7安装ZLMediaKit

https://github.com/ZLMediaKit/ZLMediaKit 一 获取代码 git clone https://gitee.com/xia-chu/ZLMediaKit cd ZLMediaKit git submodule update --init git submodule update --init 命令用于初始化和更新 Git 仓库中的子模块&#xff08;submodules&#xff09;。这个命令…

安全生产玩手机检测系统 玩手机识别系统 玩手机监测预警系统 使用 Python 和 OpenCV 库实现

在生产作业过程中&#xff0c;员工玩手机是一种极其危险的行为。它会分散员工的注意力&#xff0c;使其无法专注于工作任务。生产现场往往存在各种潜在的危险因素&#xff0c;如机械设备的运转、高空作业、化学品的使用等&#xff0c;一旦员工分心&#xff0c;就很容易忽视这些…

跨浏览器免费书签管理系统

随着互联网信息的爆炸式增长&#xff0c;如何有效管理我们日常浏览中发现的重要网页&#xff0c;成为了每个重度互联网用户的需求。一个跨平台的书签管理网站能够帮助用户在不同设备之间无缝同步和管理书签。本文将分享如何使用 Python 和 SQLite 构建一个简单、易于维护的跨平…

暖水毯/取暖毯语音识别控制芯片IC方案

暖水毯、取暖毯作为现代家居生活的温暖伴侣&#xff0c;其智能化升级已是大势所趋。在暖水毯与取暖毯中融入语音识别控制芯片IC方案&#xff0c;为用户的冬日取暖体验带来了革命性的变革。 一、暖水毯/取暖毯增加语音识别控制芯片方案&#xff0c;让产品能通过对话来调节&…

Ubuntu 24.04 系统上配置 Node.js 运行环境

本文我们重点介绍两种安装 Node.js 的方法。第一种方法使用 NVM (Node VersionManager)&#xff0c;这是安装和管理多个 Node.js 版本的最好和最快的方法。第二种方法使用官方包存储库在 Ubuntu 上安装 Node.js&#xff0c;一次只允许安装一个版本。 必备条件 A running Ubun…

qUtf8Printable()和qPrintable()

qUtf8Printable 函数是 Qt 框架中的一个实用函数&#xff0c;其主要作用是将 QString 类型的字符串安全地转换为 const char* 类型的 UTF-8 编码字符串。这个转换过程对于需要将 QString 与那些接受 const char* 参数的 C 风格字符串函数进行交互的场景特别有用。 qUtf8Printa…

3.Java入门笔记--基础语法

1.字面量 概念&#xff1a;计算机用来处理数据的&#xff0c;字面量就是告诉程序员数据在程序中的书写格式 常用数据&#xff1a;整数&#xff0c;小数直接写&#xff1b;字符单引号&#xff08;A&#xff09;且只能放一个字符&#xff1b;字符串双引号&#xff08;"Hel…

ROUGE:摘要自动评估软件包

算法解析 ROUGE&#xff08;Recall-Oriented Understudy for Gisting Evaluation&#xff09;是一组用于自动评估文本摘要质量的指标&#xff0c;主要通过比较机器生成的摘要与一个或多个参考摘要之间的重合程度来衡量。ROUGE 包括多个变体&#xff0c;其中最常用的有 ROUGE-N…

深度解析模型调优与正则化:L1、L2正则化及偏差-方差的权衡

&#x1f3af; 深度解析模型调优与正则化&#xff1a;L1、L2正则化及偏差-方差的权衡 &#x1f4d6; 目录 &#x1f31f; 模型调优的本质&#xff1a;偏差与方差的权衡&#x1f50e; 正则化的概念与作用&#x1f6e0; L1正则化&#xff08;Lasso回归&#xff09;详解与实现⚙…

linux 修改主机名和用户名颜色

编译 ~/.bashrc vim ~/.bashrc 如下格式 PS1\[\e[1;31m\]\h:\[\e[0;32m\]\w \[\e[1;34m\]\u\[\e[0m\]\$ PS1${debian_chroot:($debian_chroot)}\[\033[01;31m\]\u\[\033[01;33m\]\[\033[01;36m\]\h \[\033[01;33m\]\w \[\033[01;35m\]\$ \[\033[00m\] if [ -e /lib/terminfo…

QT中中文显示乱码问题

在VS2013中用QT开发GUI应用程序&#xff0c;Qt中显示中文乱码 一&#xff1a; //解决QT中中文显示乱码问题 #pragma execution_character_set("utf-8") 二&#xff1a;在main函数中添加以下代码&#xff1a; #include <QTextCodec>void main() {QTextCod…

MySQL中的增查操作:探索数据的奥秘,开启数据之门

本节&#xff0c;我们继续深入了解MySQL&#xff0c;本章所讲的基础操作&#xff0c;针对的是表的增删查改&#xff01; 一、Create 新增 1.1、语法 INSERT [INTO] table_name[(column [, column] ...)] VALUES(value_list) [, (value_list)] ... value_list: value, [, va…