原生JS 实现框选功能(react)
时间: 2023-08-17 18:31:09 浏览: 49
下面是一个使用原生JS实现框选功能的例子,你可以在React中将其包装成组件:
```javascript
import React, { useEffect, useRef, useState } from 'react';
import './SelectBox.css';
const SelectBox = ({ children, onSelect }) => {
const [selection, setSelection] = useState({ top: 0, left: 0, width: 0, height: 0 });
const [startPos, setStartPos] = useState({ x: 0, y: 0 });
const [dragging, setDragging] = useState(false);
const containerRef = useRef(null);
useEffect(() => {
const handleMouseMove = (e) => {
if (dragging) {
const currentPos = { x: e.clientX, y: e.clientY };
const width = Math.abs(currentPos.x - startPos.x);
const height = Math.abs(currentPos.y - startPos.y);
const left = Math.min(currentPos.x, startPos.x);
const top = Math.min(currentPos.y, startPos.y);
setSelection({ top, left, width, height });
}
};
const handleMouseUp = (e) => {
setDragging(false);
onSelect({ ...selection });
setSelection({ top: 0, left: 0, width: 0, height: 0 });
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
return () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
}, [dragging, onSelect, selection, startPos]);
const handleMouseDown = (e) => {
e.preventDefault();
setDragging(true);
setStartPos({ x: e.clientX, y: e.clientY });
};
const containerStyle = {
position: 'relative',
};
const selectionStyle = {
position: 'absolute',
backgroundColor: 'rgba(0, 0, 255, 0.2)',
border: '1px dashed blue',
...selection,
};
return (
<div className="container" ref={containerRef} onMouseDown={handleMouseDown} style={containerStyle}>
{children}
{dragging && <div className="selection" style={selectionStyle} />}
</div>
);
};
export default SelectBox;
```
这个组件将子组件包裹在一个容器中,并在容器中实现了框选功能。当用户按下鼠标左键并拖动时,组件会计算出框选区域的位置和大小,并用一个半透明的矩形覆盖在子组件上。当用户松开鼠标左键时,组件会调用`onSelect`回调函数,并将框选区域的位置和大小作为参数传递给它。
你可以像使用普通的`div`组件一样使用`SelectBox`组件。例如,你可以这样写:
```javascript
import React from 'react';
import SelectBox from './SelectBox';
const App = () => {
const items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
{ id: 4, name: 'Item 4' },
{ id: 5, name: 'Item 5' },
];
const handleSelect = (selection) => {
console.log(selection);
};
return (
<SelectBox onSelect={handleSelect}>
{items.map((item) => (
<div key={item.id} style={{ marginBottom: 10 }}>
<input type="checkbox" onChange={() => {}} />
<span style={{ marginLeft: 10 }}>{item.name}</span>
</div>
))}
</SelectBox>
);
};
export default App;
```
在这个例子中,我们将一个复选框列表作为子组件传递给`SelectBox`组件,并在`handleSelect`回调函数中打印出框选区域的位置和大小。当用户用鼠标左键框选一个或多个复选框时,组件会调用`handleSelect`回调函数,并将框选区域的位置和大小作为参数传递给它。