create-react-component-template
Version:
112 lines (106 loc) • 2.92 kB
JavaScript
/*
* Author rhys.zhao
* Date 2022-01-28 15:27:52
* LastEditors rhys.zhao
* LastEditTime 2022-06-22 13:36:56
* Description 拖拽,缩放容器组件
*/
import React, { useEffect, useRef } from 'react';
import styles from './index.scss';
let params = {
isDragging: false,
clientX: 0,
clientY: 0,
x: 0,
y: 0,
zoom: 1
};
const DragZoomContainer = (props) => {
const {
zoomOnInner = false,
zoomRange = { min: 0.5, max: 5 },
zoomOrigin = '50% 50%',
dragInDocument = true,
outerStyle = {},
position = { top: 0, left: 0 },
children
} = props;
const outerRef = useRef();
const innerRef = useRef();
// 滚动缩放
const onWheel = (dom) => {
dom.onwheel = (e) => {
e.preventDefault();
e = e || window.event;
params.zoom += e.wheelDelta / 1200;
const { min, max } = zoomRange;
if (params.zoom > max) params.zoom = max;
if (params.zoom < min) params.zoom = min;
let inner = innerRef.current;
inner.style.transform = `scale(${params.zoom})`;
inner.style.transformOrigin = zoomOrigin;
};
};
// 拖拽
const onDrag = (inner, container = document) => {
// 鼠标按下
inner.onmousedown = (e) => {
if (e.buttons === 2) {
return;
}
e.preventDefault();
e = e || window.event;
params.isDragging = true;
// 记录鼠标位置
params.clientX = e.clientX;
params.clientY = e.clientY;
// 记录inner位置
params.x = inner.offsetLeft;
params.y = inner.offsetTop;
};
// 鼠标移动
container.onmousemove = (e) => {
e = e || window.event;
if (params.isDragging) {
// 计算鼠标上下左右移动
let moveX = e.clientX - params.clientX;
let moveY = e.clientY - params.clientY;
// 更新inner位置
params.x += moveX;
params.y += moveY;
// inner移动等于鼠标的移动
inner.style.left = params.x + 'px';
inner.style.top = params.y + 'px';
// 更新鼠标位置
params.clientX = e.clientX;
params.clientY = e.clientY;
}
};
// 鼠标弹起
document.onmouseup = () => {
params.isDragging = false;
};
};
useEffect(() => {
const inner = innerRef.current;
const outer = outerRef.current;
// 初始化inner在容器中的位置
const { top, left } = position;
inner.style.left = left + 'px';
inner.style.top = top + 'px';
// 拖拽事件
const container = dragInDocument ? window.document : outer;
onDrag(inner, container);
// 缩放事件
const zoomOn = zoomOnInner ? inner : outer;
onWheel(zoomOn);
}, []);
return (
<div style={outerStyle} className={styles.outer} ref={outerRef}>
<div className={styles.inner} ref={innerRef}>
{children}
</div>
</div>
);
};
export default DragZoomContainer;