如何实现鼠标在圆形div内移动、触边时带动圆形整体位移的效果
圆形十字瞄准镜交互实现方案
你现有代码的核心问题是直接将圆形的位移和全局鼠标移动绑定,同时十字准星使用了固定定位,没有处理圆内的鼠标偏移逻辑。调整逻辑如下:
实现思路
- 优先响应圆内的鼠标偏移:当鼠标在圆形内部移动时,仅修改十字准星的top、left属性,让准星跟随鼠标移动
- 边缘触发圆形位移:当鼠标移动到圆形边缘时,计算超出的位移量,将这部分偏移叠加到圆形的定位上,实现圆形跟随移动的效果
- 边界限制:确保圆形不会移出外层黑色box的范围
完整调整后代码
HTML代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="box" class="box"> <div id="circle" class="circle"> <div id="crosshair" class="crosshair"></div> </div> </div>
CSS代码
body{ margin:0px; padding:0px; font-family: 'Roboto', sans-serif; } .box{ width:500px; height:500px; background:#000000; position:relative; cursor:crosshair; overflow: hidden; } .circle { position: absolute; background: black; border: solid 1px #ccc; width:120px; height:120px; border-radius: 50%; left: 0; top: 0; } /* 准星样式可根据需求调整,这里做了十字优化 */ .crosshair{ position: absolute; width: 20px; height: 20px; left: 50px; top: 50px; pointer-events: none; /* 避免准星拦截鼠标事件 */ } .crosshair::before, .crosshair::after { content: ''; position: absolute; background: #fff; } .crosshair::before { width: 100%; height: 2px; top: 50%; transform: translateY(-50%); } .crosshair::after { height: 100%; width: 2px; left: 50%; transform: translateX(-50%); }
JS代码
jQuery(document).ready(function() { const circleWidth = 120; const circleHeight = 120; const borderWidth = 1; const boxWidth = 500; const boxHeight = 500; const crosshairSize = 20; // 准星可移动的范围边界 const crosshairMin = crosshairSize / 2; const crosshairMax = circleWidth - crosshairSize / 2; let circleLeft = 0; let circleTop = 0; $('#box').mousemove(function(event) { // 计算鼠标相对于圆形的坐标 const offsetX = event.clientX - circleLeft - borderWidth; const offsetY = event.clientY - circleTop - borderWidth; let crosshairX = offsetX - crosshairSize / 2; let crosshairY = offsetY - crosshairSize / 2; // 处理准星水平方向边界,超出则移动圆形 if (crosshairX < crosshairMin) { const diff = crosshairMin - crosshairX; circleLeft = Math.max(0, circleLeft - diff); crosshairX = crosshairMin; } else if (crosshairX > crosshairMax - crosshairSize) { const diff = crosshairX - (crosshairMax - crosshairSize); circleLeft = Math.min(boxWidth - circleWidth - borderWidth * 2, circleLeft + diff); crosshairX = crosshairMax - crosshairSize; } // 处理准星垂直方向边界,超出则移动圆形 if (crosshairY < crosshairMin) { const diff = crosshairMin - crosshairY; circleTop = Math.max(0, circleTop - diff); crosshairY = crosshairMin; } else if (crosshairY > crosshairMax - crosshairSize) { const diff = crosshairY - (crosshairMax - crosshairSize); circleTop = Math.min(boxHeight - circleHeight - borderWidth * 2, circleTop + diff); crosshairY = crosshairMax - crosshairSize; } // 同步更新准星和圆形的位置 $('#crosshair').css({ left: crosshairX + 'px', top: crosshairY + 'px' }); $('#circle').css({ left: circleLeft + 'px', top: circleTop + 'px' }); }); });
内容的提问来源于stack exchange,提问作者BepaTest
相关产品推荐
相关产品推荐

