父元素中拖动子元素实现

结果

结果

过程

鼠标点下事件的event为鼠标相对于浏览器窗口的位置信息
子元素要在父元素范围内拖动,那就有一个允许拖动的范围,子元素本身有宽高,这也是拖动范围计算要考虑的
首先获取mousedown的点相对于子元素边界的距离
按下的点相对于子元素边界的信息
上面计算得到的距离也作为子元素边界到容器边界的距离极值
mouseBounds得到的结果为鼠标相对于浏览器可以移动的范围
因父元素相对于浏览器窗口还有一个相对的距离,为上面的offsetX、offsetY
子元素在父元素内的位置计算
上面的计算内容当按下点在前面计算得到范围内的判断,如果在超出范围则赋予对应的极值,最后结果还要减去父元素相对于浏览器的偏移值

代码

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<meta http-equiv="X-UA-Compatible" content="ie=edge" />
		<title>Document</title>
		<style>
			html,body,.father {margin: 0;height: 100%;width: 100%;}
            body{display: flex;justify-content: center; align-items: center;}
            .contain{ position: relative; height: 90%;width: 90%;border: black 1px solid;background-color: rgba(205, 135, 222, 0.767);}
			.child {position: absolute;height: 200px;width: 200px;border: black 1px solid;background-color: coral;}
		</style>
	</head>
	<body>
		<div class="contain">
			<div id="father" class="father">
				<div
					id="child"
					class="child"
					onmousedown="mouseDown(event)"
				></div>
			</div>
		</div>
		<script>
			let child = document.querySelector('#child')
			const mouseDown = evt => {
				let mBounds = mouseBounds(
					evt,
					child.getClientRects()[0],
					document.querySelector('#father').getClientRects()[0]
				)
				document.onmousemove = function(ev) {
					let pt = calcPositon(ev, mBounds)
					child.style.left = pt.left + 'px'
					child.style.top = pt.top + 'px'
					child.style.opacity = 0.9
					child.style.cursor = 'move'
				}
				document.onmouseup = function() {
					document.onmousemove = null
					document.onmouseup = null
					child.style.opacity = 1
					child.style.cursor = 'default'
				}
			}
			const calcPositon = (pt, bounds) => {
				const left =
					(pt.x > bounds.left && pt.x < bounds.right
						? pt.x
						: pt.x >= bounds.right
						? bounds.right
						: bounds.left) - bounds.offsetX
				const top =
					(pt.y > bounds.top && pt.y < bounds.bottom
						? pt.y
						: pt.y >= bounds.bottom
						? bounds.bottom
						: bounds.top) - bounds.offsetY
				return { left, top }
			}
			/**
			 * 鼠标可以移动的范围
			 * pt:鼠标按下的点
			 * compRact:要移动组件的矩形对象
			 * containerRact:容器的矩形对象
			 * return 的范围为浏览器窗口中的范围
			 */
			const mouseBounds = (pt, compRact, containerRact) => {
				return {
					left: containerRact.left + (pt.x - compRact.left),
					right: containerRact.right - (compRact.right - pt.x),
					top: containerRact.top + (pt.y - compRact.top),
					bottom: containerRact.bottom - (compRact.bottom - pt.y),
					offsetX: containerRact.left + (pt.x - compRact.left),
					offsetY: containerRact.top + (pt.y - compRact.top)
				}
			}
		</script>
	</body>
</html>
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值