Vanilla JS实现Div 3D按钮按压效果异常问题求助
问题描述
我正在开发一个项目,需要为页面中标注Block1、Block2、Block3的Div实现以下三个功能:
- 响应click事件切换颜色;
- 响应mousedown事件时,Div呈现按压状态,移除box-shadow阴影效果;
- 响应mouseup事件时,恢复与当前颜色对应的box-shadow属性。
目前仅功能1正常工作,功能2和3仅在Div处于蓝色(touch-button类)状态时生效,切换为红色(touch-button-click类)状态后失效。
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Dynamic and Draggable Divs</title> <link rel="stylesheet" href="dynamicDivs.css"> </head> <body> <div id="touch-buttons-grid"> <div class="touch-button" draggable="true">Block 1</div> <div class="touch-button" draggable="true">Block 2</div> <div class="touch-button" draggable="true">Block 3</div> <div class="touch-button-spots"></div> <div class="touch-button-spots"></div> <div class="touch-button-spots"></div> </div> <script src="dynamicDivs.js"></script> </body> </html>
JavaScript代码(问题所在)
const touchButtons = document.querySelectorAll(".touch-button"); let draggedElement = null; function toggleTouchButtonColor(event) { if (event.target.classList.contains("touch-button")) { event.target.classList.add("touch-button-click"); event.target.classList.remove("touch-button"); } else if (event.target.classList.contains("touch-button-click")) { event.target.classList.add("touch-button"); event.target.classList.remove("touch-button-click"); } } function mouseDownTouchButton(event) { event.target.style.top = "5px"; event.target.style.left = "5px"; } function mouseUpTouchButton(event) { event.target.style.top = "0px"; event.target.style.left = "0px"; } touchButtons.forEach(function (touchButton) { touchButton.addEventListener("mousedown", mouseDownTouchButton); touchButton.addEventListener("mouseup", mouseUpTouchButton); touchButton.addEventListener("click", toggleTouchButtonColor); });
CSS样式表
#touch-buttons-grid { width: 90%; height: 200px; margin: 10px auto; margin-top: 20px; background-color: rgba(220, 200, 10, 0.5); border-radius: 10px; display: grid; grid-template-columns: repeat(3, 30%); align-items: center; justify-content: center; z-index: 1; } .touch-button, .touch-button-spots { width: 40%; height: 50px; margin: 5px auto; padding: 5px; border-radius: 10px; font-size: 20px; text-align: center; z-index: 5; position: relative; } .touch-button { background-color: rgba(60, 95, 240, 0.5); box-shadow: 5px 5px rgba(60, 95, 240, 0.25); } .touch-button-click { width: 40%; height: 50px; margin: 5px auto; padding: 5px; border-radius: 10px; background-color: rgba(220, 41, 10, 1); box-shadow: 5px 5px rgba(220, 41, 10, 0.5); font-size: 20px; text-align: center; z-index: 5; } .touch-button-spots { width: 50%; height: 60px; background-color: rgba(61, 54, 54, 0.75); box-shadow: 5px 5px rgba(61, 54, 54, 0.5); }
问题原因与解决方案
问题根源
- CSS优先级与继承问题:
touch-button-click类未继承position: relative属性,导致JS中设置的top/left在红色状态下不生效; - 样式与逻辑耦合:直接操作内联样式,未统一处理阴影的移除与恢复逻辑;
- 缺少边界处理:鼠标移出元素时未恢复按压状态。
修复步骤
- 优化CSS结构:合并重复样式,确保激活状态继承基础属性:
#touch-buttons-grid { width: 90%; height: 200px; margin: 10px auto; margin-top: 20px; background-color: rgba(220, 200, 10, 0.5); border-radius: 10px; display: grid; grid-template-columns: repeat(3, 30%); align-items: center; justify-content: center; z-index: 1; } .touch-button, .touch-button-click, .touch-button-spots { width: 40%; height: 50px; margin: 5px auto; padding: 5px; border-radius: 10px; font-size: 20px; text-align: center; z-index: 5; position: relative; } .touch-button { background-color: rgba(60, 95, 240, 0.5); box-shadow: 5px 5px rgba(60, 95, 240, 0.25); } .touch-button-click { background-color: rgba(220, 41, 10, 1); box-shadow: 5px 5px rgba(220, 41, 10, 0.5); } .touch-button-spots { width: 50%; height: 60px; background-color: rgba(61, 54, 54, 0.75); box-shadow: 5px 5px rgba(61, 54, 54, 0.5); } /* 添加按压状态统一样式 */ .touch-button.pressed, .touch-button-click.pressed { box-shadow: none; top: 5px; left: 5px; }
- 简化JS逻辑:用类切换替代直接操作样式,补充边界事件:
const touchButtons = document.querySelectorAll(".touch-button"); function toggleTouchButtonColor(event) { // 用toggle简化类切换逻辑 event.target.classList.toggle("touch-button-click"); event.target.classList.toggle("touch-button"); } function mouseDownTouchButton(event) { event.target.classList.add("pressed"); } function resetTouchButtonState(event) { event.target.classList.remove("pressed"); } touchButtons.forEach(touchButton => { touchButton.addEventListener("mousedown", mouseDownTouchButton); touchButton.addEventListener("mouseup", resetTouchButtonState); // 补充mouseleave事件,防止鼠标移出后保持按压状态 touchButton.addEventListener("mouseleave", resetTouchButtonState); touchButton.addEventListener("click", toggleTouchButtonColor); });
最终效果
- 点击切换颜色功能正常;
- 无论处于蓝色还是红色状态,mousedown时都会移除阴影并偏移位置,mouseup/mouseleave时自动恢复对应状态的样式;
- 代码结构更简洁,样式与逻辑分离,便于后续维护。
内容的提问来源于stack exchange,提问作者Jonathan Isozaki
相关产品推荐
相关产品推荐

