《像素绘画板》:通过Trae将脑中的创意变为现实

335 阅读13分钟

在没有大模型和AI编辑器的时候,想要通过编程实现自己的页面并不是一件容易的事情。首先,你得找到一个与你想法类似的项目作为参考,然后再通过对HTML、CSS以及JS的深入学习,才能照猫画虎一般完成一个简单demo,又或是需要了解VueReact等前端框架的使用,熟悉整个的开发流程。但通过AI编辑器Trae,你能够省去前端知识的学习成本,只需要将自己的一些奇思妙想交给编辑器,它便能结合大模型帮助你生成一个还不错的小项目。

那么灵感怎么来呢?

  • 你可以结合自己生活和工作中的一些需求,将它们的核心部分提炼出来,然后你再想想能不能以工具的方式去解决这些问题。比如:当你工作中在处理文件时,需要用到markdownpdf的功能,可是你嫌麻烦又不想去下载其他软件,这时候你就可以借助Trae这款编辑器帮你实现一款markdownpdf格式的页面小项目,同时你还可以根据自己的一些小需求对它进行微调,只需要不断地和Trae对话就可以啦。

  • 如果你没有遇到上述的情况,那么寻找灵感的过程也可以交给Trae来解决。比如你想开发一款休闲小游戏,但不知道应该以什么为主题好。那么你直接将该问题交给AI编辑器,它会给你提供一些有趣的想法。

  • 我便是属于第二种情况,于是我我打开了Trae,把我的问题告诉它:

    请帮我想一些页面小项目的名称和功能,要求只能用HTML、CSS以及JS来实现。

    Trae交给豆包大模型理解后,给出了我很详细的答复:

    1. 可以通过html、css、js设计一款像素绘画板,核心功能:网格画布(CSS Grid实现),点击填色,支持调色 盘;特色功能:添加本地保存功能(localStorage存图片数据)、一键导出PNG;技术点:canvas.toDataURL() 导出图片等。
    2. 可以通过html,css,js设计一个记忆卡片配对游戏,核心功能:翻牌匹配相同图案,计时计步,胜利提示;技术亮点:JS随机生成卡片布局( Fisher-Yates 洗牌算法)、CSS 3D翻转动画增强交互感。
    3. . . . . . .

    我挑选了第一个作为我的想法,并再次发送给Trae的AI对话框:
    2f1ae31e-69c9-41ac-9bfa-8ca47d5a897d.png 于是它很快就把代码实现了。

如何对项目进行微调?

我们第一次发给Trae的生成提示词可能比较粗糙,会忽略很多细节的功能和设计。所以我们可以先将每次的代码运行在浏览器中,通过查看它具体的运行效果,以及使用下来发现的一些问题,对我们第一次发送的提示词内容进行补充和优化。经过反复和Trae对话,我们便能够将这个小项目打磨地越来越好。

  • 运行初始的代码,可以得到以下运行结果:image.png

  • 通过与Trae对话进行优化:

    请将页面的滚动条去掉,并给画布添加类似于写字画板的棕色边框。

    image.png

  • 重新运行页面后:image.png

  • 继续将优化的提示词发送给Trae

    请将网格区域的高度整体适当减小,宽度整体适当增加,并放置于页面居中的位置;同时将按钮分别进行美化,颜 色为绿色,边框为圆角,大小适中,增加一些CSS特效,放置于调整后的页面的左侧上方的位置;添加用户通过拖动 鼠标可以在网格区域上色。

    image.png

  • 运行代码并测试画板的功能,画了一只可爱的果冻喵:image.png

使用感想

从这个小项目的灵感来源,到包含的功能以及代码的实现,全部都来自于Trae这款编辑器。整个过程中,我所做的只是不断地和Trae对话,根据编辑器的反馈结果给出相应的建议,也算是实现了“零代码”开发页面。

《像素绘画板》 虽然功能非常简单,但它让我第一次体验了使用AI编辑器开发的全过程,只靠人类的自然语言也可以打造出一款自己的小项目。这也意味着,如果你并不从事写代码的相关行业,也可以靠“开口”开发自己的作品。

作品链接: 像素绘画板 - AI Coding

后续优化版本:像素绘画板 v2.0 - AI Coding

源码分享

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>
    <link rel="stylesheet" href="pixel_painter.css">
</head>
<body>
    <div id="canvas-container"></div>
    <div id="color-picker">
        <button onclick="saveDrawing()">保存</button>
        <button onclick="resetCanvas()">重置</button>
        <input type="color" id="custom-color">
    </div>
    <script src="pixel_painter.js"></script>
</body>
</html>

CSS

body {
    font-family: Arial, sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    padding: 20px;
}
#canvas-container {
    display: grid;
    grid-template-columns: repeat(80, 10px);
    grid-template-rows: repeat(50, 10px);
    gap: 1px;
    background-color: #ccc;
    border: 10px solid #8B4513;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
    margin-left: 80px;
}
.pixel {
    background-color: white;
    width: 10px;
    height: 10px;
}
#color-picker {
    display: flex;
    flex-direction: column;
    gap: 10px;
    position: fixed;
    top: calc(20px + 1 * (10px + 30px + 10px)); /* 恢复原间距 */
    left: 20px;
    width: 100px;
    z-index: 1;
}
.color-option {
    width: 30px;
    height: 30px;
    border: 2px solid transparent;
}
.color-option.selected {
    border-color: black;
}
button {
  width: 120px;
  margin: 0px;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  background-color: #4CAF50;
  color: white;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  transition-duration: 0.4s;
  cursor: pointer;
  }
  button:hover {
  background-color: white;
  color: black;
  border: 2px solid #4CAF50;
  }
  button:active {
  transform: translateY(4px);
  box-shadow: 0 2px #666;
}

#export-buttons {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: fixed;
  top: 10px;
  left: 20px;
}

JS

const canvas = document.getElementById('canvas-container');
const customColor = document.getElementById('custom-color');
let selectedColor = '#000000';
let pixels = [];
let isDrawing = false;

// 初始化画布
function initCanvas() {
    for (let i = 0; i < 80 * 50; i++) {
        const pixel = document.createElement('div');
        pixel.classList.add('pixel');
        pixel.addEventListener('click', () => colorPixel(pixel));
        pixel.addEventListener('mousemove', () => colorPixel(pixel));
        canvas.appendChild(pixel);
        pixels.push(pixel);
    }
    loadDrawing();
}

// 选择颜色
customColor.addEventListener('change', () => {
    selectedColor = customColor.value;
});

// 填充像素
function colorPixel(pixel) {
    if (isDrawing) {
        pixel.style.backgroundColor = selectedColor;
    }
}

// 保存绘画(现在功能为导出 PNG)
function saveDrawing() {
    exportPNG();
}

// 重置画布
function resetCanvas() {
    pixels.forEach(pixel => {
        pixel.style.backgroundColor = 'white';
    });
}

// 加载绘画
function loadDrawing() {
    const savedColors = JSON.parse(localStorage.getItem('pixelDrawing'));
    if (savedColors) {
        savedColors.forEach((color, index) => {
            pixels[index].style.backgroundColor = color;
        });
    }
}

// 导出PNG
function exportPNG() {
    const tempCanvas = document.createElement('canvas');
    const ctx = tempCanvas.getContext('2d');
    tempCanvas.width = 80 * 10;
    tempCanvas.height = 50 * 10;

    pixels.forEach((pixel, index) => {
        const x = (index % 80) * 10;
        const y = Math.floor(index / 80) * 10;
        ctx.fillStyle = pixel.style.backgroundColor;
        ctx.fillRect(x, y, 20, 20);
    });

    const link = document.createElement('a');
    link.download = 'pixel-art.png';
    link.href = tempCanvas.toDataURL();
    link.click();
}

// 添加鼠标事件监听器
canvas.addEventListener('mousedown', () => isDrawing = true);
canvas.addEventListener('mouseup', () => isDrawing = false);
canvas.addEventListener('mouseleave', () => isDrawing = false);

initCanvas();

v2.0源码分享

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>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="controls">
        <input type="color" id="colorPicker">
        <input type="text" id="textInput" placeholder="输入要转换的文字">
        <button id="textToPixelButton">文字转像素画</button>
        <button id="saveButton">保存</button>
        <button id="exportButton">导出PNG</button>
        <button id="clearButton">清空画布</button>
        <button id="eraserButton">橡皮擦</button>
        <button id="importButton">导入图片</button>
        <button id="ai-chat-button">AI聊天</button>
        <button id="clear-chat-history">清除对话</button>
    </div>
    <h1 class="pixel-text">像素绘画板</h1>
    <div id="canvas"></div>
    
    <script src="script.js"></script>
<div id="ai-chat-popup" style="display: none;">
        <div id="ai-chat-messages"></div>
        <input type="text" id="ai-chat-input" placeholder="请输入您的绘画想法...">
        <button id="ai-chat-send">发送</button>
    </div>
</body>
</html>

CSS

body {
    background: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);
    background-attachment: fixed;
    font-family: 'Press Start 2P', cursive;
    display: flex;
    flex-direction: column;
    align-items: center;
    overflow: hidden; /* 去掉滚动条 */
}

.pixel-text {
    font-family: 'Press Start 2P', cursive;
    font-size: 32px;
    color: #333;
    text-shadow: 2px 2px 0px #fff, 4px 4px 0px #000;
    margin-bottom: 20px;
    letter-spacing: 2px;
}

#ai-loading-bar {
    border: 2px solid #667eea;
    background-color: rgba(255, 255, 255, 0.5);
    border-radius: 10px;
    overflow: hidden;
}

#ai-loading-progress {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    height: 100%;
    border-radius: 8px;
    transition: width 0.5s ease;
}

@font-face {
    font-family: 'Press Start 2P';
    src: url('https://fonts.gstatic.com/s/pressstart2p/v14/e3t4euO8T-267oIAQAu6jDQyK3nYivN04w.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

.controls input[type="color"] {
    width: 100%;
    height: 48px;
    border: none;
    border-radius: 25px;
    padding: 4px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    cursor: pointer;
    transition: all 0.3s ease;
}

.controls input[type="color"]:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2);
}

.controls input[type="color"]::-webkit-color-swatch-wrapper {
    padding: 0;
}

.controls input[type="color"]::-webkit-color-swatch {
    border: none;
    border-radius: 21px;
}

.controls {
    position: absolute;
    left: 20px;
    top: 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.controls button {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border: none;
    border-radius: 25px;
    color: white;
    padding: 12px 24px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
    font-family: 'Press Start 2P', cursive;
    font-weight: bold;
    letter-spacing: 1px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    transition: all 0.3s ease;
    cursor: pointer;
}

.controls button:hover {
    background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
    transform: translateY(-2px);
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2);
}

#canvas {
    display: grid;
    grid-gap: 1px;
    background-color: #ccc;
    border: 15px double #4a321a; /* 加宽边框并使用双线条样式,更改颜色为更深的棕色 */
    box-shadow: 0 0 30px rgba(74, 50, 26, 0.7), 0 0 10px rgba(74, 50, 26, 0.5) inset; /* 增强外部阴影并添加内部阴影 */
    margin: auto; /* 居中显示 */
    height: auto;
    width: auto;
}

.pixel {
    background-color: #fff;
}

#ai-qa-container {
    position: absolute;
    right: 30px;
    top: 30px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    background: rgba(255, 255, 255, 0.3);
    padding: 15px;
    border-radius: 16px;
    backdrop-filter: blur(5px);
    box-shadow: 0 8px 12px rgba(0, 0, 0, 0.1);
}

#ai-qa-container input[type="text"] {
    width: 180px;
    height: 35px;
    border: 2px solid #667eea;
    border-radius: 28px;
    padding: 4px 12px;
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
    font-size: 16px;
    font-family: 'Press Start 2P', cursive;
    color: #333;
    transition: all 0.3s ease;
}

#ai-qa-container input[type="text"]:focus {
    outline: none;
    border-color: #764ba2;
    box-shadow: 0 8px 10px rgba(0, 0, 0, 0.2);
}

#ai-qa-container button {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border: 2px solid transparent;
    border-radius: 28px;
    color: white;
    padding: 8px 14px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
    font-family: 'Press Start 2P', cursive;
    font-weight: bold;
    letter-spacing: 1px;
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
    transition: all 0.3s ease;
    cursor: pointer;
}

#ai-qa-container button:hover {
    background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
    transform: translateY(-3px);
    box-shadow: 0 8px 10px rgba(0, 0, 0, 0.2);
    border-color: white;
}

#ai-qa-container button:hover {
    background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
    transform: translateY(-2px);
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2);
}

#ai-chat-popup {
    /* 美化聊天框背景 */
    background: linear-gradient(135deg, #e6f7ff 0%, #f0f8ff 100%);
    border: 2px solid #b3d9ff;
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);

    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: white;
    padding: 20px;
    border-radius: 16px;
    box-shadow: 0 8px 12px rgba(0, 0, 0, 0.1);
    width: 400px;
    height: 500px;
    display: none;
    flex-direction: column;
}

#ai-chat-messages {
    height: 430px;
    overflow-y: auto;
    /* 参照 QQ 美化对话内容框 */
    background: #f0f3f5;
    border: 1px solid #d3d7dc;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
    /* 消息气泡样式 */
    display: flex;
    flex-direction: column;
    gap: 10px;

    flex-grow: 1;
    overflow-y: auto;
    padding: 10px;
    margin-bottom: 10px;
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.9) 0%, rgba(240, 240, 240, 0.9) 100%);
    border-radius: 14px;
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
    font-family: 'Press Start 2P', cursive;
    font-size: 12px;
    line-height: 1.6;
    color: #333;
}

#ai-chat-messages div {
    max-width: 70%;
    padding: 8px 12px;
    border-radius: 16px;
    margin-bottom: 5px;
}

#ai-chat-messages div:nth-child(odd) {
    background: #9eea6a;
    align-self: flex-end;
}

#ai-chat-messages div:nth-child(even) {
    background: #fff;
    align-self: flex-start;
}

#ai-chat-input {
    width: calc(100% - 120px);
    height: 35px;
    border: 2px solid #667eea;
    border-radius: 28px;
    padding: 4px 12px;
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
    font-size: 16px;
    font-family: 'Press Start 2P', cursive;
    color: #333;
    transition: all 0.3s ease;
}

#ai-chat-input:focus {
    outline: none;
    border-color: #764ba2;
    box-shadow: 0 8px 10px rgba(0, 0, 0, 0.2);
}

#ai-chat-send {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border: 2px solid transparent;
    border-radius: 28px;
    color: white;
    padding: 8px 14px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
    font-family: 'Press Start 2P', cursive;
    font-weight: bold;
    letter-spacing: 1px;
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
    transition: all 0.3s ease;
    cursor: pointer;
    margin-left: 10px;
}

#ai-chat-send:hover {
    background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
    transform: translateY(-3px);
    box-shadow: 0 8px 10px rgba(0, 0, 0, 0.2);
    border-color: white;
}

#ai-response-output {
    max-width: 180px;
    max-height: 200px;
    overflow-y: auto;
    padding: 10px;
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.9) 0%, rgba(240, 240, 240, 0.9) 100%);
    border-radius: 14px;
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
    font-family: 'Press Start 2P', cursive;
    font-size: 12px;
    line-height: 1.6;
    color: #333;
}

#ai-response-output::-webkit-scrollbar {
    width: 6px;
}

#ai-response-output::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.5);
    border-radius: 3px;
}

#ai-response-output::-webkit-scrollbar-thumb {
    background: #667eea;
    border-radius: 3px;
}

#ai-response-output::-webkit-scrollbar-thumb:hover {
    background: #764ba2;
}

JS

document.addEventListener('DOMContentLoaded', () => {
    const clearChatHistoryButton = document.getElementById('clear-chat-history');
    clearChatHistoryButton.addEventListener('click', () => {
        localStorage.removeItem('aiChatHistory');
        aiChatMessages.innerHTML = '';
    });
    const aiChatButton = document.getElementById('ai-chat-button');
    const aiChatPopup = document.getElementById('ai-chat-popup');
    const aiChatInput = document.getElementById('ai-chat-input');
    const aiChatSend = document.getElementById('ai-chat-send');
    const aiChatMessages = document.getElementById('ai-chat-messages');

    aiChatButton.addEventListener('click', () => {
        // 加载历史记录
        const chatHistory = JSON.parse(localStorage.getItem('aiChatHistory')) || [];
        aiChatMessages.innerHTML = '';
        chatHistory.forEach((message) => {
            const msgElement = document.createElement('div');
            msgElement.textContent = `${message.role === 'user' ? '您' : 'AI'}: ${message.content}`;
            aiChatMessages.appendChild(msgElement);
        });

        if (aiChatPopup.style.display === 'block') {
            aiChatPopup.style.display = 'none';
        } else {
            aiChatPopup.style.display = 'block';
        }
    });

    aiChatSend.addEventListener('click', async () => {
        const question = aiChatInput.value;
        if (question.trim() === '') return;

        // 添加用户消息到本地缓存
        const chatHistory = JSON.parse(localStorage.getItem('aiChatHistory')) || [];
        chatHistory.push({ role: 'user', content: question });
        localStorage.setItem('aiChatHistory', JSON.stringify(chatHistory));

        const userMessage = document.createElement('div');
        userMessage.textContent = `您: ${question}`;
        aiChatMessages.appendChild(userMessage);

        // 清空画布输入框
        aiChatInput.value = '';

        try {
            const response = await fetch('https://api.deepseek.com/v1/chat/completions', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': 'Bearer sk-c81f865b4a684e6cad698bfec13bc4df'
                },
                body: JSON.stringify({
                    "model": "deepseek-chat",
                    "messages": [
                        {"role": "system", "content": "你是一个画家,请根据我的问题,给出一些绘制建议,需要分点回答"},
                        {"role": "user", "content": question}
                    ]
                })
            });

            const data = await response.json();
            const answer = data.choices[0].message.content;

            // 添加 AI 回复到本地缓存
        chatHistory.push({ role: 'ai', content: answer });
        localStorage.setItem('aiChatHistory', JSON.stringify(chatHistory));

        const aiMessage = document.createElement('div');
            aiMessage.textContent = `AI: ${answer}`;
            aiChatMessages.appendChild(aiMessage);
        } catch (error) {
            console.error('请求 DeepSeek API 时出错:', error);
        }
    });
    const textInput = document.getElementById('textInput');
    const textToPixelButton = document.getElementById('textToPixelButton');

    textToPixelButton.addEventListener('click', () => {
        const text = textInput.value;
        if (!text) return;

        const tempCanvas = document.createElement('canvas');
        const ctx = tempCanvas.getContext('2d');
        const gridSize = 60;
        tempCanvas.width = gridSize;
        tempCanvas.height = gridSize;

        ctx.fillStyle = '#fff';
        ctx.fillRect(0, 0, gridSize, gridSize);

        ctx.font = '20px Arial';
        ctx.fillStyle = '#000';
        ctx.textAlign = 'center';
        ctx.fillText(text, gridSize / 2, gridSize / 2);

        const imageData = ctx.getImageData(0, 0, gridSize, gridSize);
        const data = imageData.data;
        const pixels = document.querySelectorAll('.pixel');
        const color = colorPicker.value;

        let index = 0;
        for (let i = 0; i < gridSize; i++) {
            for (let j = 0; j < gridSize; j++) {
                const r = data[index];
                const g = data[index + 1];
                const b = data[index + 2];
                const a = data[index + 3];

                if (a > 0 && r < 128 && g < 128 && b < 128) {
                    pixels[i * gridSize + j].style.backgroundColor = color;
                } else {
                    pixels[i * gridSize + j].style.backgroundColor = '#fff';
                }

                index += 4;
            }
        }
    });
    const canvas = document.getElementById('canvas');
    const colorPicker = document.getElementById('colorPicker');
    const saveButton = document.getElementById('saveButton');
    const exportButton = document.getElementById('exportButton');
    const clearButton = document.getElementById('clearButton');
    const eraserButton = document.getElementById('eraserButton');
    const importButton = document.getElementById('importButton');
    let isErasing = false;

    const gridSize = 60; // 增加网格尺寸
    const pixelSize = 10;

    // 创建网格
    for (let i = 0; i < gridSize; i++) {
        for (let j = 0; j < gridSize; j++) {
            const pixel = document.createElement('div');
            pixel.classList.add('pixel');
            pixel.style.width = `${pixelSize}px`;
            pixel.style.height = `${pixelSize}px`;
            let isDrawing = false;

        canvas.addEventListener('mousedown', () => {
            isDrawing = true;
        });

        canvas.addEventListener('mouseup', () => {
            isDrawing = false;
        });

        canvas.addEventListener('mouseleave', () => {
            isDrawing = false;
        });

        pixel.addEventListener('mousedown', () => {
            if (isErasing) {
                pixel.style.backgroundColor = '#fff';
            } else {
                pixel.style.backgroundColor = colorPicker.value;
            }
        });

        pixel.addEventListener('mouseenter', () => {
            if (isDrawing) {
                if (isErasing) {
                    pixel.style.backgroundColor = '#fff';
                } else {
                    pixel.style.backgroundColor = colorPicker.value;
                }
            }
        });
            canvas.appendChild(pixel);
        }
    }
    canvas.style.gridTemplateColumns = `repeat(${gridSize}, ${pixelSize}px)`;

        importButton.addEventListener('click', () => {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = 'image/*';

        input.addEventListener('change', (e) => {
            const file = e.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = (event) => {
                    const img = new Image();
                    img.onload = () => {
                        const tempCanvas = document.createElement('canvas');
                        tempCanvas.width = gridSize;
                        tempCanvas.height = gridSize;
                        const ctx = tempCanvas.getContext('2d');
                        // 计算图片的裁剪区域
                        let sourceX = 0;
                        let sourceY = 0;
                        let sourceWidth = img.width;
                        let sourceHeight = img.height;
                        if (img.width > img.height) {
                            sourceX = (img.width - img.height) / 2;
                            sourceWidth = img.height;
                        } else {
                            sourceY = (img.height - img.width) / 2;
                            sourceHeight = img.width;
                        }
                        // 裁剪并绘制图片到临时画布
                        ctx.drawImage(img, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, gridSize, gridSize);
                        
                        const imageData = ctx.getImageData(0, 0, gridSize, gridSize);
                        const data = imageData.data;
                        const pixels = document.querySelectorAll('.pixel');

                        let index = 0;
                        for (let i = 0; i < gridSize; i++) {
                            for (let j = 0; j < gridSize; j++) {
                                const r = data[index];
                                const g = data[index + 1];
                                const b = data[index + 2];
                                const a = data[index + 3];

                                if (a === 0) {
                                    pixels[i * gridSize + j].style.backgroundColor = '#fff';
                                } else {
                                    pixels[i * gridSize + j].style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
                                }

                                index += 4;
                            }
                        }
                    };
                    img.src = event.target.result;
                };
                reader.readAsDataURL(file);
            }
        });

        input.click();
    });

    eraserButton.addEventListener('click', () => {
        isErasing = !isErasing;
        eraserButton.textContent = isErasing ? '结束擦除' : '橡皮擦';
    });

// 保存功能
    saveButton.addEventListener('click', () => {
        const pixels = document.querySelectorAll('.pixel');
        const data = [];
        pixels.forEach(pixel => {
            data.push(pixel.style.backgroundColor);
        });
        localStorage.setItem('pixelArt', JSON.stringify(data));
    });

    // 加载保存的数据
    const savedData = JSON.parse(localStorage.getItem('pixelArt'));
    if (savedData) {
        const pixels = document.querySelectorAll('.pixel');
        pixels.forEach((pixel, index) => {
            pixel.style.backgroundColor = savedData[index];
        });
    }

    // 清空画布功能
    clearButton.addEventListener('click', () => {
        const pixels = document.querySelectorAll('.pixel');
        pixels.forEach(pixel => {
            pixel.style.backgroundColor = '#fff';
        });
        localStorage.removeItem('pixelArt');
    });

    // 导出PNG
    exportButton.addEventListener('click', () => {
        const tempCanvas = document.createElement('canvas');
        tempCanvas.width = gridSize * pixelSize;
        tempCanvas.height = gridSize * pixelSize;
        const ctx = tempCanvas.getContext('2d');
        // 在绘制前填充白色背景
        ctx.fillStyle = '#fff';
        ctx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);

        const pixels = document.querySelectorAll('.pixel');
        let index = 0;
        for (let i = 0; i < gridSize; i++) {
            for (let j = 0; j < gridSize; j++) {
                const pixel = pixels[index];
                const color = window.getComputedStyle(pixel).backgroundColor;
                ctx.fillStyle = color;
                ctx.fillRect(j * pixelSize, i * pixelSize, pixelSize, pixelSize);
                index++;
            }
        }

        const link = document.createElement('a');
        link.download = 'pixel-art.png';
        link.href = tempCanvas.toDataURL();
        link.click();
    });
});

    const aiQuestionInput = document.getElementById('ai-question-input');
    const aiSubmitButton = document.getElementById('ai-submit-button');
    const aiResponseOutput = document.getElementById('ai-response-output');

    aiSubmitButton.addEventListener('click', async () => {
        const loadingBar = document.getElementById('ai-loading-bar');
        const loadingProgress = document.getElementById('ai-loading-progress');
        loadingBar.style.display = 'block';
        const interval = setInterval(() => {
            if (loadingProgress.style.width === '100%') {
                loadingProgress.style.width = '0%';
            } else {
                loadingProgress.style.width = (parseInt(loadingProgress.style.width) + 10) + '%';
            }
        }, 500);
        const question = aiQuestionInput.value;
        if (question.trim() === '') {
            return;
        }

        try {
            const response = await fetch('https://api.deepseek.com/v1/chat/completions', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': 'Bearer 你的deepseek-api-key'
                },
                body: JSON.stringify({
                    "model": "deepseek-chat",
                    "messages": [
                        {"role": "system", "content": "你是一个画家,请根据我的问题,给出一些绘制建议,需要分点回答"},
                        {"role": "user", "content": question}
                    ],
                    "stream": false
                })
            });

            const data = await response.json();
            const answer = data.choices[0].message.content;
            aiResponseOutput.textContent = answer;
        clearInterval(interval);
        loadingBar.style.display = 'none';
        loadingProgress.style.width = '0%';
        clearInterval(interval);
        loadingBar.style.display = 'none';
        loadingProgress.style.width = '0%';
        } catch (error) {
            console.error('请求 DeepSeek API 时出错:', error);
            aiResponseOutput.textContent = '请求出错,请稍后重试。';
        }
    });