【html系列】如何在网页中实现点击生成带有重力和碰撞效果的 Emoji

在这个教程中,我们将展示如何使用 HTML 和 JavaScript 创建一个简单的网页应用程序。当用户点击页面时,会在点击位置生成随机数量的 emoji 表情,并为这些表情添加重力和碰撞效果。最终的效果类似于一个小游戏,每个点击都会产生有趣的动画效果。

项目概述

我们的目标是在单个 HTML 文件中完成所有的工作,包括 HTML 结构、CSS 样式和 JavaScript 脚本。以下是具体的步骤:

  1. HTML 结构:创建基本的 HTML 页面结构。
  2. CSS 样式:设置页面样式,使内容居中并隐藏滚动条。
  3. JavaScript 功能
    • 监听点击事件。
    • 在点击位置生成随机数量的 emoji 表情。
    • 添加重力效果,使 emoji 向下移动。
    • 检测并处理 emoji 之间的碰撞。

步骤一:创建 HTML 结构

首先,我们需要创建一个基本的 HTML 页面结构。打开你喜欢的代码编辑器(如 VSCode),新建一个名为 index.html 的文件,并输入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Emoji Gravity and Collision</title>
<style>
/* CSS styles will go here */
</style>
</head>
<body>
<div id="info">单击鼠标召唤emoji</div>
<script>
// JavaScript code will go here
</script>
</body>
</html>

步骤二:添加 CSS 样式

接下来,我们将在 <style> 标签中添加一些 CSS 样式来美化页面。这些样式将帮助我们隐藏默认的边距、滚动条,并使提示信息居中显示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<style>
body {
margin: 0; /* Remove default margin */
overflow: hidden; /* Hide scrollbars */
font-family: Arial, sans-serif; /* Set font family */
display: flex; /* Use flexbox layout */
justify-content: center; /* Center horizontally */
align-items: center; /* Center vertically */
height: 100vh; /* Full viewport height */
background-color: #f0f0f0; /* Light gray background */
}
#info {
position: absolute; /* Position absolutely */
top: 20px; /* Distance from top */
left: 50%; /* Center horizontally */
transform: translateX(-50%); /* Adjust for element width */
color: #333; /* Text color */
z-index: 10; /* Ensure above other elements */
}
.emoji {
position: absolute; /* Position absolutely */
width: 40px; /* Width of emoji container */
height: 40px; /* Height of emoji container */
text-align: center; /* Center text horizontally */
line-height: 40px; /* Center text vertically */
font-size: 2em; /* Font size */
user-select: none; /* Prevent text selection */
}
</style>

步骤三:编写 JavaScript 代码

最后,我们将在 <script> 标签中编写 JavaScript 代码来实现核心功能。以下是完整的 JavaScript 代码及其详细注释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<script>
const emojis = ['😊', '😎', '😍', '🤔', '😂', '🥳', '🤩', '😃']; // Array of emojis
const gravity = 0.5; // Gravity constant
let emojisOnScreen = []; // Array to store emoji objects

document.addEventListener('click', (event) => { // Listen for click events
const numEmojis = Math.floor(Math.random() * 5) + 3; // Random number between 3 and 7
for (let i = 0; i < numEmojis; i++) { // Loop to create multiple emojis
createEmoji(event.clientX, event.clientY); // Create an emoji at the click position
}
});

function createEmoji(x, y) { // Function to create a new emoji
const emojiDiv = document.createElement('div'); // Create a div element
emojiDiv.classList.add('emoji'); // Add class for styling
emojiDiv.textContent = emojis[Math.floor(Math.random() * emojis.length)]; // Set random emoji
emojiDiv.style.left = `${x}px`; // Set x position
emojiDiv.style.top = `${y}px`; // Set y position
document.body.appendChild(emojiDiv); // Append to body

const emojiObj = { // Object to hold emoji data
element: emojiDiv, // Reference to the DOM element
xVelocity: (Math.random() - 0.5) * 10, // Initial x velocity
yVelocity: -10 - Math.random() * 5, // Initial y velocity
x: x, // Current x position
y: y // Current y position
};

emojisOnScreen.push(emojiObj); // Add to array of emojis on screen
}

function updateEmojis() { // Function to update all emojis
emojisOnScreen.forEach((emoji, index) => { // Iterate over each emoji
emoji.yVelocity += gravity; // Apply gravity to y velocity
emoji.x += emoji.xVelocity; // Update x position
emoji.y += emoji.yVelocity; // Update y position

emoji.element.style.left = `${emoji.x}px`; // Update x position in CSS
emoji.element.style.top = `${emoji.y}px`; // Update y position in CSS

checkCollision(emoji, index); // Check for collisions

if (emoji.y > window.innerHeight || emoji.x < 0 || emoji.x > window.innerWidth) { // If emoji is out of bounds
document.body.removeChild(emoji.element); // Remove from DOM
emojisOnScreen.splice(index, 1); // Remove from array
}
});
}

function checkCollision(currentEmoji, currentIndex) { // Function to check collisions
emojisOnScreen.forEach((otherEmoji, otherIndex) => { // Iterate over each emoji
if (currentIndex !== otherIndex) { // Skip self-collision
const dx = currentEmoji.x - otherEmoji.x; // Difference in x positions
const dy = currentEmoji.y - otherEmoji.y; // Difference in y positions
const distance = Math.sqrt(dx * dx + dy * dy); // Calculate distance

if (distance < 40) { // If distance is less than 40 pixels (assuming each emoji is 40x40 pixels)
currentEmoji.xVelocity *= -1; // Reverse x velocity
currentEmoji.yVelocity *= -1; // Reverse y velocity
otherEmoji.xVelocity *= -1; // Reverse x velocity of other emoji
otherEmoji.yVelocity *= -1; // Reverse y velocity of other emoji
}
}
});
}

setInterval(updateEmojis, 20); // Call updateEmojis every 20 milliseconds
</script>

代码解释

  1. 定义常量和变量

    1
    2
    3
    const emojis = ['😊', '😎', '😍', '🤔', '😂', '🥳', '🤩', '😃']; // Array of emojis
    const gravity = 0.5; // Gravity constant
    let emojisOnScreen = []; // Array to store emoji objects
    • emojis: 包含可用的 emoji 字符数组。
    • gravity: 定义了重力加速度。
    • emojisOnScreen: 存储当前屏幕上的所有 emoji 对象。
  2. 监听点击事件

    1
    2
    3
    4
    document.addEventListener('click', (event) => { // Listen for click events
    const numEmojis = Math.floor(Math.random() * 5) + 3; // Random number between 3 and 7
    for (let i = 0; i < numEmojis; i++) { // Loop to create multiple emojis
    createEmoji(event.clientX, event.clientY); // Create an emoji at the click