跳到主要内容

可左右拖拽改变大小的区块

可以通过左右两边的拖动区域按下鼠标来改变区块的宽度,对于演示响应式布局非常必要,所有做了这个组件。

你将会在这个网站的其它地方看到这个组件的使用。✨

将鼠标放到区块的左右边缘,容许 5px 的误差内,鼠标指针会变成 col-resize 的样式,此时按住鼠标左右移动可以改变区域的宽度。

Resize Block

代码实现

import React, { useState, useCallback, useEffect } from 'react';
import debounce from '@/site/utils/debounce';

export default function ResizeBlock ({ maxWidth, minWidth, defaultWidth, children }) {
const maxW = maxWidth || 920;
const minW = minWidth || 320;
const defaultW = defaultWidth || 600;

const [blockWidth, setBlockWidth] = useState(defaultW);
const [handSide, setHandSide] = useState('left');
const [clientX, setClientX] = useState(0)
// 是否在拖动
const [isResizing, setIsResizing] = useState(false)

const handleStartResize = useCallback((e, side) => {
setHandSide(side)
setIsResizing(true)
setClientX(e.clientX)
}, [])
const handleStopResize = useCallback(() => {
setIsResizing(false);
}, [])

const didHandleResize = debounce(e => {
if (!isResizing) return
const offset = e.clientX - clientX;
let width = blockWidth
if (handSide === 'left') {
width -= offset
}
if (handSide === 'right') {
width += offset
}
if (width > maxW) width = maxW;
if (width < minW) width = minW;
setClientX(e.clientX);
setBlockWidth(width);
}, 0)

const handleResize = useCallback(didHandleResize, [isResizing, clientX, didHandleResize])

useEffect(() => {
document.addEventListener('mouseup', handleStopResize)
document.addEventListener('mousemove', handleResize)

return () => {
document.removeEventListener('mouseup', handleStopResize)
document.removeEventListener('mousemove', handleResize)
}
}, [handleStopResize, handleResize])

return (
<div className='wrapper'>
<div className='resizeFrame'>
<div className='handDrag dragLeft' onMouseDown={e => handleStartResize(e, 'left')}></div>
<div className='handDrag dragRight' onMouseDown={e => handleStartResize(e, 'right')}></div>
<div className='blockInner' style={{ width: blockWidth ? blockWidth + 'px': 'auto'}}>
{children}
</div>
</div>
</div>
)
}