HTML&CSS&JS:赛博木鱼

用 HTML + CSS + JS 打造一个禅意十足的互动小应用------赛博木鱼, 本文将拆解其核心实现逻辑,带你从 0 到 1 理解 "敲木鱼" 背后的技术细节。


大家复制代码时,可能会因格式转换出现错乱,导致样式失效。建议先少量复制代码进行测试,若未能解决问题,私信回复源码两字,我会发送完整的压缩包给你。

演示效果

HTML&CSS

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>赛博木鱼</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #121212;
            color: #FFFFFF;
            font-family: 'Kaiti SC', 'PingFang SC', sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            overflow: hidden;
        }

        .title-container {
            text-align: center;
            margin-bottom: 20px;
        }

        .main-title {
            color: #FFFFFF;
            font-size: 6vw;
            font-family: 'Kaiti SC', sans-serif;
            background: linear-gradient(180deg,
                rgba(255, 176, 103, 0.05) 0%,
                rgba(115, 55, 0, 0.02) 100%);
            background-clip: text;
            margin: 0;
            line-height: 1;
        }

        .score-container {
            text-align: center;
            margin: 20px 0;
        }

        .score {
            font-size: 10vh;
            font-family: 'PingFang SC', sans-serif;
            font-weight: 900;
            margin: 0;
        }

        .description {
            font-size: 5vh;
            font-family: 'PingFang SC', sans-serif;
            margin-top: 10px;
        }

        .wooden-fish-container {
            position: relative;
            width: 300px;
            height: 250px;
            display: flex;
            justify-content: center;
            align-items: center;
            margin: 30px 0;
        }

        .wooden-fish {
            width: 284px;
            height: 236px;
            transition: transform 0.1s ease;
        }

        .mallet {
            position: absolute;
            top: 20px;
            right: 20px;
            width: 119px;
            height: 69px;
            transition: transform 0.1s ease;
            z-index: 10;
        }

        .floating-text {
            position: absolute;
            top: -50px;
            left: 50%;
            transform: translateX(-50%);
            font-family: 'PingFang SC', sans-serif;
            font-size: 1.5em;
            color: #FFFFFF;
            opacity: 0;
            pointer-events: none;
            animation: floatUp 0.4s ease-out forwards;
        }

        @keyframes floatUp {
            0% {
                opacity: 1;
                transform: translateX(-50%) translateY(0);
            }
            100% {
                opacity: 0;
                transform: translateX(-50%) translateY(-60px);
            }
        }

        .bottom-text {
            font-family: 'Kaiti SC', sans-serif;
            font-size: 1.2em;
            text-align: center;
            margin-top: 30px;
        }
    </style>
</head>
<body>
    <div class="title-container">
        <div class="main-title">赛博木鱼</div>
    </div>

    <div class="score-container">
        <div class="score" id="score">0</div>
        <div class="description">功德</div>
    </div>

    <div class="wooden-fish-container" id="fishContainer">
        <img src="https://img.alicdn.com/imgextra/i3/O1CN012CO0YU1VSfNs506ZS_!!6000000002652-2-tps-284-236.png"
             alt="木鱼" class="wooden-fish" id="woodenFish">
        <img src="https://img.alicdn.com/imgextra/i1/O1CN01tKb5Et1aSjWRjCHK3_!!6000000003329-2-tps-119-69.png"
             alt="锤子" class="mallet" id="mallet">
    </div>

    <div class="bottom-text">轻敲木鱼,细悟赛博真经。</div>

    <audio id="clickSound" preload="auto">
        <source src="https://qianwen.alicdn.com/resource/qiaomuyu.mp3" type="audio/mpeg">
    </audio>

    <script>
        let score = 0;
        const scoreElement = document.getElementById('score');
        const woodenFish = document.getElementById('woodenFish');
        const mallet = document.getElementById('mallet');
        const fishContainer = document.getElementById('fishContainer');
        const clickSound = document.getElementById('clickSound');

        fishContainer.addEventListener('click', function(e) {
            // 播放音效
            clickSound.currentTime = 0;
            clickSound.play();

            // 锤子旋转动画
            mallet.style.transform = 'rotate(-25deg)';
            setTimeout(() => {
                mallet.style.transform = 'rotate(0deg)';
            }, 100);

            // 木鱼放大动画
            woodenFish.style.transform = 'scale(1.1)';
            setTimeout(() => {
                woodenFish.style.transform = 'scale(1)';
            }, 100);

            // 增加分数
            score++;
            scoreElement.textContent = score;

            // 创建漂浮文字
            const floatingText = document.createElement('div');
            floatingText.className = 'floating-text';
            floatingText.textContent = '功德+1';
            fishContainer.appendChild(floatingText);

            // 移除漂浮文字
            setTimeout(() => {
                floatingText.remove();
            }, 400);
        });
    </script>
</body>
</html>

HTML

  • title-container:标题容器:承载 "赛博木鱼" 主标题,通过居中布局突出视觉核心
  • score-container:分数展示区:包含 "功德数" 和 "功德" 描述,是用户交互的核心反馈载体
  • wooden-fish-container:交互核心容器
  • wooden-fish:木鱼图片:通过 CDN 引入资源,无需本地存储,是点击交互的视觉核心
  • mallet:锤子图片:绝对定位在木鱼右上方,点击时通过旋转动画模拟 "敲击" 动作
  • clickSound:音效载体:预加载木鱼敲击音效(preload="auto"),点击时触发播放,增强沉浸感
  • floating-text:动态生成元素:点击时创建 "功德 + 1" 漂浮文字,完成交互反馈闭环

CSS

  • .mallet:点击时锤子绕右上角旋转 25 度,模拟 "敲下去" 的动作,100 毫秒快速回弹
  • .wooden-fish:点击时木鱼轻微放大 1.1 倍,模拟 "被敲击后的震动",与锤子动作同步:
  • .floating-text:自动向上淡出,营造"功德升天"的视觉效果。

JavaScript

  1. 初始化变量:获取 DOM 元素与状态
javascript 复制代码
let score = 0; // 功德数初始值
const scoreElement = document.getElementById('score'); // 分数显示元素
const woodenFish = document.getElementById('woodenFish'); // 木鱼元素
const mallet = document.getElementById('mallet'); // 锤子元素
const fishContainer = document.getElementById('fishContainer'); // 交互容器
const clickSound = document.getElementById('clickSound'); // 音效元素

通过 getElementById 获取核心交互元素,提前定义功德数状态。

  1. 核心交互:点击事件处理
javascript 复制代码
fishContainer.addEventListener('click', function(e) {
    // 1. 播放敲击音效(每次点击从头播放,支持连续敲击)
    clickSound.currentTime = 0;
    clickSound.play();

    // 2. 锤子旋转动画:敲下→回弹
    mallet.style.transform = 'rotate(-25deg)';
    setTimeout(() => {
        mallet.style.transform = 'rotate(0deg)';
    }, 100);

    // 3. 木鱼缩放动画:放大→还原
    woodenFish.style.transform = 'scale(1.1)';
    setTimeout(() => {
        woodenFish.style.transform = 'scale(1)';
    }, 100);

    // 4. 功德数累加与更新
    score++;
    scoreElement.textContent = score;

    // 5. 生成"功德+1"漂浮文字
    const floatingText = document.createElement('div');
    floatingText.className = 'floating-text';
    floatingText.textContent = '功德+1';
    fishContainer.appendChild(floatingText);

    // 6. 动画结束后移除文字(避免DOM堆积)
    setTimeout(() => {
        floatingText.remove();
    }, 400);
});
  1. 关键技术点拆解

音效重置:clickSound.currentTime = 0 确保连续点击时音效不叠加,每次都是完整的 "敲击声";

动画同步:锤子旋转和木鱼缩放的过渡时长(0.1s)与定时器延迟(100ms)一致,动作协调;

DOM 优化:漂浮文字动画结束后通过 remove()移除,避免页面 DOM 元素过多导致性能问题;

无依赖设计:不使用任何框架,仅原生 API,兼容性覆盖所有现代浏览器。


各位互联网搭子,要是这篇文章成功引起了你的注意,别犹豫,关注、点赞、评论、分享走一波,让我们把这份默契延续下去,一起在知识的海洋里乘风破浪!

相关推荐
mldong4 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排5 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60615 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角6 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!6 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰7 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi8 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen9 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马10 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu10 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss