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.rhkb.cn/news/453697.html

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

相关文章

具备哪些特质的内外网文件交换系统 才是高科技企业需要的?

高科技企业是指涉及对国家产生深远和积极影响的先进技术的产业集群&#xff0c;它们以持续的创新和高研发投入为核心&#xff0c;推动科技进步和产业升级。高科技企业是市场经济的重要组成&#xff0c;为经济发展和技术进步提供充足动力&#xff0c;因此&#xff0c;高科技企业…

LeetCode刷题日记之贪心算法(五)

目录 前言无重叠区间划分字母区间合并区间单调递增的数字监控二叉树总结 前言 随着对贪心算法的不断深入&#xff0c;本篇文章将继续挑战一些经典的题目&#xff0c;进一步巩固这一算法的应用技巧。希望博主记录的内容能够帮助大家更好地掌握贪心算法的解题思路✍✍✍ 无重叠区…

【K8S系列】Kubernetes Pod节点CrashLoopBackOff 状态及解决方案详解【已解决】

在 Kubernetes 中&#xff0c;Pod 的状态为 CrashLoopBackOff 表示某个容器在启动后崩溃&#xff0c;Kubernetes 尝试重启该容器&#xff0c;但由于持续崩溃&#xff0c;重启的间隔时间逐渐增加。下面将详细介绍 CrashLoopBackOff 状态的原因、解决方案及相关命令的输出解释。 …

Openlayers高级交互(3/20):动态添加 layer 到 layerGroup,并动态删除

layerGroup 是 OpenLayers 库中的一个类,用于创建图层组。图层组允许您将多个图层组合在一起,并作为一个整体来控制它们的可见性和其他属性。本示例动态添加layer到layerGroup,并动态删除。 效果图 专栏名称内容介绍Openlayers基础实战 (72篇)专栏提供73篇文章,为小白群…

回归预测||时序预测||基于灰狼优化的时域卷积TCN连接Transformer-BiLSTM的数据回归预测|时序预测Matlab程序

回归预测||时序预测||基于灰狼优化的时域卷积TCN连接Transformer-BiLSTM的数据回归预测|时序预测Matlab程序 文章目录 一、基本原理一、基本概念二、原理和流程1. 数据准备2. 模型构建3. 灰狼优化算法设计4. 模型训练与优化5. 模型评估与预测 三、优势与应用四、总结 二、实验结…

Docker 用例:15 种最常见的 Docker 使用方法

容器化应用程序而不是将它们托管在虚拟机上是过去几年一直流行的概念&#xff0c;使容器管理流行起来。Docker 处于这一转变的核心&#xff0c;帮助组织无缝地采用容器化技术。最近&#xff0c;Docker 用例遍布所有行业&#xff0c;无论规模大小和性质如何。 什么是Docker&…

Windows--使用node.js的免安装版本

原文网址&#xff1a;Windows--使用node.js的免安装版本_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Windows下如何使用node.js的免安装版本。 下载 1.访问官网 https://nodejs.org/en 记住这个版本号&#xff0c;这个是长期支持的版本。 2.找到压缩包 点击其他下载&#…

windows系统中,在cmd窗口演练 Redis 基本操作命令

文章目录 一、Redis 介绍1.1 Redis 的应用场景1.2 Redis 的特点 二、Windows版Redis安装三、Redis Desktop Manager安装四、Redis 常用基本操作4.1 查看操作4.2 操作string类型的命令4.2.1 设置获取Key4.2.2 MSET&#xff08;Multi&#xff09;支持批量设置key、MGET支持批量获…

平时使用Xshell能连接虚拟机,现在突然连接不上

问题&#xff1a;平时使用Xshell能连接虚拟机&#xff0c;现在突然连接不上&#xff0c;使用ip addr 命令查看ip地址 ens33 接口状态为 DOWN&#xff0c;没有分配IP地址&#xff0c;这通常意味着该网络接口未激活或存在配置问题。&#xff08;因为平时能连接&#xff0c;就说明…

DNS代理是什么?浅析DNS代理的工作原理及应用

DNS代理作为计算机网络中重要的一环&#xff0c;扮演着连接用户和互联网服务的关键角色。来了解DNS代理的定义、功能、工作原理以及在网络中的应用场景和重要性吧。 一、理解DNS代理。 DNS代理充当在用户和真正的DNS服务器之间的中介。它接收来自用户端的DNS查询请求&#xf…

std::function和bind绑定器

本文来自《深入应用C11 代码优化与工程级应用》 std::function和std::bind&#xff0c;使我们使用标准库函数时更加方便&#xff0c;且还能方便地实现延迟求值。 1.可调用对象(Callable Objects) 可调用对象有如下几种定义&#xff1a; (1)是一个函数指针 #include<ios…

php elasticsearch/elasticsearch使用apikey访问接口

此处使用的windows版es和kibana。 1.前提&#xff1a;以安装好es和kibana并正常运行&#xff0c;记得保存es安装完成时提示的账号密码。 2.登录kibana,创建索引并加入几条数据,可以通过kibana界面添加或者通过调用接口添加&#xff0c;非重点不赘述了。 3.添加ApiKey, 使用…

Linux 部署 Harbor 镜像仓库详解

文章目录 安装 Docker安装 Harbor访问 Harbor 安装 Docker 本次部署流程使用的是1台阿里云ECS&#xff0c;Ubuntu 22.04&#xff0c;2核4G。 首先需要做的是在当前服务器上&#xff0c;安装好 Docker&#xff0c;参考链接如下&#xff1a; https://blog.csdn.net/weixin_4659…

ESD防静电闸机如何保护汽车电子产品

随着汽车电子技术的快速发展&#xff0c;汽车中集成了越来越多的电子设备&#xff0c;如车载信息娱乐系统、自动驾驶传感器、驾驶辅助系统等。静电放电可能导致电子组件的损坏、性能下降&#xff0c;甚至使整个系统失效。因此&#xff0c;如何有效保护汽车电子产品免受静电损害…

【【自动驾驶】车辆运动学模型】

【自动驾驶】车辆运动学模型 1. 引言2. 以车辆重心为中心的单车模型2.1 模型介绍2.2 滑移角 β \beta β 的推导2.2 航向角 ψ \psi ψ推导过程&#xff1a;2.3 滑移角 β \beta β2.3 Python代码实现2.4 C代码实现 3. 前轮驱动的单车模型3.1 模型介绍3.3 Python代码实现3.4 …

软件I2C的代码

I2C的函数 GPIO的配置——scl和sda都配置为开漏输出 void MyI2C_Init(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruture;GPIO_InitStruture.GPIO_Mode GPIO_Mode_Out_OD;GPIO_InitStruture.GPIO_PinGPIO_Pin_10 | GPIO_Pin_…

Debug-029-el-table实现自动滚动分批请求数据

前情提要 最近做了一个小优化&#xff0c;还是关于展示大屏方面的。大屏中使用el-table展示列表数据&#xff0c;最初的方案是将数据全部返回&#xff0c;确实随着数据变多有性能问题&#xff0c;有时请求时间比较长。这里做的优化就是实现列表的滚动到距离底部一定高度时再次请…

【银河麒麟高级服务器操作系统实例】金融行业TCP连接数猛增场景的系统优化

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 服务器环境以及配置 物理机/虚拟机/云/容器 物理…

项目实战:Qt+OpenCV仿射变换工具v1.1.0(支持打开图片、输出棋盘角点、调整偏移点、导出变换后的图等等)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/143105881 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、Op…

python中frida的安装+frida-server(雷电模拟器)保姆级安装教程

一.安装雷电模拟器 雷电模拟器官网 直接下载安装即可 &#xff08;1&#xff09;打开必要权限 雷电模拟器的设置已完毕 二.安装adb工具 本文以autox.js来实现adb操作 &#xff08;1&#xff09;vscode中下载auto.js插件 &#xff08;2&#xff09;雷电模拟器下载autox.j…