You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
}

问题原因与解决方案

问题根源

  1. CSS优先级与继承问题:touch-button-click类未继承position: relative属性,导致JS中设置的top/left在红色状态下不生效;
  2. 样式与逻辑耦合:直接操作内联样式,未统一处理阴影的移除与恢复逻辑;
  3. 缺少边界处理:鼠标移出元素时未恢复按压状态。

修复步骤

  1. 优化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;
}
  1. 简化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 02:14:50