前言:
最近写一个项目遇到了需要拉伸调整一个元素得大小(宽高)。所以打算实现一下。
思路就是用 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;// 定义状态变量,使用useStateconst [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 (<divclassName={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
这个库提供了拖动和调整大小的能力,可以用于在元素上实现拉伸和调整大小的效果。
总结:
这种功能建议使用 成熟的库来实现,兼容性什么的一般都会适配。