Datawhale-AI冬令营二期

发布于:2025-02-11 ⋅ 阅读:(44) ⋅ 点赞:(0)

说明:这是在MarsCode平台经过调试的版本,最初按照Prompt并没有直接实现。

一、番茄时钟

在这里插入图片描述

(1)输入Prompt

请你基于html、tailwind css和javascript,帮我设计一个“番茄时钟”。要求UI简洁美观大方,同时具有呼吸感,点击开始计时、点击暂停计时和重置计时的功能能够完美实现

(2)创建 HTML 文件

这个HTML页面是一个简单的番茄时钟界面,包含:
一个标题:番茄钟。
一个显示计时器倒计时的区域(id=“timer”)。
三个按钮:开始、暂停和重置。
通过TailwindCSS进行布局和样式的设计,并使用外部JavaScript文件(script.js)来处理逻辑。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>番茄时钟</title>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 flex items-center justify-center h-screen">
  <div class="bg-white p-8 roundedshadow-md w-96">
        <h1 class="text-6xl font-bold text-gray-800">番茄钟</h1>
    
    <div class="flex flex-col mt-4">
        <div id="timer" class="text-6xl font-bold text-gray-800"></div>
    </div>
    <div class="flex mt-4">
        <button id="start" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded mr-2">开始</button>
        <button id="pause" class="bg-yellow-500 hover:bg-yellow-600 text-white font-bold py-2 px-4 rounded mr-2">暂停</button>
        <button id="reset" class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded">重置</button>
    </div>
    <script src="script.js"></script>
  </div>
</body>
</html>

解析1:HTML结构

<!DOCTYPE html>定义了文档类型,表示这是一个HTML5文档。
<html lang="en"> 指定文档语言为英语,方便搜索引擎和浏览器理解。
<head>
    <meta charset="UTF-8">定义文档字符集为UTF-8,确保支持中文和其他字符集。
    <meta name="viewport" content="width=device-width, initial-scale=1.0">设置视口的宽度与设备屏幕宽度一致,使网页在移动设备上自适应显示。
    <title>番茄时钟</title>定义页面的标题栏显示文本。
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">引入了TailwindCSS框架,它是一个功能强大的CSS框架,简化了HTML中的样式编写。
    <script src="https://cdn.tailwindcss.com"></script>引入TailwindCSS的JavaScript支持库。
</head>
<body class="bg-gray-100 flex items-center justify-center h-screen">
bg-gray-100:设置背景颜色为浅灰色(TailwindCSS类)。
flex:使用Flexbox布局,使子元素在页面中居中对齐。
items-center:垂直居中子元素。
justify-center:水平居中子元素。
h-screen:设置页面高度为100vh(视口高度),即使页面充满屏幕。

解析2:计时器内容

<div class="bg-white p-8 roundedshadow-md w-96">
	bg-white:设置背景为白色。
	p-8:设置内边距为2rem,使内部内容距离边缘有一定的间距。
	rounded shadow-md:为该元素添加圆角和阴影,使其看起来更美观
	w-96:设置宽度为24rem(96的单位是rem,TailwindCSS默认配置中的24rem)。
    <h1 class="text-6xl font-bold text-gray-800">番茄钟</h1>
    bg-white:设置背景为白色。
	p-8:设置内边距为2rem,使内部内容距离边缘有一定的间距。
	rounded shadow-md:为该元素添加圆角和阴影,使其看起来更美观
	w-96:设置宽度为24rem(96的单位是rem,TailwindCSS默认配置中的24rem)。
    <div class="flex flex-col mt-4">
    flex flex-col:使用Flexbox布局,将子元素垂直排列。
	mt-4:设置顶部外边距为1rem,让计时器与标题之间有一定间距。
        <div id="timer" class="text-6xl font-bold text-gray-800"></div>
        text-6xl:设置字体大小为6xl(约为4rem),使计时器的数字更大。
		font-bold:加粗文本。
		text-gray-800:设置文本颜色为深灰色。
    </div>

解析3:按钮区域

<div class="flex mt-4">
flex mt-4:使用Flexbox布局,并设置顶部外边距为1rem,使按钮区域与计时器区域之间有间隔。
	<button id="start" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded mr-2">开始</button>
	<button id="pause" class="bg-yellow-500 hover:bg-yellow-600 text-white font-bold py-2 px-4 rounded mr-2">暂停</button>
	<button id="reset" class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded">重置</button>
	每个按钮 (<button>) 的样式:
	bg-green-500、bg-yellow-500、bg-red-500:分别设置按钮的背景色为绿色、黄色、红色。
	hover:bg-green-600、hover:bg-yellow-600、hover:bg-red-600:设置当鼠标悬停时按钮背景色变为深绿色、深黄色、深红色。
	text-white:设置按钮文字为白色。
	font-bold:加粗按钮文字。
	py-2 px-4:设置按钮的内边距,py-2表示上下内边距为0.5rem,px-4表示左右内边距为1rem。
	rounded:为按钮添加圆角效果。
	mr-2:为每个按钮添加右边距,使它们之间有间隔。
</div>

解析4:脚本引用

<script src="script.js"></script>
script.js:外部JavaScript文件,负责处理番茄时钟的逻辑,包括开始、暂停、重置等功能。你需要实现该文件中的JavaScript代码来控制计时器和按钮的交互。

(3)使用JavaScript实现时钟功能

该代码实现了一个简单的番茄钟功能,可以启动、暂停和重置计时器。
计时器每秒更新一次,并在计时结束时弹出提示框。
通过按钮交互,用户可以控制计时器的开始、暂停和重置。

let timer;
let isRunning = false;
let timeLeft = 1500; // 25 minutes in seconds

function updateTimer() {
    const minutes = Math.floor(timeLeft / 60);
    const seconds = timeLeft % 60;
    document.getElementById('timer').textContent = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
}

function startTimer() {
    if (!isRunning) {
        isRunning = true;
        timer = setInterval(() => {
            if (timeLeft > 0) {
                timeLeft--;
                updateTimer();
            } else {
                clearInterval(timer);
                isRunning = false;
                alert('时间到!');
            }
        }, 1000);
    }
}

function pauseTimer() {
    if (isRunning) {
        clearInterval(timer);
        isRunning = false;
    }
}

function resetTimer() {
    clearInterval(timer);
    isRunning = false;
    timeLeft = 1500;
    updateTimer();
}

document.getElementById('start').addEventListener('click', startTimer);
document.getElementById('pause').addEventListener('click', pauseTimer);
document.getElementById('reset').addEventListener('click', resetTimer);

updateTimer();

解析1:变量声明

let timer;//用于存储定时器的ID,便于在暂停或重置时清除定时器。
let isRunning = false;//布尔值,标志计时器是否正在运行。如果计时器正在运行,则为 true,否则为 false。
let timeLeft = 1500; // 25 minutes in seconds
//表示剩余时间,单位是秒。初始值为 1500 秒,即 25 分钟。

解析2:updateTimer 函数

function updateTimer() {//每次更新时间时调用。该函数将 timeLeft 转换为分钟和秒数,并将其格式化成 mm:ss 的形式。
    const minutes = Math.floor(timeLeft / 60);//计算剩余时间的分钟部分。
    const seconds = timeLeft % 60;//计算剩余时间的秒数。
    document.getElementById('timer').textContent = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;//将格式化后的时间显示在页面上,<div> 或 <span> 元素的内容更新为分钟和秒数的格式。如果秒数小于 10,则在秒数前面加上零。
}

解析3:startTimer 函数

function startTimer() {//启动计时器的功能
    if (!isRunning) {//它首先检查计时器是否已经在运行,如果没有,则:
        isRunning = true;//将计时器状态设置为正在运行。
        timer = setInterval(() => {//使用 setInterval 每秒执行一次回调函数。
            if (timeLeft > 0) {//如果剩余时间 timeLeft > 0,则每秒减少 1 秒并更新显示的时间。
                timeLeft--;
                updateTimer();
            } else {//如果剩余时间 timeLeft = 0,则停止计时器 (clearInterval(timer)),将 isRunning 设置为 false,并弹出一个提示框提示 "时间到!"
                clearInterval(timer);
                isRunning = false;
                alert('时间到!');
            }
        }, 1000);
    }
}

解析4:pauseTimer 函数——暂停计时器

function pauseTimer() {
    if (isRunning) {//如果计时器正在运行(isRunning 为 true),则清除定时器(clearInterval(timer))并将 isRunning 设置为 false,表示计时器已经停止。
        clearInterval(timer);
        isRunning = false;
    }
}

解析5:resetTimer 函数——重置计时器

function resetTimer() {
    clearInterval(timer);//无论计时器是否正在运行,都会停止定时器(clearInterval(timer)),将 isRunning 设置为 false,将 timeLeft 重置为 1500 秒(25 分钟),并更新显示的时间。

    isRunning = false;
    timeLeft = 1500;
    updateTimer();
}

解析6:事件监听

document.getElementById('start').addEventListener('click', startTimer);
document.getElementById('pause').addEventListener('click', pauseTimer);
document.getElementById('reset').addEventListener('click', resetTimer);
//为三个按钮添加事件监听器:
//点击 开始 按钮时调用 startTimer 函数启动计时器。
//点击 暂停 按钮时调用 pauseTimer 函数暂停计时器。
//点击 重置 按钮时调用 resetTimer 函数重置计时器。

解析7:初始调用

updateTimer();
//在页面加载时,调用 updateTimer 函数,初始化显示的时间(25 分钟)。

二、井字棋

在这里插入图片描述

(1)输入Prompt

Prompt:请你基于html、tailwind css和javascript,帮我设计一个“井字棋游戏”。要求UI简洁美观大方,同时具有呼吸感,人类玩家以及电脑玩家放置棋子,游戏胜负平局判定条件能够完美实现

(2)创建HTML文件

这段 HTML 代码创建了一个简单的 Tic Tac Toe(井字棋)游戏的前端界面,使用了 TailwindCSS来实现响应式和美观的布局。它包含了游戏标题、3x3 的棋盘和一个用于重置游戏的按钮。最终的游戏逻辑(如玩家的轮流、胜利条件判断、重置功能等)会通过用外部 JavaScript(script.js) 文件来处理。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tic Tac Toe</title>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 flex flex-col items-center justify-center h-screen">
    <h1 class="text-3xl font-bold mb-4">Tic Tac Toe</h1>
    <div id="game-board" class="grid grid-cols-3 gap-4 w-full max-w-xs">
        <!-- 棋盘单元格 -->
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
    </div>
    <div class="mt-4 flex flex-col items-center">
        <p id="game-result" class="text-xl font-bold"></p>
        <button id="reset-button" class="mt-4 bg-blue-500 text-white px-4 py-2 rounded">Reset</button>
    </div>
    <script src="script.js"></script>
</body>
</html>

解析1:HTML结构

<!DOCTYPE html>声明了文档类型为 HTML5,告诉浏览器该文件遵循 HTML5 标准解析。
<html lang="en">开始 HTML 文档,并设置 lang="en" 属性,表示文档内容是英文(这有助于搜索引擎优化和屏幕阅读器)。
<head>
    <meta charset="UTF-8">设置字符编码为 UTF-8,支持多种语言字符,避免乱码。
    <meta name="viewport" content="width=device-width, initial-scale=1.0">响应式设计的关键。它让页面在移动设备上能够自适应屏幕宽度,initial-scale=1.0 表示初始缩放比例为 1。
    <title>Tic Tac Toe</title>设置网页的标题,这个标题会显示在浏览器的标签栏中。
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">引入 TailwindCSS 样式表,这是一个流行的工具类 CSS 框架,提供许多实用的类来快速设计网页。
    <script src="https://cdn.tailwindcss.com"></script>引入 TailwindCSS 的 JavaScript 文件,允许使用 TailwindCSS的一些动态功能(例如,CSS配置和优化)。
</head>结束 <head> 部分。<head> 部分通常用于包含页面元数据(如字符集、视口设置、样式表等)。
<body class="bg-gray-100 flex flex-col items-center justify-center h-screen">
bg-gray-100: 背景颜色设置为浅灰色。
flex: 使用 Flexbox 布局。
flex-col: 设置Flexbox方向为纵向排列。
items-center: 垂直居中对齐所有子元素。
justify-center: 水平居中对齐所有子元素。
h-screen: 让页面高度占满整个视口。

解析2:游戏标题和棋盘

    <h1 class="text-3xl font-bold mb-4">Tic Tac Toe</h1>显示游戏的标题 "Tic Tac Toe"。
    <div id="game-board" class="grid grid-cols-3 gap-4 w-full max-w-xs">创建一个 3x3 的网格布局作为棋盘:
    grid: 使用 CSS 网格布局。
	grid-cols-3: 定义棋盘为 3 列。
	gap-4: 设置网格单元格之间的间隔为 4 个单位。
	w-full max-w-xs: 设置棋盘的宽度为全屏,并且最大宽度为 xs(适应小屏幕设备)。
        <!-- 棋盘单元格 -->
        每个棋盘单元格由一个 <button> 元素表示,使用了以下的类:
		w-20 h-20: 设置按钮的宽度和高度为 20 个单位。
		bg-white: 设置按钮背景为白色。
		text-5xl: 设置按钮内文本的大小为 5x大。
		font-bold: 设置文本加粗。
		border-2 border-gray-300: 设置按钮的边框为 2px 宽,颜色为浅灰色。
		focus:outline-none: 去除按钮获得焦点时的默认样式。
		这些按钮代表棋盘中的每个格子,这行代码重复了 9 次,表示棋盘上的 9 个格子。点击后将用于放置玩家的 X 或 O。
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
        <button class="w-20 h-20 bg-white text-5xl font-bold border-2 border-gray-300 focus:outline-none"></button>
    </div>结束 div 元素,关闭棋盘容器。
    <div class="mt-4 flex flex-col items-center">创建一个新的 div 元素,用来放置游戏结果和重置按钮。
    mt-4: 设置上方外边距为 4 个单位,确保内容之间有空隙。
	flex: 使用 Flexbox 布局。
	flex-col: 设置子元素纵向排列。
	items-center: 在横向上居中对齐子元素。

解析3:游戏结果和重置按钮

		<p id="game-result" class="text-xl font-bold"></p>显示游戏的结果(例如 "Player X wins!" 或 "It's a draw!")。
		text-xl: 设置文本大小为 xl。
		font-bold: 设置文本为加粗。
        <button id="reset-button" class="mt-4 bg-blue-500 text-white px-4 py-2 rounded">Reset</button>创建一个重置按钮,用于重新开始游戏:
        mt-4: 设置按钮上方的外边距为 4 个单位。
		bg-blue-500 text-white: 设置按钮背景色为蓝色,文字颜色为白色。
		px-4 py-2: 设置按钮的内边距(水平 4,垂直 2)。
		rounded: 设置按钮的边角为圆角。
	</div>结束外部 div 元素,关闭结果和重置按钮的容器。

解析4:脚本引用

	<script src="script.js"></script>引入外部的 script.js 文件。这个文件将包含实现 Tic Tac Toe 游戏逻辑的 JavaScript 代码(该文件负责处理游戏逻辑(如玩家的轮流、胜利判断、重置功能等)
</body>结束 body 部分。
</html>结束整个 HTML 文档。
总结

(2)使用JavaScript实现游戏功能

这段代码实现了一个完整的井字棋游戏,支持玩家与电脑交替下棋,判断胜负或平局,并且可以重置游戏。电脑的下棋方式是随机选择空白单元格进行下棋。

// 初始化棋盘和当前玩家
let board = ['', '', '', '', '', '', '', '', ''];
let currentPlayer = 'X';

// 获取所有棋盘单元格
const cells = document.querySelectorAll('#game-board button');

// 为每个单元格添加点击事件监听器
cells.forEach((cell, index) => {
    cell.addEventListener('click', () => makeMove(index));
});

// 获取游戏结果显示元素和重置按钮
const gameResult = document.getElementById('game-result');
const resetButton = document.getElementById('reset-button');

// 为重置按钮添加点击事件监听器
resetButton.addEventListener('click', resetBoard);

// 玩家下棋
function makeMove(index) {
    if (board[index] === '') {
        board[index] = currentPlayer;
        cells[index].textContent = currentPlayer;
        if (checkWin(currentPlayer)) {
            gameResult.textContent = 'Player ' + currentPlayer + ' wins!';
            gameResult.style.fontSize = '18px'; // 调小字体
            resetButton.disabled = false;
        } else if (checkDraw()) {
            gameResult.textContent = 'It\'s a draw!';
            gameResult.style.fontSize = '18px'; // 调小字体
            resetButton.disabled = false;
        } else {
            currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
            if (currentPlayer === 'O') {
                setTimeout(makeComputerMove, 500);
            }
        }
    }
}

// 电脑下棋
function makeComputerMove() {
    const emptyCells = board.reduce((acc, cell, index) => {
        if (cell === '') acc.push(index);
        return acc;
    }, []);

    if (emptyCells.length > 0) {
        const randomIndex = Math.floor(Math.random() * emptyCells.length);
        const index = emptyCells[randomIndex];
        makeMove(index);
    }
}

// 检查是否获胜
function checkWin(player) {
    const winPatterns = [
        [0, 1, 2], [3, 4, 5], [6, 7, 8], // 行
        [0, 3, 6], [1, 4, 7], [2, 5, 8], // 列
        [0, 4, 8], [2, 4, 6] // 对角线
    ];

    return winPatterns.some(pattern => {
        return pattern.every(index => board[index] === player);
    });
}

// 检查是否平局
function checkDraw() {
    return board.every(cell => cell !== '');
}

// 重置棋盘
function resetBoard() {
    board = ['', '', '', '', '', '', '', '', ''];
    cells.forEach(cell => cell.textContent = '');
    currentPlayer = 'X';
    gameResult.textContent = '';
    resetButton.disabled = true;
}

解析1:初始化棋盘和当前玩家

let board = ['', '', '', '', '', '', '', '', ''];//board 数组表示棋盘,包含 9 个元素(每个元素代表一个棋盘单元格),初始时每个单元格为空字符串(即 ' ')。
let currentPlayer = 'X';//用来记录当前玩家,初始为 'X'(玩家一)。

解析2:获取所有棋盘单元格

const cells = document.querySelectorAll('#game-board button');通过 document.querySelectorAll 获取所有按钮元素(代表棋盘的单元格)。这些按钮放在一个 ID 为 game-board 的容器内。

解析3:为每个单元格添加点击事件监听器

cells.forEach((cell, index) => {
    cell.addEventListener('click', () => makeMove(index));
    遍历每个单元格,为每个按钮添加一个点击事件监听器,点击时会调用 makeMove(index) 函数,其中 index 是单元格的索引。
});

解析4: 获取游戏结果显示元素和重置按钮

//获取显示游戏结果的元素(ID 为 game-result)和重置按钮元素(ID 为 reset-button)。
const gameResult = document.getElementById('game-result');
const resetButton = document.getElementById('reset-button');

解析5:为重置按钮添加点击事件监听器

//为重置按钮添加点击事件,当点击时调用 resetBoard() 函数,重新开始一局游戏。
resetButton.addEventListener('click', resetBoard);

解析6:玩家下棋

//用来处理玩家的每一步。玩家点击空白单元格时,当前玩家的标记('X' 或 'O')会被放入对应的 board 索引位置,同时更新显示。
function makeMove(index) {
    if (board[index] === '') {
        board[index] = currentPlayer;
        cells[index].textContent = currentPlayer;
        if (checkWin(currentPlayer)) {//检查当前玩家是否获胜,若获胜则显示相应信息,并启用重置按钮。
            gameResult.textContent = 'Player ' + currentPlayer + ' wins!';
            gameResult.style.fontSize = '18px'; // 调小字体
            resetButton.disabled = false;
        } else if (checkDraw()) {//检查是否平局,若是则显示平局信息。
            gameResult.textContent = 'It\'s a draw!';
            gameResult.style.fontSize = '18px'; // 调小字体
            resetButton.disabled = false;
        } else {//若没有获胜且没有平局,切换玩家
            currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
            if (currentPlayer === 'O') {//若是电脑的回合,则通过 setTimeout 调用 makeComputerMove() 模拟电脑下棋,延迟 500 毫秒。
                setTimeout(makeComputerMove, 500);
            }
        }
    }
}

解析7:电脑下棋

//用来模拟电脑下棋。首先通过 reduce 方法找到所有空白单元格的索引,存储在 emptyCells 数组中。
function makeComputerMove() {
    const emptyCells = board.reduce((acc, cell, index) => {
        if (cell === '') acc.push(index);
        return acc;
    }, []);

    if (emptyCells.length > 0) {//随机选择一个空白单元格,调用 makeMove(index) 让电脑下棋。
        const randomIndex = Math.floor(Math.random() * emptyCells.length);
        const index = emptyCells[randomIndex];
        makeMove(index);
    }
}

解析8:检查是否获胜

//检查给定玩家是否获胜。它定义了所有可能的获胜组合(行、列、对角线),通过 some 和 every 方法判断是否存在一个获胜组合。
function checkWin(player) {
    const winPatterns = [
        [0, 1, 2], [3, 4, 5], [6, 7, 8], // 行
        [0, 3, 6], [1, 4, 7], [2, 5, 8], // 列
        [0, 4, 8], [2, 4, 6] // 对角线
    ];

    return winPatterns.some(pattern => {
        return pattern.every(index => board[index] === player);
    });
}

解析9:检查是否平局

//检查是否所有单元格都已填满,且没有获胜者,从而确定是否平局。
function checkDraw() {
    return board.every(cell => cell !== '');
}

解析10:重置棋盘

//用于重置棋盘。将 board 数组清空,并将所有按钮文本清空,同时将当前玩家设置回 'X',清除游戏结果,并禁用重置按钮。
function resetBoard() {
    board = ['', '', '', '', '', '', '', '', ''];
    cells.forEach(cell => cell.textContent = '');
    currentPlayer = 'X';
    gameResult.textContent = '';
    resetButton.disabled = true;
}

三、个人成就系统

在这里插入图片描述

Prompt:请按照以下步骤帮助我创建一个“人生成就系统”
步骤1:创建基本的HTML页面结构
请帮我创建一个基本的HTML页面,包含<!DOCTYPE html>声明,<html>、<head>和<body>标签在<head>中添加页面标题“人生成就系统”,并引入Tailwind CSS的CDN链接。
步骤2:添加页面头部和主容器
在<body>中添加一个导航栏,包含页面标题“人生成就系统”。然后添加一个主容器,用于放置记录成就的表单和展示成就的时间轴。
步骤3:创建成就记录表单
在主容器中添加一个表单,包含以下字段:
-成就标题(文本输入框)
-成就描述(多行文本框)
-成就日期
(日期选择器)
-提交按钮
使用Tailwind CSS进行样式美化。
步骤4:创建时间轴展示区域
在主容器中,表单下方添加一个时间轴区域,用于展示用户记录的成就。时间轴应按日期排序,并以时间流动的方式展示。
步骤5:添加JavaScript逻辑以处理表单提交和时间轴更新使用JavaScript为成就记录表单添加提交事件监听器。提交时,获取表单数据,创建一个新的成就条目并将其添加到时间轴中。确保成就按日期排序。使用Tailwind CSS进行样式美化。
步骤6:美化时间轴样式
使用Tailwind CSS进一步美化时间轴,使其更具视觉吸引力。添加左右交错的时间轴节点,使用不同颜色区分不同年份或类别的成就。
PS.给每一个时间成就事项增加可修改选项

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>人生成就系统</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100">
    <div class="container mx-auto px-4 py-8">
        <!-- 步骤2: 添加页面头部和主容器 -->
        <nav class="bg-blue-600 text-white py-4 px-8 rounded-t-lg shadow-lg">
            <h1 class="text-2xl font-bold">人生成就系统</h1>
        </nav>

        <div class="mt-8">
            <!-- 步骤3: 创建成就记录表单 -->
            <form id="achievement-form" class="bg-white p-6 rounded-lg shadow-lg">
                <h2 class="text-xl font-semibold mb-4">记录新成就</h2>
                
                <label for="title" class="block text-gray-700 mb-2">成就标题</label>
                <input type="text" id="title" class="w-full p-2 border border-gray-300 rounded-lg mb-4" placeholder="请输入成就标题">

                <label for="description" class="block text-gray-700 mb-2">成就描述</label>
                <textarea id="description" class="w-full p-2 border border-gray-300 rounded-lg mb-4" placeholder="请输入成就描述" rows="4"></textarea>

                <label for="date" class="block text-gray-700 mb-2">成就日期</label>
                <input type="date" id="date" class="w-full p-2 border border-gray-300 rounded-lg mb-4">

                <button type="submit" class="w-full bg-blue-600 text-white py-2 rounded-lg" id="submit-button">提交成就</button>
            </form>

            <!-- 步骤4: 创建时间轴展示区域 -->
            <div id="timeline" class="mt-12">
                <h2 class="text-2xl font-semibold mb-4">我的成就时间轴</h2>
                <div id="timeline-content"></div>
            </div>
        </div>
    </div>

    <!-- 步骤5: 添加JavaScript逻辑 -->
    <script>
        // 获取表单和时间轴容器
        const form = document.getElementById('achievement-form');
        const timelineContent = document.getElementById('timeline-content');

        // 创建一个存储所有成就的数组
        let achievements = [];
        let editingIndex = null; // 当前正在编辑的成就索引

        // 监听表单提交事件
        form.addEventListener('submit', function(event) {
            event.preventDefault();

            // 获取表单数据
            const title = document.getElementById('title').value;
            const description = document.getElementById('description').value;
            const date = document.getElementById('date').value;

            // 创建新的成就对象
            const achievement = {
                title,
                description,
                date: new Date(date),  // 转换为 Date 对象
            };

            if (editingIndex === null) {
                // 如果没有在编辑,添加新的成就
                achievements.push(achievement);
            } else {
                // 如果在编辑,更新现有成就
                achievements[editingIndex] = achievement;
                editingIndex = null; // 清空编辑状态
            }

            // 按日期排序成就
            achievements.sort((a, b) => a.date - b.date);

            // 清空当前时间轴并重新渲染
            timelineContent.innerHTML = '';
            achievements.forEach(addAchievementToTimeline);

            // 清空表单
            form.reset();
            document.getElementById('submit-button').textContent = "提交成就"; // 还原按钮文本
        });

        // 将成就添加到时间轴
        function addAchievementToTimeline(achievement, index) {
            const achievementElement = document.createElement('div');
            achievementElement.classList.add('relative', 'mb-8');
            
            // 时间轴左侧和右侧
            const timelineNode = document.createElement('div');
            timelineNode.classList.add('absolute', 'top-0', 'w-2', 'h-full', 'bg-gray-300');
            achievementElement.appendChild(timelineNode);

            // 时间轴节点
            const node = document.createElement('div');
            node.classList.add('w-8', 'h-8', 'bg-blue-600', 'rounded-full', 'absolute', '-left-4', 'top-0');
            achievementElement.appendChild(node);

            // 成就信息
            const info = document.createElement('div');
            info.classList.add('ml-12', 'bg-white', 'p-4', 'rounded-lg', 'shadow-lg', 'w-3/4');
            info.innerHTML = `
                <h3 class="text-xl font-bold">${achievement.title}</h3>
                <p class="text-gray-700">${achievement.description}</p>
                <p class="text-gray-500 mt-2">日期:${achievement.date.toLocaleDateString()}</p>
            `;
            achievementElement.appendChild(info);

            // 添加修改按钮(小巧的圆形按钮)
            const editButton = document.createElement('button');
            editButton.textContent = '✎';
            editButton.classList.add('absolute', 'top-2', 'right-2', 'bg-yellow-500', 'text-white', 'text-sm', 'w-8', 'h-8', 'rounded-full', 'flex', 'items-center', 'justify-center', 'shadow-md', 'hover:bg-yellow-600', 'focus:outline-none');
            editButton.onclick = () => editAchievement(index);
            achievementElement.appendChild(editButton);

            // 将新的成就条目添加到时间轴中
            timelineContent.appendChild(achievementElement);
        }

        // 编辑成就
        function editAchievement(index) {
            const achievement = achievements[index];
            editingIndex = index;  // 设置为正在编辑的成就索引

            // 填充表单数据
            document.getElementById('title').value = achievement.title;
            document.getElementById('description').value = achievement.description;
            document.getElementById('date').value = achievement.date.toISOString().split('T')[0];

            // 更新按钮文本为“更新成就”
            document.getElementById('submit-button').textContent = "更新成就";
        }
    </script>
</body>
</html>

四、工作任务管理系统

在这里插入图片描述

设计理念:为有条理的应对每日工作任务设计工作任务管理系统,由用户列出每一项工作任务并给定计划需时和紧急程度,按照紧急程度顺序列出任务轴,任务轴上的每一个任务卡片可以修改编辑,已完成的任务可以点击完成,并被列为任务轴最下方的“已完成事项”。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>工作任务管理系统</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 font-sans">
    <!-- 页面头部 -->
    <nav class="bg-blue-600 text-white p-4">
        <h1 class="text-3xl font-bold text-center">工作任务管理系统</h1>
    </nav>

    <!-- 主容器 -->
    <div class="container mx-auto p-6">
        <!-- 任务输入表单 -->
        <div class="bg-white p-6 rounded-lg shadow-md mb-6">
            <h2 class="text-2xl font-semibold mb-4">添加任务</h2>
            <form id="taskForm" class="space-y-4">
                <div>
                    <label for="taskTitle" class="block text-sm font-medium text-gray-700">任务标题</label>
                    <input type="text" id="taskTitle" name="taskTitle" class="w-full p-2 border border-gray-300 rounded" required>
                </div>
                <div>
                    <label for="taskDescription" class="block text-sm font-medium text-gray-700">任务描述</label>
                    <textarea id="taskDescription" name="taskDescription" rows="4" class="w-full p-2 border border-gray-300 rounded" required></textarea>
                </div>
                <div>
                    <label for="duration" class="block text-sm font-medium text-gray-700">预计完成时间(分钟)</label>
                    <input type="number" id="duration" name="duration" min="1" class="w-full p-2 border border-gray-300 rounded" required>
                </div>
                <div>
                    <label for="priority" class="block text-sm font-medium text-gray-700">紧急程度 (0-1)</label>
                    <input type="range" id="priority" name="priority" min="0" max="1" step="0.01" class="w-full" required>
                    <span id="priorityValue" class="text-sm font-medium">0</span>
                </div>
                <button type="submit" class="w-full bg-blue-600 text-white py-2 rounded mt-4">添加任务</button>
            </form>
        </div>

        <!-- 时间轴展示 -->
        <div id="taskTimeline" class="space-y-4">
            <!-- 任务将显示在这里 -->
        </div>
    </div>

    <script>
        // 获取DOM元素
        const taskForm = document.getElementById("taskForm");
        const taskTitle = document.getElementById("taskTitle");
        const taskDescription = document.getElementById("taskDescription");
        const duration = document.getElementById("duration");
        const priority = document.getElementById("priority");
        const priorityValue = document.getElementById("priorityValue");
        const taskTimeline = document.getElementById("taskTimeline");

        // 更新紧急程度显示
        priority.addEventListener("input", function() {
            priorityValue.textContent = priority.value;
        });

        // 存储任务数据
        let tasks = [];

        // 提交表单并添加任务
        taskForm.addEventListener("submit", function(event) {
            event.preventDefault();

            // 获取任务数据
            const newTask = {
                title: taskTitle.value,
                description: taskDescription.value,
                duration: parseInt(duration.value) || 0,  // 用时(分钟)
                priority: parseFloat(priority.value),
                completed: false,  // 添加completed字段表示任务是否完成
            };

            // 添加到任务列表
            tasks.push(newTask);

            // 清空表单
            taskForm.reset();
            priorityValue.textContent = "0";

            // 按照紧急程度和时长排序
            sortTasks();

            // 重新渲染任务时间轴
            renderTaskTimeline();
        });

        // 渲染任务时间轴
        function renderTaskTimeline() {
            taskTimeline.innerHTML = ""; // 清空现有内容
            tasks.forEach((task, index) => {
                const taskElement = document.createElement("div");
                taskElement.classList.add("p-4", "bg-white", "rounded-lg", "shadow-md", "relative");

                // 完成任务时,添加背景色
                if (task.completed) {
                    taskElement.classList.add("bg-gray-200");
                }

                // 显示任务内容
                taskElement.innerHTML = `
                    <div class="flex justify-between items-center">
                        <h3 class="text-xl font-semibold">${task.title}</h3>
                        
                        <button class="absolute top-2 right-2 text-gray-500" οnclick="editTask(${index})">
                            ✎
                        </button>
                    </div>
                    <p class="text-gray-700 mb-2 ${task.completed ? "text-gray-400" : ""}">${task.description}</p>
                    <p class="text-gray-500 mb-2 ${task.completed ? "text-gray-400" : ""}">预计完成时间: ${task.duration} 分钟</p>
                    <p class="text-gray-500 ${task.completed ? "text-gray-400" : ""}">紧急程度: ${task.priority}</p>
                    <button class="absolute bottom-2 right-2 bg-green-500 text-white py-1 px-3 rounded ${task.completed ? "opacity-50 cursor-not-allowed" : ""}" οnclick="completeTask(${index})">
                            完成
                    </button>
                    ${task.completed ? '<p class="absolute inset-0 text-center text-3xl font-bold text-red-600 flex items-center justify-center">已完成</p>' : ""}
                `;
                taskTimeline.appendChild(taskElement);
            });
        }

        // 编辑任务功能
        function editTask(index) {
            const task = tasks[index];
            taskTitle.value = task.title;
            taskDescription.value = task.description;
            duration.value = task.duration;
            priority.value = task.priority;
            priorityValue.textContent = task.priority;

            // 从任务列表中移除任务
            tasks.splice(index, 1);

            // 重新渲染任务时间轴
            renderTaskTimeline();
        }

        // 标记任务为完成
        function completeTask(index) {
            tasks[index].completed = true;

            // 按照紧急程度和时长排序
            sortTasks();

            // 重新渲染任务时间轴
            renderTaskTimeline();
        }

        // 排序任务
        function sortTasks() {
            tasks.sort((a, b) => {
                if (a.completed !== b.completed) {
                    return a.completed ? 1 : -1; // 完成的任务排在后面
                }
                if (a.priority !== b.priority) {
                    return b.priority - a.priority; // 优先级高的排在前面
                }
                return a.duration - b.duration; // 紧急程度相同的情况下按时间排序
            });
        }
    </script>
</body>
</html>

5、蛇年祝福

Prompt:请生成一个 HTML 文件,其中包含一段 JavaScript 代码。创建一个新年贺卡网页,要求如下:
用户自定义内容:
贺卡标题:金蛇献瑞
贺卡抬头:亲爱的Amy
贺卡正文:祝你新的一年更加热爱自己
贺卡祝福:愿你在蛇年里灵动优雅,前程似锦!
重要!页面布局必须严格执行:
爆竹区域:
爆竹emoji(🧨)大小设置为text-6xl
提示文字"点击爆竹送祝福"必须在爆竹下方,不能被遮挡
整体容器使用flex flex-col布局,确保垂直排列
鼠标移到爆竹上时要有hover:scale-110效果
贺卡样式(必须实现):
使用rounded-2xl确保圆角效果
添加backdrop-blur-sm实现毛玻璃效果
边缘要有红色渐变光晕效果
padding设置为p-8确保内容不贴边
重要!颜色必须严格执行:
文字渐变效果(必须应用到所有文字符号):
.symbol {
background-image: linear-gradient(135deg, #ff4d4d, #ffb700);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: #ff4d4d; / 降级方案 /
}
烟花效果(必须实现):
.firework {
position: absolute;
width: 6px;
height: 6px;
border-radius: 50%;
background: linear-gradient(135deg, #ff4d4d, #ffb700);
transform-origin: center center;
animation: explode 1.5s cubic-bezier(0.165, 0.84, 0.44, 1) forwards;
}
@keyframes explode {
0% { transform: scale(1) rotate(0deg); opacity: 1; }
50% { opacity: 1; }
100% { transform: scale(40) rotate(45deg); opacity: 0; }
}
符号喷射效果:
所有文字符号必须应用渐变色
符号大小设为28px
符号需要旋转和缩放动画
轨迹要有渐变效果
动画时序:
点击爆竹后:
立即创建烟花效果(16个粒子,呈放射状)
同时开始喷射符号(36个,带渐变色)
1.2秒后显示贺卡

分享链接🔗
在这里插入图片描述

<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>新年贺卡</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    fontFamily: {
                        classic: ['Noto Serif SC', '楷体', 'STKaiti', 'serif']
                    }
                }
            }
        }
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
</head>

<body
    class="bg-gradient-to-br from-red-50 to-pink-50 min-h-screen flex items-center justify-center overflow-hidden font-classic">
    <div class="fixed top-0 left-0 w-full h-full bg-pattern opacity-10"></div>

    <div id="firework-container"
        class="cursor-pointer fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-10">
        <div class="text-6xl animate-bounce hover:scale-110 transition-transform">🧨</div>
        <div class="click-hint text-center mt-4 text-red-600 animate-pulse">点击爆竹送祝福</div>
    </div>

    <div id="card-container" class="hidden relative z-10">
        <div class="card-wrapper relative">
            <div
                class="absolute -inset-1 bg-gradient-to-r from-pink-600 to-red-600 rounded-2xl blur opacity-25 group-hover:opacity-50 transition duration-1000">
            </div>
            <div
                class="relative bg-white bg-opacity-90 backdrop-blur-sm rounded-2xl p-8 max-w-md mx-auto transform transition-all duration-1000">
                <div class="absolute -top-6 left-1/2 transform -translate-x-1/2">
                    <span class="text-4xl">🐍</span>
                </div>
                <h1
                    class="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-red-600 to-pink-600 text-center mb-8 mt-4 tracking-wider">
                    金蛇献瑞</h1>
                <div class="text-lg text-gray-800 space-y-6">
                    <p class="font-semibold text-gray-700 tracking-wide">亲爱的【Jenny】:</p>
                    <p class="text-center my-6 text-gray-800 tracking-wide">祝你新的一年更加热爱自己</p>
                    <p
                        class="text-right italic bg-gradient-to-r from-red-600 to-pink-600 bg-clip-text text-transparent tracking-wide">
                        愿你在蛇年里灵动优雅,前程似锦!</p>
                </div>
                <div class="absolute -bottom-4 right-4">
                    <span class="text-2xl transform rotate-45"></span>
                </div>
            </div>
        </div>
    </div>

    <canvas id="matter-canvas" class="fixed top-0 left-0 w-full h-full pointer-events-none"></canvas>

    <style>
        /* 导入字体 */
        @import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;600;700&display=swap');
        
        /* 定义字体变量 */
        :root {
            --font-classic: 'Noto Serif SC', '楷体', 'STKaiti', serif;
        }
        
        @keyframes scale-breath {
        
            0%,
            100% {
                transform: scale(1) rotate(-1deg);
            }
        
            50% {
                transform: scale(1.02) rotate(1deg);
            }
        }
        
        .card-appear {
            opacity: 0;
            transform: scale(0.8) translateY(20px);
            animation: card-entrance 1.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
            will-change: transform, opacity;
            font-family: var(--font-classic);
        }
        
        @keyframes card-entrance {
            0% {
                opacity: 0;
                transform: scale(0.8) translateY(20px);
            }
        
            100% {
                opacity: 1;
                transform: scale(1) translateY(0);
            }
        }
        
        .firework {
            position: absolute;
            width: 6px;
            height: 6px;
            border-radius: 50%;
            animation: explode 1.5s cubic-bezier(0.165, 0.84, 0.44, 1) forwards;
            transform-origin: center center;
            will-change: transform, opacity;
        }
        
        @keyframes explode {
            0% {
                transform: scale(1) rotate(0deg);
                opacity: 1;
            }
        
            50% {
                opacity: 1;
            }
        
            100% {
                transform: scale(40) rotate(45deg);
                opacity: 0;
            }
        }
        
        .symbol {
            position: absolute;
            font-size: 28px;
            user-select: none;
            pointer-events: none;
            opacity: 0;
            animation: spray-out 2s cubic-bezier(0.23, 1, 0.32, 1) forwards;
            background-image: linear-gradient(135deg, #ff4d4d, #ffb700);
            -webkit-background-clip: text;
            background-clip: text;
            -webkit-text-fill-color: transparent;
            color: #ff4d4d;
            text-shadow: 2px 2px 8px rgba(255, 77, 77, 0.5);
            will-change: transform, opacity;
            font-family: var(--font-classic);
            letter-spacing: 1px;
        }
        
        .symbol[data-type="emoji"] {
            background-image: none;
            -webkit-background-clip: unset;
            background-clip: unset;
            -webkit-text-fill-color: unset;
            color: unset;
            text-shadow: none;
            font-family: inherit;
        }
        
        @keyframes spray-out {
            0% {
                opacity: 0;
                transform: translate3d(0, 0, 0) rotate(0) scale(0.8);
            }
        
            15% {
                opacity: 1;
                transform: translate3d(calc(var(--spray-x) * 0.2), calc(var(--spray-y) * 0.2), 0) rotate(calc(var(--spray-rotation) * 0.2)) scale(1.5);
            }
        
            70% {
                opacity: 1;
                transform: translate3d(calc(var(--spray-x) * 0.7), calc(var(--spray-y) * 0.7), 0) rotate(calc(var(--spray-rotation) * 0.7)) scale(1.2);
            }
        
            100% {
                opacity: 0;
                transform: translate3d(var(--spray-x), var(--spray-y), 0) rotate(var(--spray-rotation)) scale(0.8);
            }
        }
        
        .bg-pattern {
            background-image: radial-gradient(circle at 1px 1px, rgba(255, 0, 0, 0.1) 1px, transparent 0);
            background-size: 40px 40px;
            pointer-events: none;
        }
        
        .card-wrapper {
            transform-style: preserve-3d;
            perspective: 1000px;
            will-change: transform;
        }
        
        .card-wrapper>div {
            transition: all 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
            backface-visibility: hidden;
        }
        
        .card-wrapper:hover>div {
            transform: translateY(-5px) scale(1.02);
            box-shadow: 0 20px 40px rgba(255, 0, 0, 0.15);
        }
        
        .symbol-trail {
            position: absolute;
            pointer-events: none;
            opacity: 0.3;
            filter: blur(2px);
            animation: trail-fade 0.8s cubic-bezier(0.4, 0, 0.2, 1) forwards;
            font-size: 24px;
            background-image: linear-gradient(135deg, #ff4d4d, #ffb700);
            -webkit-background-clip: text;
            background-clip: text;
            -webkit-text-fill-color: transparent;
            color: #ff4d4d;
            will-change: transform, opacity;
            font-family: var(--font-classic);
            letter-spacing: 1px;
        }
        
        .symbol-trail[data-type="emoji"] {
            background-image: none;
            -webkit-background-clip: unset;
            background-clip: unset;
            -webkit-text-fill-color: unset;
            color: unset;
            font-family: inherit;
        }
        
        @keyframes trail-fade {
            0% {
                opacity: 0.3;
                transform: scale(0.9);
            }
        
            100% {
                opacity: 0;
                transform: scale(0.6);
            }
        }
        
        .click-hint {
            font-family: var(--font-classic);
            font-weight: 600;
            text-shadow: 0 0 10px rgba(255, 77, 77, 0.3);
            background-image: linear-gradient(135deg, #ff4d4d, #ff8c00);
            -webkit-background-clip: text;
            background-clip: text;
            -webkit-text-fill-color: transparent;
            color: #ff4d4d;
            letter-spacing: 2px;
        }
    </style>
    
    <script>
        // 新年相关的符号
        const symbols = {
            text: ['福', '春', '年', '喜', '财', '禄', '寿', '囍'],
            emoji: ['🎊', '🐍', '🏮', '💰', '⭐️', '🎉', '🍊', '🍎']
        };
        let animationFrame;
        
        // 烟花爆炸效果
        function createFirework(x, y) {
            const colors = ['#ff4d4d', '#ff8c00', '#ffb700', '#ff6b6b', '#ff4500'];
            const particleCount = 16;
        
            for (let i = 0; i < particleCount; i++) {
                const firework = document.createElement('div');
                firework.className = 'firework';
                firework.style.left = x + 'px';
                firework.style.top = y + 'px';
                firework.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
                firework.style.transform = `rotate(${i * (360 / particleCount)}deg)`;
                document.body.appendChild(firework);
        
                setTimeout(() => firework.remove(), 1500);
            }
        }
        
        // 创建符号轨迹效果
        function createSymbolTrail(element, duration = 1000) {
            const trail = element.cloneNode(true);
            trail.className = 'symbol-trail';
            trail.setAttribute('data-type', element.getAttribute('data-type'));
            trail.style.left = element.style.left;
            trail.style.top = element.style.top;
            trail.style.transform = element.style.transform;
            document.body.appendChild(trail);
            setTimeout(() => trail.remove(), duration);
        }
        
        // 创建喷射的符号
        function createSpraySymbol(x, y, angle, speed, delay = 0) {
            // 随机选择是文字还是emoji
            const isEmoji = Math.random() < 0.4; // 40%概率是emoji
            const symbolArray = isEmoji ? symbols.emoji : symbols.text;
            const symbol = symbolArray[Math.floor(Math.random() * symbolArray.length)];
        
            const symbolElement = document.createElement('div');
            symbolElement.className = 'symbol';
            symbolElement.setAttribute('data-type', isEmoji ? 'emoji' : 'text');
            symbolElement.textContent = symbol;
            symbolElement.style.left = x + 'px';
            symbolElement.style.top = y + 'px';
        
            // 设置喷射角度和方向
            const radians = (angle * Math.PI) / 180;
            const distance = 150 + Math.random() * 250; // 增加喷射距离
            const finalX = Math.cos(radians) * distance;
            const finalY = Math.sin(radians) * distance;
        
            symbolElement.style.setProperty('--spray-x', `${finalX}px`);
            symbolElement.style.setProperty('--spray-y', `${finalY}px`);
            symbolElement.style.setProperty('--spray-speed', `${speed}s`);
            symbolElement.style.setProperty('--spray-rotation', `${Math.random() * 720 - 360}deg`);
        
            document.body.appendChild(symbolElement);
        
            // 创建轨迹效果
            let lastTrailTime = 0;
            const createTrail = (timestamp) => {
                if (timestamp - lastTrailTime > 50) {
                    createSymbolTrail(symbolElement);
                    lastTrailTime = timestamp;
                }
                animationFrame = requestAnimationFrame(createTrail);
            };
        
            setTimeout(() => {
                animationFrame = requestAnimationFrame(createTrail);
                setTimeout(() => {
                    cancelAnimationFrame(animationFrame);
                }, 2000);
            }, delay);
        
            setTimeout(() => symbolElement.remove(), delay + 2000);
        }
        
        // 点击事件处理
        document.getElementById('firework-container').addEventListener('click', function (e) {
            this.style.display = 'none';
        
            // 创建烟花效果
            createFirework(window.innerWidth / 2, window.innerHeight / 2);
        
            // 创建喷射的符号
            const totalSymbols = 36; // 增加符号数量
            const angleStep = 360 / totalSymbols;
        
            for (let i = 0; i < totalSymbols; i++) {
                const angle = i * angleStep + (Math.random() * 20 - 10); // 添加随机角度偏移
                const speed = 1.2 + Math.random() * 0.6; // 调整速度范围
                const delay = Math.random() * 400; // 增加随机延迟
        
                setTimeout(() => {
                    createSpraySymbol(
                        window.innerWidth / 2,
                        window.innerHeight / 2,
                        angle,
                        speed,
                        delay
                    );
                }, delay);
            }
        
            // 等符号动画开始后再显示贺卡
            setTimeout(() => {
                const cardContainer = document.getElementById('card-container');
                cardContainer.classList.remove('hidden');
                cardContainer.firstElementChild.classList.add('card-appear');
            }, 1200);
        }); 
    </script>
</body>

</html>

6、烟花

Prompt:请生成一个 HTML 文件,其中包含一段 JavaScript 代码。创建一个新年祝福页面,需要同时实现两个核心效果:
一、烟花背景效果(使用Canvas):
烟花发射效果:
从底部随机位置发射
上升轨迹带有金色拖尾
轨迹产生闪烁火花
爆炸效果:
实现多种爆炸形状
爆炸粒子带有重力效果
粒子颜色随机变化
自然衰减消失
二、页面主体内容(必须实现):
核心文字布局:
第一行文字:“Datawhale”
使用渐变色(从#3b82f6到#60a5fa)
添加文字发光效果(使用text-shadow)
必须实现渐入和向上浮动的动画
第二行:大型心形emoji “❤️”
必须添加跳动动画(使用@keyframes heartbeat)
心形两侧需要添加闪烁的✨装饰
动画持续时间1.5秒,无限循环
样式细节:
使用"Ma Shan Zheng"字体(从Google Fonts加载)
内容区域样式:
半透明黑色背景(rgba(0, 0, 0, 0.5))
使用backdrop-filter: blur(10px)
添加发光边框效果
padding设置为3.5rem
圆角设置为1.5rem
动画要求:
Datawhale文字动画:
初始状态:opacity: 0, translateY(20px)
最终状态:opacity: 1, translateY(0)
过渡时间:1.5s
心形动画关键帧:
0%: scale(1)
14%: scale(1.3)
28%: scale(1)
42%: scale(1.3)
70%: scale(1)
响应式设计:
内容区域在不同屏幕尺寸下保持合适的大小
文字大小响应式调整
确保在移动设备上显示完整
请确保烟花效果和页面主体内容同时实现,缺一不可。两个部分都需要完整的代码实现。

分享链接🔗
在这里插入图片描述

<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>新年祝福</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&display=swap" rel="stylesheet">
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: #000;
            font-family: 'Ma Shan Zheng', cursive;
        }

        .message {
            opacity: 0;
            transform: translateY(20px);
            transition: all 1.5s ease-out;
        }

        .message.show {
            opacity: 1;
            transform: translateY(0);
        }

        #fireworks {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 1;
        }

        .content {
            position: relative;
            z-index: 2;
            background: rgba(0, 0, 0, 0.5);
            padding: 3.5rem;
            border-radius: 1.5rem;
            backdrop-filter: blur(10px);
            box-shadow: 0 0 40px rgba(255, 255, 255, 0.15);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }

        .title-glow {
            animation: titleGlow 3s ease-in-out infinite;
            background: linear-gradient(45deg, #3b82f6, #60a5fa);
            background-clip: text;
            -webkit-background-clip: text;
            color: transparent;
            text-shadow:
                0 0 20px rgba(59, 130, 246, 0.8),
                0 0 40px rgba(59, 130, 246, 0.6),
                0 0 60px rgba(59, 130, 246, 0.4);
            letter-spacing: 2px;
            position: relative;
        }

        .title-glow::before {
            content: '2025';
            position: absolute;
            top: -1.5rem;
            right: -1rem;
            font-size: 1rem;
            color: #fcd34d;
            text-shadow: 0 0 10px rgba(252, 211, 77, 0.6);
            animation: fadeInRotate 1s ease-out;
        }

        @keyframes fadeInRotate {
            from {
                opacity: 0;
                transform: rotate(-45deg) scale(0.5);
            }

            to {
                opacity: 1;
                transform: rotate(0) scale(1);
            }
        }

        @keyframes titleGlow {

            0%,
            100% {
                filter: brightness(1);
            }

            50% {
                filter: brightness(1.4);
            }
        }

        .floating {
            animation: floating 3s ease-in-out infinite;
        }

        @keyframes floating {
            0% {
                transform: translateY(0px);
            }

            50% {
                transform: translateY(-10px);
            }

            100% {
                transform: translateY(0px);
            }
        }

        .heart {
            animation: heartbeat 1.5s ease-in-out infinite;
            color: #ef4444;
            font-size: 3.5rem;
            margin: 2rem 0;
            opacity: 0.95;
            text-shadow: 0 0 20px rgba(239, 68, 68, 0.6);
            position: relative;
        }

        .heart::before,
        .heart::after {
            content: '✨';
            position: absolute;
            font-size: 1.5rem;
            animation: sparkle 2s ease-in-out infinite;
        }

        .heart::before {
            left: -2rem;
            top: 0;
            animation-delay: 0.5s;
        }

        .heart::after {
            right: -2rem;
            top: 0;
            animation-delay: 1s;
        }

        @keyframes sparkle {

            0%,
            100% {
                opacity: 0.3;
                transform: scale(0.8);
            }

            50% {
                opacity: 1;
                transform: scale(1.2);
            }
        }

        @keyframes heartbeat {
            0% {
                transform: scale(1);
            }

            14% {
                transform: scale(1.3);
            }

            28% {
                transform: scale(1);
            }

            42% {
                transform: scale(1.3);
            }

            70% {
                transform: scale(1);
            }
        }

        .border-glow {
            animation: borderGlow 3s ease-in-out infinite;
            position: relative;
        }

        .border-glow::before {
            content: '🎊';
            position: absolute;
            top: -1.5rem;
            left: -1.5rem;
            font-size: 2rem;
            animation: rotate 3s linear infinite;
        }

        .border-glow::after {
            content: '🎊';
            position: absolute;
            bottom: -1.5rem;
            right: -1.5rem;
            font-size: 2rem;
            animation: rotate 3s linear infinite reverse;
        }

        @keyframes rotate {
            from {
                transform: rotate(0deg);
            }

            to {
                transform: rotate(360deg);
            }
        }

        @keyframes borderGlow {
            0% {
                box-shadow: 0 0 25px rgba(59, 130, 246, 0.4);
            }

            50% {
                box-shadow: 0 0 50px rgba(59, 130, 246, 0.6);
            }

            100% {
                box-shadow: 0 0 25px rgba(59, 130, 246, 0.4);
            }
        }

        .year-text {
            color: #fcd34d;
            text-shadow: 0 0 15px rgba(252, 211, 77, 0.6);
            font-weight: bold;
            letter-spacing: 1px;
            position: relative;
            display: inline-block;
        }

        .year-text::before,
        .year-text::after {
            content: '';
            position: absolute;
            height: 2px;
            width: 0;
            background: linear-gradient(90deg, transparent, #fcd34d, transparent);
            animation: lineGrow 2s ease-out forwards;
        }

        .year-text::before {
            top: -0.5rem;
            left: 0;
        }

        .year-text::after {
            bottom: -0.5rem;
            right: 0;
        }

        @keyframes lineGrow {
            to {
                width: 100%;
            }
        }

        @keyframes slither {
            0% {
                transform: translateX(0) rotate(5deg);
            }

            25% {
                transform: translateX(5px) rotate(-5deg);
            }

            50% {
                transform: translateX(0) rotate(5deg);
            }

            75% {
                transform: translateX(-5px) rotate(-5deg);
            }

            100% {
                transform: translateX(0) rotate(5deg);
            }
        }

        .snake-emoji {
            display: inline-block;
            animation: slither 2s ease-in-out infinite;
            transform-origin: center;
        }
    </style>
</head>

<body class="min-h-screen flex items-center justify-center bg-gradient-to-b from-black to-gray-800">
    <canvas id="fireworks"></canvas>
    <div class="content text-center border-glow">
        <div id="message" class="message space-y-8">
            <p class="text-6xl font-bold title-glow mb-8">【替换名字!】</p>
            <div class="heart floating">❤️</div>
            <div class="mt-8 text-2xl year-text">
                <span class="snake-emoji">🐍</span>
                蛇年大吉
                <span class="snake-emoji">🐍</span>
            </div>
        </div>
    </div>
    <script >
        class Firework {
            constructor(canvas) {
                this.canvas = canvas;
                this.ctx = canvas.getContext('2d');
                this.particles = [];
                this.hue = Math.random() * 360;
                this.resize();
                window.addEventListener('resize', () => this.resize());
                this.init();
            }

            resize() {
                this.width = window.innerWidth;
                this.height = window.innerHeight;
                this.canvas.width = this.width;
                this.canvas.height = this.height;
            }

            init() {
                this.createParticles(
                    Math.random() * this.width,
                    this.height * 0.8,
                    true
                );
                this.animate();
            }

            createParticles(x, y, isRocket = false) {
                if (isRocket) {
                    // 创建一个烟花火箭
                    const targetY = this.height * 0.2 + (Math.random() * this.height * 0.3);
                    this.particles.push({
                        x,
                        y,
                        vx: (Math.random() - 0.5) * 2, // 添加水平方向的随机移动
                        vy: -12,
                        targetY,
                        isRocket: true,
                        color: `hsl(${this.hue}, 100%, 50%)`,
                        size: 3,
                        trail: [],
                        sparkTrail: [] // 添加火花轨迹
                    });
                } else {
                    // 创建多种形状的爆炸效果
                    const shapes = [
                        this.createCircularBurst,
                        this.createHeartBurst,
                        this.createCrossBurst,
                        this.createSpiralBurst
                    ];
                    const selectedShape = shapes[Math.floor(Math.random() * shapes.length)];
                    selectedShape.call(this, x, y);
                }
            }

            createCircularBurst(x, y) {
                const particleCount = 120;
                const angleStep = (Math.PI * 2) / particleCount;

                for (let layer = 0; layer < 3; layer++) {
                    const velocity = 3 + layer * 2 + Math.random() * 2;
                    const baseLife = 180 + layer * 50;

                    for (let i = 0; i < particleCount; i++) {
                        const angle = angleStep * i + (Math.random() * 0.5 - 0.25);
                        const life = baseLife + Math.random() * 100;
                        this.createParticle(x, y, angle, velocity, life, layer);
                    }
                }
            }

            createHeartBurst(x, y) {
                const particleCount = 80;
                for (let i = 0; i < particleCount; i++) {
                    const angle = (i / particleCount) * Math.PI * 2;
                    const heartX = 16 * Math.pow(Math.sin(angle), 3);
                    const heartY = -(13 * Math.cos(angle) - 5 * Math.cos(2 * angle) - 2 * Math.cos(3 * angle) - Math.cos(4 * angle));
                    const velocity = 2 + Math.random() * 2;
                    const direction = Math.atan2(heartY, heartX);
                    this.createParticle(x, y, direction, velocity, 150 + Math.random() * 100, 0);
                }
            }

            createCrossBurst(x, y) {
                const arms = 8;
                const particlesPerArm = 15;
                for (let arm = 0; arm < arms; arm++) {
                    const baseAngle = (arm / arms) * Math.PI * 2;
                    for (let i = 0; i < particlesPerArm; i++) {
                        const velocity = 4 + (i / particlesPerArm) * 4;
                        const angle = baseAngle + (Math.random() * 0.3 - 0.15);
                        this.createParticle(x, y, angle, velocity, 150 + Math.random() * 100, 0);
                    }
                }
            }

            createSpiralBurst(x, y) {
                const turns = 5;
                const particlesPerTurn = 30;
                const totalParticles = turns * particlesPerTurn;

                for (let i = 0; i < totalParticles; i++) {
                    const angle = (i / particlesPerTurn) * Math.PI * 2 + (i / totalParticles) * Math.PI * 2 * turns;
                    const velocity = 2 + (i / totalParticles) * 6;
                    this.createParticle(x, y, angle, velocity, 150 + Math.random() * 100, 0);
                }
            }

            createParticle(x, y, angle, velocity, life, layer) {
                const vx = Math.cos(angle) * velocity;
                const vy = Math.sin(angle) * velocity;
                this.particles.push({
                    x,
                    y,
                    vx,
                    vy,
                    life,
                    maxLife: life,
                    color: `hsla(${this.hue + layer * 20}, 100%, ${60 + Math.random() * 20}%, 1)`,
                    size: 2.5 - layer * 0.5 + Math.random(),
                    isRocket: false,
                    trail: [],
                    decay: 0.99 - Math.random() * 0.02
                });
            }

            animate() {
                this.ctx.fillStyle = 'rgba(0, 0, 0, 0.07)';
                this.ctx.fillRect(0, 0, this.width, this.height);

                this.particles.forEach((particle, index) => {
                    if (particle.isRocket) {
                        // 火箭尾迹效果
                        particle.trail.push({ x: particle.x, y: particle.y });
                        if (particle.trail.length > 5) particle.trail.shift();

                        // 添加火花效果
                        if (Math.random() < 0.3) {
                            particle.sparkTrail.push({
                                x: particle.x,
                                y: particle.y,
                                vx: (Math.random() - 0.5) * 2,
                                vy: Math.random() * 2,
                                life: 10
                            });
                        }

                        // 更新和绘制火花
                        particle.sparkTrail.forEach((spark, sparkIndex) => {
                            spark.x += spark.vx;
                            spark.y += spark.vy;
                            spark.life--;

                            if (spark.life <= 0) {
                                particle.sparkTrail.splice(sparkIndex, 1);
                            } else {
                                this.ctx.fillStyle = `hsla(${this.hue}, 100%, 50%, ${spark.life / 10})`;
                                this.ctx.beginPath();
                                this.ctx.arc(spark.x, spark.y, 1, 0, Math.PI * 2);
                                this.ctx.fill();
                            }
                        });

                        // 绘制火箭尾迹
                        particle.trail.forEach((point, i) => {
                            this.ctx.fillStyle = `hsla(${this.hue}, 100%, 50%, ${i / particle.trail.length})`;
                            this.ctx.beginPath();
                            this.ctx.arc(point.x, point.y, particle.size * (i / particle.trail.length), 0, Math.PI * 2);
                            this.ctx.fill();
                        });

                        particle.x += particle.vx;
                        particle.y += particle.vy;
                        particle.vx *= 0.99; // 轻微的水平减速

                        if (particle.y <= particle.targetY) {
                            this.createParticles(particle.x, particle.y);
                            this.particles.splice(index, 1);
                            this.hue = Math.random() * 360;
                        }
                    } else {
                        particle.x += particle.vx;
                        particle.y += particle.vy;
                        particle.vy += 0.08;
                        particle.vx *= particle.decay;
                        particle.vy *= particle.decay;
                        particle.life--;

                        const alpha = particle.life / particle.maxLife;
                        const size = particle.size * (0.5 + alpha * 0.5);

                        if (particle.life <= 0) {
                            this.particles.splice(index, 1);
                        } else {
                            this.ctx.fillStyle = particle.color.replace('1)', `${alpha})`);
                            this.ctx.beginPath();
                            this.ctx.arc(particle.x, particle.y, size, 0, Math.PI * 2);
                            this.ctx.fill();
                        }
                    }
                });

                if (Math.random() < 0.02) {
                    this.createParticles(
                        Math.random() * this.width,
                        this.height * 0.8,
                        true
                    );
                }

                requestAnimationFrame(() => this.animate());
            }
        }

        const canvas = document.getElementById('fireworks');
        new Firework(canvas);
    </script>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const message = document.getElementById('message');

            // 延迟显示消息
            setTimeout(() => {
                message.classList.add('show');
            }, 1000);
        });
    </script>
</body>

</html>

网站公告

今日签到

点亮在社区的每一天
去签到