核心思路
根据起始点的x,y轴坐标与当前鼠标所在的x,y轴坐标之间生成一个宽度与旋转角度不断变化的div模拟一条线
也可使用宽度不变高度改变方式模拟线的长度
line.style.width = Math.sqrt((moveX - x) * (moveX - x) + (moveY - y) *
(moveY - y)) + “px”;
line.style.transform = “rotate(” + Math.atan2(moveY - y, moveX - x) + “rad)”;
方法实现
// 默认样式
const defaultStyle = {
height: '2px',
background: 'red',
backgroundSize: '8px 1px',
transformOrigin: 'top lefT',
zIndex: 9999,
pointerEvents: 'none',
linearGradient: '',
};
/**
ele:传入的dom容器
x: 起始x轴坐标
y: 其实y轴坐标
fn: 回调函数
style: 样式
*/
// 鼠标按下不放开,从按下点到移动点之间实时生成一条线
// 样式可以完全抽离进行自定义
const startDraw = (ele, x, y, fn, style = defaultStyle) => {
ele = isDOMElement(ele) ? ele : ele.current;
const { background, height, backgroundSize, transformOrigin, zIndex, pointerEvents, linearGradient: oldLinearGradient } = style;
const linearGradient = `linear-gradient(to right, ${background} 0%, transparent 50%, transparent 100%)`;
const move = (e) => {
const moveX = e.clientX;
const moveY = e.clientY;
const line = document.getElementById('line') === null ? document.createElement("div") : document.getElementById('line')
line.id = "line";
line.style.position = "absolute";
line.style.left = x + "px";
line.style.top = y + "px";
line.style.width = Math.sqrt((moveX - x) * (moveX - x) + (moveY - y) * (moveY - y)) + "px";
line.style.height = height;
line.style.background = oldLinearGradient ? oldLinearGradient : linearGradient;
line.style.backgroundSize = backgroundSize;
line.style.transformOrigin = transformOrigin;
line.style.transform = "rotate(" + Math.atan2(moveY - y, moveX - x) + "rad)";
line.style.zIndex = zIndex;
line.style.pointerEvents = pointerEvents;
ele.appendChild(line);
}
ele.addEventListener('mousemove', move);
document.addEventListener('mouseup', () => {
fn && fn();
document.getElementById('line') && document.getElementById('line').remove();
ele.removeEventListener('mousemove', move);
});
}
具体代码应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="demo" style="background-color: #ebebeb;z-index:0;position:absolute;width:1400px;height:600px;"></div>
</body>
<script>
// 判断是否为dom
function isDOMElement(obj) {
return obj instanceof HTMLElement && typeof obj.nodeType === 'number';
}
const defaultStyle = {
height: '2px',
background: 'red',
backgroundSize: '8px 1px',
transformOrigin: 'top lefT',
zIndex: 9999,
pointerEvents: 'none',
linearGradient: '',
};
const startDraw = (ele, x, y, fn, style = defaultStyle) => {
ele = isDOMElement(ele) ? ele : ele.current;
const { background, height, backgroundSize, transformOrigin, zIndex, pointerEvents, linearGradient: oldLinearGradient } = style;
const linearGradient = `linear-gradient(to right, ${background} 0%, transparent 50%, transparent 100%)`;
const move = (e) => {
const moveX = e.clientX;
const moveY = e.clientY;
const line = document.getElementById('line') === null ? document.createElement("div") : document.getElementById('line')
line.id = "line";
line.style.position = "absolute";
line.style.left = x + "px";
line.style.top = y + "px";
line.style.width = Math.sqrt((moveX - x) * (moveX - x) + (moveY - y) * (moveY - y)) + "px";
line.style.height = height;
line.style.background = oldLinearGradient ? oldLinearGradient : linearGradient;
line.style.backgroundSize = backgroundSize;
line.style.transformOrigin = transformOrigin;
line.style.transform = "rotate(" + Math.atan2(moveY - y, moveX - x) + "rad)";
line.style.zIndex = zIndex;
line.style.pointerEvents = pointerEvents;
ele.appendChild(line);
}
ele.addEventListener('mousemove', move);
document.addEventListener('mouseup', () => {
fn && fn();
document.getElementById('line') && document.getElementById('line').remove();
ele.removeEventListener('mousemove', move);
});
}
document.getElementById('demo').onmousedown = function(e) {
const x = e.clientX;
const y = e.clientY;
startDraw(document.getElementById('demo'), x, y)
}
</script>
</html>
具体效果展示