用 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
- 初始化变量:获取 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 获取核心交互元素,提前定义功德数状态。
- 核心交互:点击事件处理
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);
});
- 关键技术点拆解
音效重置:clickSound.currentTime = 0 确保连续点击时音效不叠加,每次都是完整的 "敲击声";
动画同步:锤子旋转和木鱼缩放的过渡时长(0.1s)与定时器延迟(100ms)一致,动作协调;
DOM 优化:漂浮文字动画结束后通过 remove()移除,避免页面 DOM 元素过多导致性能问题;
无依赖设计:不使用任何框架,仅原生 API,兼容性覆盖所有现代浏览器。
各位互联网搭子,要是这篇文章成功引起了你的注意,别犹豫,关注、点赞、评论、分享走一波,让我们把这份默契延续下去,一起在知识的海洋里乘风破浪!