|
|
@@ -0,0 +1,1065 @@
|
|
|
+// 全局变量
|
|
|
+let currentTheme = 'pastel';
|
|
|
+let currentStyle = 'cartoon';
|
|
|
+let currentCanvasSize = 128;
|
|
|
+let currentPixelSize = 8;
|
|
|
+let currentSocialMediaFormat = 'custom';
|
|
|
+let favorites = JSON.parse(localStorage.getItem('favorites')) || [];
|
|
|
+let avatarHistory = JSON.parse(localStorage.getItem('avatarHistory')) || [];
|
|
|
+let currentSeed = null;
|
|
|
+let useSeed = false;
|
|
|
+const maxHistoryItems = 50;
|
|
|
+
|
|
|
+// 社交媒体格式尺寸映射
|
|
|
+const socialMediaFormats = {
|
|
|
+ facebook: 180,
|
|
|
+ twitter: 400,
|
|
|
+ instagram: 320,
|
|
|
+ linkedin: 400,
|
|
|
+ youtube: 800
|
|
|
+};
|
|
|
+
|
|
|
+// 编辑相关变量
|
|
|
+let isDrawing = false;
|
|
|
+let currentTool = 'brush';
|
|
|
+let currentColor = '#000000';
|
|
|
+let currentBrushSize = 1;
|
|
|
+let history = [];
|
|
|
+let historyIndex = -1;
|
|
|
+
|
|
|
+// 颜色主题
|
|
|
+const colorThemes = {
|
|
|
+ pastel: ['#FFB6C1', '#FFD700', '#98FB98', '#87CEEB', '#DDA0DD', '#FFA07A'],
|
|
|
+ vibrant: ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8', '#F7DC6F'],
|
|
|
+ dark: ['#2C3E50', '#34495E', '#7F8C8D', '#95A5A6', '#BDC3C7', '#ECF0F1'],
|
|
|
+ monochrome: ['#000000', '#333333', '#666666', '#999999', '#CCCCCC', '#FFFFFF']
|
|
|
+};
|
|
|
+
|
|
|
+// 初始化
|
|
|
+window.addEventListener('DOMContentLoaded', () => {
|
|
|
+ initializeApp();
|
|
|
+ generateAvatar();
|
|
|
+ loadHistory(); // 加载历史记录
|
|
|
+});
|
|
|
+
|
|
|
+function initializeApp() {
|
|
|
+ // 界面切换
|
|
|
+ setupNavigation();
|
|
|
+
|
|
|
+ // 按钮事件
|
|
|
+ setupButtons();
|
|
|
+
|
|
|
+ // 设置
|
|
|
+ setupSettings();
|
|
|
+
|
|
|
+ // 加载收藏
|
|
|
+ loadFavorites();
|
|
|
+}
|
|
|
+
|
|
|
+// 设置导航
|
|
|
+function setupNavigation() {
|
|
|
+ const navBtns = document.querySelectorAll('.nav-btn');
|
|
|
+ navBtns.forEach(btn => {
|
|
|
+ btn.addEventListener('click', () => {
|
|
|
+ const screen = btn.dataset.screen;
|
|
|
+ showScreen(screen);
|
|
|
+
|
|
|
+ // 更新导航按钮状态
|
|
|
+ navBtns.forEach(b => b.classList.remove('active'));
|
|
|
+ btn.classList.add('active');
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 返回按钮
|
|
|
+ document.getElementById('backToGenerate').addEventListener('click', () => {
|
|
|
+ showScreen('generate-screen');
|
|
|
+ document.getElementById('nav-generate').classList.add('active');
|
|
|
+ document.getElementById('nav-favorites').classList.remove('active');
|
|
|
+ });
|
|
|
+
|
|
|
+ document.getElementById('backToGenerate2').addEventListener('click', () => {
|
|
|
+ showScreen('generate-screen');
|
|
|
+ document.getElementById('nav-generate').classList.add('active');
|
|
|
+ document.getElementById('nav-settings').classList.remove('active');
|
|
|
+ });
|
|
|
+
|
|
|
+ document.getElementById('backToGenerate3').addEventListener('click', () => {
|
|
|
+ showScreen('generate-screen');
|
|
|
+ document.getElementById('nav-generate').classList.add('active');
|
|
|
+ });
|
|
|
+
|
|
|
+ document.getElementById('backToGenerate4').addEventListener('click', () => {
|
|
|
+ showScreen('generate-screen');
|
|
|
+ document.getElementById('nav-generate').classList.add('active');
|
|
|
+ document.getElementById('nav-history').classList.remove('active');
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 显示指定界面
|
|
|
+function showScreen(screenId) {
|
|
|
+ const screens = document.querySelectorAll('.screen');
|
|
|
+ screens.forEach(screen => screen.classList.remove('active'));
|
|
|
+ document.getElementById(screenId).classList.add('active');
|
|
|
+}
|
|
|
+
|
|
|
+// 设置按钮事件
|
|
|
+function setupButtons() {
|
|
|
+ // 重新生成按钮
|
|
|
+ document.getElementById('regenerateBtn').addEventListener('click', generateAvatar);
|
|
|
+
|
|
|
+ // 保存按钮
|
|
|
+ document.getElementById('saveBtn').addEventListener('click', saveAvatar);
|
|
|
+
|
|
|
+ // 编辑按钮
|
|
|
+ document.getElementById('editBtn').addEventListener('click', openEditScreen);
|
|
|
+
|
|
|
+ // 收藏按钮
|
|
|
+ document.getElementById('favoriteBtn').addEventListener('click', addToFavorites);
|
|
|
+
|
|
|
+ // 下载按钮
|
|
|
+ document.getElementById('downloadBtn').addEventListener('click', downloadAvatar);
|
|
|
+
|
|
|
+ // 主题按钮
|
|
|
+ const themeBtns = document.querySelectorAll('.theme-btn');
|
|
|
+ themeBtns.forEach(btn => {
|
|
|
+ btn.addEventListener('click', () => {
|
|
|
+ currentTheme = btn.dataset.theme;
|
|
|
+ themeBtns.forEach(b => b.classList.remove('active'));
|
|
|
+ btn.classList.add('active');
|
|
|
+ generateAvatar();
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 风格按钮
|
|
|
+ const styleBtns = document.querySelectorAll('.style-btn');
|
|
|
+ styleBtns.forEach(btn => {
|
|
|
+ btn.addEventListener('click', () => {
|
|
|
+ currentStyle = btn.dataset.style;
|
|
|
+ styleBtns.forEach(b => b.classList.remove('active'));
|
|
|
+ btn.classList.add('active');
|
|
|
+ generateAvatar();
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 细节按钮
|
|
|
+ const detailBtns = document.querySelectorAll('.detail-btn');
|
|
|
+ detailBtns.forEach(btn => {
|
|
|
+ btn.addEventListener('click', () => {
|
|
|
+ // 随机化特定细节
|
|
|
+ generateAvatarWithFocus(btn.dataset.detail);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 社交媒体格式按钮
|
|
|
+ const socialBtns = document.querySelectorAll('.social-options .theme-btn');
|
|
|
+ socialBtns.forEach(btn => {
|
|
|
+ btn.addEventListener('click', () => {
|
|
|
+ const format = btn.dataset.format;
|
|
|
+ setSocialMediaFormat(format);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 种子相关按钮
|
|
|
+ setupSeedButtons();
|
|
|
+
|
|
|
+ // 编辑界面按钮
|
|
|
+ setupEditButtons();
|
|
|
+
|
|
|
+ // 历史记录按钮
|
|
|
+ const clearHistoryBtn = document.getElementById('clearHistoryBtn');
|
|
|
+ if (clearHistoryBtn) {
|
|
|
+ clearHistoryBtn.addEventListener('click', clearHistory);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 设置设置选项
|
|
|
+function setupSettings() {
|
|
|
+ // 画布大小
|
|
|
+ const canvasSizeSelect = document.getElementById('canvasSize');
|
|
|
+ canvasSizeSelect.addEventListener('change', (e) => {
|
|
|
+ currentCanvasSize = parseInt(e.target.value);
|
|
|
+ currentSocialMediaFormat = 'custom';
|
|
|
+ updateCanvasSize();
|
|
|
+ generateAvatar();
|
|
|
+ });
|
|
|
+
|
|
|
+ // 社交媒体格式
|
|
|
+ const socialMediaFormatSelect = document.getElementById('socialMediaFormat');
|
|
|
+ socialMediaFormatSelect.addEventListener('change', (e) => {
|
|
|
+ currentSocialMediaFormat = e.target.value;
|
|
|
+
|
|
|
+ if (currentSocialMediaFormat !== 'custom') {
|
|
|
+ // 设置为对应社交媒体格式的尺寸
|
|
|
+ currentCanvasSize = socialMediaFormats[currentSocialMediaFormat];
|
|
|
+ canvasSizeSelect.value = currentCanvasSize;
|
|
|
+ updateCanvasSize();
|
|
|
+ generateAvatar();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 像素大小
|
|
|
+ const pixelSizeSelect = document.getElementById('pixelSize');
|
|
|
+ pixelSizeSelect.addEventListener('change', (e) => {
|
|
|
+ currentPixelSize = parseInt(e.target.value);
|
|
|
+ generateAvatar();
|
|
|
+ });
|
|
|
+
|
|
|
+ // 界面主题
|
|
|
+ const appThemeSelect = document.getElementById('appTheme');
|
|
|
+ appThemeSelect.addEventListener('change', (e) => {
|
|
|
+ const theme = e.target.value;
|
|
|
+ document.body.className = theme === 'dark' ? 'dark-theme' : '';
|
|
|
+ localStorage.setItem('appTheme', theme);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 加载保存的主题
|
|
|
+ const savedTheme = localStorage.getItem('appTheme') || 'light';
|
|
|
+ appThemeSelect.value = savedTheme;
|
|
|
+ document.body.className = savedTheme === 'dark' ? 'dark-theme' : '';
|
|
|
+
|
|
|
+ // 清空收藏
|
|
|
+ document.getElementById('clearFavorites').addEventListener('click', () => {
|
|
|
+ if (confirm('确定要清空所有收藏吗?')) {
|
|
|
+ favorites = [];
|
|
|
+ localStorage.setItem('favorites', JSON.stringify(favorites));
|
|
|
+ loadFavorites();
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 设置编辑界面按钮
|
|
|
+function setupEditButtons() {
|
|
|
+ // 返回按钮
|
|
|
+ document.getElementById('backToGenerate3').addEventListener('click', () => {
|
|
|
+ showScreen('generate-screen');
|
|
|
+ document.getElementById('nav-generate').classList.add('active');
|
|
|
+ });
|
|
|
+
|
|
|
+ // 颜色选择器
|
|
|
+ document.getElementById('colorPicker').addEventListener('input', (e) => {
|
|
|
+ currentColor = e.target.value;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 画笔大小
|
|
|
+ document.getElementById('brushSize').addEventListener('change', (e) => {
|
|
|
+ currentBrushSize = parseInt(e.target.value);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 工具按钮
|
|
|
+ const toolBtns = document.querySelectorAll('.tool-btn');
|
|
|
+ toolBtns.forEach(btn => {
|
|
|
+ btn.addEventListener('click', () => {
|
|
|
+ currentTool = btn.dataset.tool;
|
|
|
+ toolBtns.forEach(b => b.classList.remove('active'));
|
|
|
+ btn.classList.add('active');
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 撤销/重做按钮
|
|
|
+ document.getElementById('undoBtn').addEventListener('click', undo);
|
|
|
+ document.getElementById('redoBtn').addEventListener('click', redo);
|
|
|
+
|
|
|
+ // 保存编辑
|
|
|
+ document.getElementById('saveEditBtn').addEventListener('click', saveEdit);
|
|
|
+}
|
|
|
+
|
|
|
+// 打开编辑界面
|
|
|
+function openEditScreen() {
|
|
|
+ const avatarCanvas = document.getElementById('avatarCanvas');
|
|
|
+ const editCanvas = document.getElementById('editCanvas');
|
|
|
+ const ctx = editCanvas.getContext('2d');
|
|
|
+
|
|
|
+ // 设置编辑画布大小与生成画布一致
|
|
|
+ editCanvas.width = avatarCanvas.width;
|
|
|
+ editCanvas.height = avatarCanvas.height;
|
|
|
+
|
|
|
+ // 复制当前头像到编辑画布
|
|
|
+ ctx.drawImage(avatarCanvas, 0, 0);
|
|
|
+
|
|
|
+ // 初始化编辑工具
|
|
|
+ currentTool = 'brush';
|
|
|
+ currentColor = '#000000';
|
|
|
+ currentBrushSize = 1;
|
|
|
+
|
|
|
+ // 重置历史记录
|
|
|
+ history = [];
|
|
|
+ historyIndex = -1;
|
|
|
+ saveToHistory();
|
|
|
+
|
|
|
+ // 设置画布事件监听
|
|
|
+ setupCanvasEventListeners();
|
|
|
+
|
|
|
+ // 显示编辑界面
|
|
|
+ showScreen('edit-screen');
|
|
|
+}
|
|
|
+
|
|
|
+// 设置画布事件监听
|
|
|
+function setupCanvasEventListeners() {
|
|
|
+ const canvas = document.getElementById('editCanvas');
|
|
|
+
|
|
|
+ // 移除旧的事件监听
|
|
|
+ canvas.removeEventListener('mousedown', startDrawing);
|
|
|
+ canvas.removeEventListener('mousemove', draw);
|
|
|
+ canvas.removeEventListener('mouseup', stopDrawing);
|
|
|
+ canvas.removeEventListener('mouseout', stopDrawing);
|
|
|
+
|
|
|
+ canvas.removeEventListener('touchstart', startDrawing);
|
|
|
+ canvas.removeEventListener('touchmove', draw);
|
|
|
+ canvas.removeEventListener('touchend', stopDrawing);
|
|
|
+
|
|
|
+ // 添加新的事件监听
|
|
|
+ canvas.addEventListener('mousedown', startDrawing);
|
|
|
+ canvas.addEventListener('mousemove', draw);
|
|
|
+ canvas.addEventListener('mouseup', stopDrawing);
|
|
|
+ canvas.addEventListener('mouseout', stopDrawing);
|
|
|
+
|
|
|
+ canvas.addEventListener('touchstart', startDrawing);
|
|
|
+ canvas.addEventListener('touchmove', draw);
|
|
|
+ canvas.addEventListener('touchend', stopDrawing);
|
|
|
+}
|
|
|
+
|
|
|
+// 开始绘制
|
|
|
+function startDrawing(e) {
|
|
|
+ isDrawing = true;
|
|
|
+ draw(e);
|
|
|
+}
|
|
|
+
|
|
|
+// 绘制
|
|
|
+function draw(e) {
|
|
|
+ if (!isDrawing) return;
|
|
|
+
|
|
|
+ const canvas = document.getElementById('editCanvas');
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+
|
|
|
+ // 获取鼠标/触摸位置
|
|
|
+ let rect = canvas.getBoundingClientRect();
|
|
|
+ let x, y;
|
|
|
+
|
|
|
+ if (e.type.startsWith('mouse')) {
|
|
|
+ x = e.clientX - rect.left;
|
|
|
+ y = e.clientY - rect.top;
|
|
|
+ } else {
|
|
|
+ e.preventDefault();
|
|
|
+ x = e.touches[0].clientX - rect.left;
|
|
|
+ y = e.touches[0].clientY - rect.top;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换为像素坐标(对齐到像素网格)
|
|
|
+ x = Math.floor(x / currentPixelSize) * currentPixelSize;
|
|
|
+ y = Math.floor(y / currentPixelSize) * currentPixelSize;
|
|
|
+
|
|
|
+ // 根据工具执行不同操作
|
|
|
+ switch (currentTool) {
|
|
|
+ case 'brush':
|
|
|
+ drawBrush(ctx, x, y);
|
|
|
+ break;
|
|
|
+ case 'eraser':
|
|
|
+ drawEraser(ctx, x, y);
|
|
|
+ break;
|
|
|
+ case 'fill':
|
|
|
+ fillBucket(ctx, x, y);
|
|
|
+ isDrawing = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 停止绘制
|
|
|
+function stopDrawing() {
|
|
|
+ if (isDrawing) {
|
|
|
+ isDrawing = false;
|
|
|
+ saveToHistory();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 画笔绘制
|
|
|
+function drawBrush(ctx, x, y) {
|
|
|
+ ctx.fillStyle = currentColor;
|
|
|
+ ctx.fillRect(x, y, currentBrushSize * currentPixelSize, currentBrushSize * currentPixelSize);
|
|
|
+}
|
|
|
+
|
|
|
+// 橡皮擦绘制
|
|
|
+function drawEraser(ctx, x, y) {
|
|
|
+ ctx.clearRect(x, y, currentBrushSize * currentPixelSize, currentBrushSize * currentPixelSize);
|
|
|
+}
|
|
|
+
|
|
|
+// 填充工具
|
|
|
+function fillBucket(ctx, x, y) {
|
|
|
+ const canvas = ctx.canvas;
|
|
|
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
|
+ const data = imageData.data;
|
|
|
+
|
|
|
+ const targetColor = getPixelColor(data, x, y, canvas.width);
|
|
|
+ const fillColor = hexToRgb(currentColor);
|
|
|
+
|
|
|
+ if (colorsMatch(targetColor, fillColor)) return;
|
|
|
+
|
|
|
+ const stack = [{x, y}];
|
|
|
+
|
|
|
+ while (stack.length > 0) {
|
|
|
+ const pixel = stack.pop();
|
|
|
+ const currentPixelColor = getPixelColor(data, pixel.x, pixel.y, canvas.width);
|
|
|
+
|
|
|
+ if (colorsMatch(currentPixelColor, targetColor)) {
|
|
|
+ setPixelColor(data, pixel.x, pixel.y, fillColor, canvas.width);
|
|
|
+
|
|
|
+ // 检查相邻像素
|
|
|
+ if (pixel.x > 0) stack.push({x: pixel.x - currentPixelSize, y: pixel.y});
|
|
|
+ if (pixel.x < canvas.width - currentPixelSize) stack.push({x: pixel.x + currentPixelSize, y: pixel.y});
|
|
|
+ if (pixel.y > 0) stack.push({x: pixel.x, y: pixel.y - currentPixelSize});
|
|
|
+ if (pixel.y < canvas.height - currentPixelSize) stack.push({x: pixel.x, y: pixel.y + currentPixelSize});
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ctx.putImageData(imageData, 0, 0);
|
|
|
+}
|
|
|
+
|
|
|
+// 获取像素颜色
|
|
|
+function getPixelColor(data, x, y, width) {
|
|
|
+ const index = (y * width + x) * 4;
|
|
|
+ return {
|
|
|
+ r: data[index],
|
|
|
+ g: data[index + 1],
|
|
|
+ b: data[index + 2],
|
|
|
+ a: data[index + 3]
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+// 设置像素颜色
|
|
|
+function setPixelColor(data, x, y, color, width) {
|
|
|
+ const index = (y * width + x) * 4;
|
|
|
+ data[index] = color.r;
|
|
|
+ data[index + 1] = color.g;
|
|
|
+ data[index + 2] = color.b;
|
|
|
+ data[index + 3] = 255; // 不透明
|
|
|
+}
|
|
|
+
|
|
|
+// 颜色匹配
|
|
|
+function colorsMatch(color1, color2) {
|
|
|
+ return color1.r === color2.r && color1.g === color2.g && color1.b === color2.b;
|
|
|
+}
|
|
|
+
|
|
|
+// 十六进制转RGB
|
|
|
+function hexToRgb(hex) {
|
|
|
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
|
+ return result ? {
|
|
|
+ r: parseInt(result[1], 16),
|
|
|
+ g: parseInt(result[2], 16),
|
|
|
+ b: parseInt(result[3], 16)
|
|
|
+ } : null;
|
|
|
+}
|
|
|
+
|
|
|
+// 保存到历史记录
|
|
|
+function saveToHistory() {
|
|
|
+ const canvas = document.getElementById('editCanvas');
|
|
|
+ const dataURL = canvas.toDataURL();
|
|
|
+
|
|
|
+ // 移除当前索引之后的历史记录
|
|
|
+ if (historyIndex < history.length - 1) {
|
|
|
+ history = history.slice(0, historyIndex + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ history.push(dataURL);
|
|
|
+ historyIndex = history.length - 1;
|
|
|
+}
|
|
|
+
|
|
|
+// 撤销
|
|
|
+function undo() {
|
|
|
+ if (historyIndex > 0) {
|
|
|
+ historyIndex--;
|
|
|
+ loadFromHistory();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 重做
|
|
|
+function redo() {
|
|
|
+ if (historyIndex < history.length - 1) {
|
|
|
+ historyIndex++;
|
|
|
+ loadFromHistory();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 从历史记录加载
|
|
|
+function loadFromHistory() {
|
|
|
+ const canvas = document.getElementById('editCanvas');
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+ const img = new Image();
|
|
|
+
|
|
|
+ img.onload = function() {
|
|
|
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
+ ctx.drawImage(img, 0, 0);
|
|
|
+ };
|
|
|
+
|
|
|
+ img.src = history[historyIndex];
|
|
|
+}
|
|
|
+
|
|
|
+// 保存编辑
|
|
|
+function saveEdit() {
|
|
|
+ const editCanvas = document.getElementById('editCanvas');
|
|
|
+ const avatarCanvas = document.getElementById('avatarCanvas');
|
|
|
+ const ctx = avatarCanvas.getContext('2d');
|
|
|
+
|
|
|
+ // 设置生成画布大小与编辑画布一致
|
|
|
+ avatarCanvas.width = editCanvas.width;
|
|
|
+ avatarCanvas.height = editCanvas.height;
|
|
|
+
|
|
|
+ // 复制编辑后的头像回生成画布
|
|
|
+ ctx.drawImage(editCanvas, 0, 0);
|
|
|
+
|
|
|
+ // 返回生成界面
|
|
|
+ showScreen('generate-screen');
|
|
|
+ document.getElementById('nav-generate').classList.add('active');
|
|
|
+
|
|
|
+ alert('编辑已保存!');
|
|
|
+}
|
|
|
+
|
|
|
+// 设置种子相关按钮
|
|
|
+function setupSeedButtons() {
|
|
|
+ const seedInput = document.getElementById('seedInput');
|
|
|
+ const copySeedBtn = document.getElementById('copySeedBtn');
|
|
|
+ const randomSeedBtn = document.getElementById('randomSeedBtn');
|
|
|
+
|
|
|
+ // 种子输入事件
|
|
|
+ seedInput.addEventListener('input', (e) => {
|
|
|
+ setSeed(e.target.value);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 复制种子按钮
|
|
|
+ copySeedBtn.addEventListener('click', () => {
|
|
|
+ const seedText = seedInput.value;
|
|
|
+ if (seedText) {
|
|
|
+ navigator.clipboard.writeText(seedText).then(() => {
|
|
|
+ alert('种子已复制到剪贴板!');
|
|
|
+ }).catch(err => {
|
|
|
+ console.error('复制失败:', err);
|
|
|
+ alert('复制失败,请手动复制');
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ alert('没有可复制的种子');
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 生成随机种子按钮
|
|
|
+ randomSeedBtn.addEventListener('click', () => {
|
|
|
+ const randomSeed = generateRandomSeed();
|
|
|
+ seedInput.value = randomSeed;
|
|
|
+ setSeed(randomSeed);
|
|
|
+ generateAvatar();
|
|
|
+ });
|
|
|
+
|
|
|
+ // 当重新生成头像时,如果没有种子则生成一个
|
|
|
+ document.getElementById('regenerateBtn').addEventListener('click', () => {
|
|
|
+ if (!seedInput.value.trim()) {
|
|
|
+ const randomSeed = generateRandomSeed();
|
|
|
+ seedInput.value = randomSeed;
|
|
|
+ setSeed(randomSeed);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 设置社交媒体格式
|
|
|
+function setSocialMediaFormat(format) {
|
|
|
+ currentSocialMediaFormat = format;
|
|
|
+
|
|
|
+ // 设置为对应社交媒体格式的尺寸
|
|
|
+ currentCanvasSize = socialMediaFormats[currentSocialMediaFormat];
|
|
|
+
|
|
|
+ // 更新设置界面中的选择器
|
|
|
+ const canvasSizeSelect = document.getElementById('canvasSize');
|
|
|
+ const socialMediaFormatSelect = document.getElementById('socialMediaFormat');
|
|
|
+
|
|
|
+ canvasSizeSelect.value = currentCanvasSize;
|
|
|
+ socialMediaFormatSelect.value = currentSocialMediaFormat;
|
|
|
+
|
|
|
+ // 更新画布大小
|
|
|
+ updateCanvasSize();
|
|
|
+
|
|
|
+ // 重新生成头像
|
|
|
+ generateAvatar();
|
|
|
+
|
|
|
+ // 更新社交媒体格式按钮的激活状态
|
|
|
+ const socialBtns = document.querySelectorAll('.social-options .theme-btn');
|
|
|
+ socialBtns.forEach(btn => {
|
|
|
+ btn.classList.remove('active');
|
|
|
+ if (btn.dataset.format === format) {
|
|
|
+ btn.classList.add('active');
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 更新画布大小
|
|
|
+function updateCanvasSize() {
|
|
|
+ const canvas = document.getElementById('avatarCanvas');
|
|
|
+ canvas.width = currentCanvasSize;
|
|
|
+ canvas.height = currentCanvasSize;
|
|
|
+}
|
|
|
+
|
|
|
+// 生成头像
|
|
|
+function generateAvatar() {
|
|
|
+ const canvas = document.getElementById('avatarCanvas');
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+
|
|
|
+ // 如果有种子输入但未设置,先设置种子
|
|
|
+ const seedInput = document.getElementById('seedInput');
|
|
|
+ if (seedInput && seedInput.value && seedInput.value.trim() !== '') {
|
|
|
+ setSeed(seedInput.value);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空画布
|
|
|
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
+
|
|
|
+ // 绘制背景
|
|
|
+ ctx.fillStyle = getRandomColor();
|
|
|
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
+
|
|
|
+ // 根据风格生成头像
|
|
|
+ switch(currentStyle) {
|
|
|
+ case 'cartoon':
|
|
|
+ drawCartoonStyle(ctx);
|
|
|
+ break;
|
|
|
+ case 'pixelart':
|
|
|
+ drawPixelArtStyle(ctx);
|
|
|
+ break;
|
|
|
+ case 'minimal':
|
|
|
+ drawMinimalStyle(ctx);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存到历史记录
|
|
|
+ saveAvatarToHistory();
|
|
|
+}
|
|
|
+
|
|
|
+// 生成特定细节的头像
|
|
|
+function generateAvatarWithFocus(focus) {
|
|
|
+ const canvas = document.getElementById('avatarCanvas');
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+
|
|
|
+ // 保存当前头像
|
|
|
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
|
+
|
|
|
+ // 重新生成
|
|
|
+ generateAvatar();
|
|
|
+
|
|
|
+ // 根据焦点重新绘制特定部分
|
|
|
+ switch(focus) {
|
|
|
+ case 'eyes':
|
|
|
+ drawEyes(ctx);
|
|
|
+ break;
|
|
|
+ case 'nose':
|
|
|
+ drawNose(ctx);
|
|
|
+ break;
|
|
|
+ case 'mouth':
|
|
|
+ drawMouth(ctx);
|
|
|
+ break;
|
|
|
+ case 'accessories':
|
|
|
+ drawAccessories(ctx);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 基于种子的随机数生成器
|
|
|
+function seededRandom(seed) {
|
|
|
+ let x = Math.sin(seed) * 10000;
|
|
|
+ return x - Math.floor(x);
|
|
|
+}
|
|
|
+
|
|
|
+// 获取当前随机数生成器
|
|
|
+function getRandom() {
|
|
|
+ if (useSeed && currentSeed !== null) {
|
|
|
+ currentSeed = (currentSeed + 0.123456789) % 1;
|
|
|
+ return seededRandom(currentSeed);
|
|
|
+ }
|
|
|
+ return Math.random();
|
|
|
+}
|
|
|
+
|
|
|
+// 设置随机种子
|
|
|
+function setSeed(seed) {
|
|
|
+ if (seed && seed.trim() !== '') {
|
|
|
+ // 将字符串种子转换为数字
|
|
|
+ let numSeed = 0;
|
|
|
+ for (let i = 0; i < seed.length; i++) {
|
|
|
+ numSeed += seed.charCodeAt(i) * Math.pow(31, i);
|
|
|
+ }
|
|
|
+ currentSeed = numSeed % 1;
|
|
|
+ useSeed = true;
|
|
|
+ } else {
|
|
|
+ useSeed = false;
|
|
|
+ currentSeed = null;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 生成随机种子字符串
|
|
|
+function generateRandomSeed() {
|
|
|
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
|
+ let result = '';
|
|
|
+ for (let i = 0; i < 10; i++) {
|
|
|
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+// 获取随机颜色
|
|
|
+function getRandomColor() {
|
|
|
+ const colors = colorThemes[currentTheme];
|
|
|
+ return colors[Math.floor(getRandom() * colors.length)];
|
|
|
+}
|
|
|
+
|
|
|
+// 卡通风格
|
|
|
+function drawCartoonStyle(ctx) {
|
|
|
+ const centerX = ctx.canvas.width / 2;
|
|
|
+ const centerY = ctx.canvas.height / 2;
|
|
|
+ const size = Math.min(ctx.canvas.width, ctx.canvas.height) * 0.8;
|
|
|
+
|
|
|
+ // 头部
|
|
|
+ ctx.fillStyle = getRandomColor();
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(centerX, centerY, size / 2, 0, Math.PI * 2);
|
|
|
+ ctx.fill();
|
|
|
+
|
|
|
+ drawEyes(ctx);
|
|
|
+ drawNose(ctx);
|
|
|
+ drawMouth(ctx);
|
|
|
+ drawAccessories(ctx);
|
|
|
+}
|
|
|
+
|
|
|
+// 像素艺术风格
|
|
|
+function drawPixelArtStyle(ctx) {
|
|
|
+ const gridSize = currentPixelSize;
|
|
|
+ const cols = Math.floor(ctx.canvas.width / gridSize);
|
|
|
+ const rows = Math.floor(ctx.canvas.height / gridSize);
|
|
|
+
|
|
|
+ // 头部轮廓
|
|
|
+ for (let y = 2; y < rows - 2; y++) {
|
|
|
+ for (let x = 2; x < cols - 2; x++) {
|
|
|
+ if ((x === 2 || x === cols - 3) && (y > 4 && y < rows - 5)) continue;
|
|
|
+ if (Math.abs(x - cols/2) + Math.abs(y - rows/2) < rows/2 - 1) {
|
|
|
+ ctx.fillStyle = getRandomColor();
|
|
|
+ ctx.fillRect(x * gridSize, y * gridSize, gridSize, gridSize);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 眼睛
|
|
|
+ drawPixelEyes(ctx, gridSize, cols, rows);
|
|
|
+
|
|
|
+ // 嘴巴
|
|
|
+ drawPixelMouth(ctx, gridSize, cols, rows);
|
|
|
+}
|
|
|
+
|
|
|
+// 简约风格
|
|
|
+function drawMinimalStyle(ctx) {
|
|
|
+ const centerX = ctx.canvas.width / 2;
|
|
|
+ const centerY = ctx.canvas.height / 2;
|
|
|
+ const size = Math.min(ctx.canvas.width, ctx.canvas.height) * 0.6;
|
|
|
+
|
|
|
+ // 头部
|
|
|
+ ctx.fillStyle = getRandomColor();
|
|
|
+ ctx.fillRect(centerX - size/2, centerY - size/2, size, size);
|
|
|
+
|
|
|
+ // 眼睛
|
|
|
+ const eyeSize = size * 0.1;
|
|
|
+ ctx.fillStyle = '#000000';
|
|
|
+ ctx.fillRect(centerX - size/4 - eyeSize/2, centerY - size/6, eyeSize, eyeSize);
|
|
|
+ ctx.fillRect(centerX + size/4 - eyeSize/2, centerY - size/6, eyeSize, eyeSize);
|
|
|
+
|
|
|
+ // 嘴巴
|
|
|
+ ctx.fillRect(centerX - size/6, centerY + size/6, size/3, eyeSize/2);
|
|
|
+}
|
|
|
+
|
|
|
+// 绘制眼睛
|
|
|
+function drawEyes(ctx) {
|
|
|
+ const centerX = ctx.canvas.width / 2;
|
|
|
+ const centerY = ctx.canvas.height / 2;
|
|
|
+ const eyeSize = Math.min(ctx.canvas.width, ctx.canvas.height) * 0.15;
|
|
|
+
|
|
|
+ ctx.fillStyle = '#FFFFFF';
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(centerX - eyeSize * 1.5, centerY - eyeSize/2, eyeSize, 0, Math.PI * 2);
|
|
|
+ ctx.arc(centerX + eyeSize * 1.5, centerY - eyeSize/2, eyeSize, 0, Math.PI * 2);
|
|
|
+ ctx.fill();
|
|
|
+
|
|
|
+ ctx.fillStyle = '#000000';
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(centerX - eyeSize * 1.5, centerY - eyeSize/2, eyeSize * 0.4, 0, Math.PI * 2);
|
|
|
+ ctx.arc(centerX + eyeSize * 1.5, centerY - eyeSize/2, eyeSize * 0.4, 0, Math.PI * 2);
|
|
|
+ ctx.fill();
|
|
|
+}
|
|
|
+
|
|
|
+// 绘制鼻子
|
|
|
+function drawNose(ctx) {
|
|
|
+ const centerX = ctx.canvas.width / 2;
|
|
|
+ const centerY = ctx.canvas.height / 2;
|
|
|
+ const noseSize = Math.min(ctx.canvas.width, ctx.canvas.height) * 0.08;
|
|
|
+
|
|
|
+ ctx.fillStyle = getRandomColor();
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(centerX, centerY, noseSize, 0, Math.PI * 2);
|
|
|
+ ctx.fill();
|
|
|
+}
|
|
|
+
|
|
|
+// 绘制嘴巴
|
|
|
+function drawMouth(ctx) {
|
|
|
+ const centerX = ctx.canvas.width / 2;
|
|
|
+ const centerY = ctx.canvas.height / 2;
|
|
|
+ const mouthSize = Math.min(ctx.canvas.width, ctx.canvas.height) * 0.25;
|
|
|
+
|
|
|
+ ctx.fillStyle = '#FF0000';
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(centerX, centerY + mouthSize/3, mouthSize/2, 0, Math.PI);
|
|
|
+ ctx.fill();
|
|
|
+}
|
|
|
+
|
|
|
+// 绘制装饰
|
|
|
+function drawAccessories(ctx) {
|
|
|
+ const centerX = ctx.canvas.width / 2;
|
|
|
+ const centerY = ctx.canvas.height / 2;
|
|
|
+ const size = Math.min(ctx.canvas.width, ctx.canvas.height) * 0.8;
|
|
|
+
|
|
|
+ // 随机添加装饰
|
|
|
+ const accessoryType = Math.floor(getRandom() * 3);
|
|
|
+
|
|
|
+ switch(accessoryType) {
|
|
|
+ case 0: // 帽子
|
|
|
+ ctx.fillStyle = getRandomColor();
|
|
|
+ ctx.fillRect(centerX - size/3, centerY - size/2 - size/6, size * 2/3, size/6);
|
|
|
+ ctx.fillRect(centerX - size/2.5, centerY - size/2, size * 2/5, size/10);
|
|
|
+ break;
|
|
|
+ case 1: // 眼镜
|
|
|
+ ctx.strokeStyle = getRandomColor();
|
|
|
+ ctx.lineWidth = 3;
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(centerX - size/4, centerY - size/6, size/8, 0, Math.PI * 2);
|
|
|
+ ctx.arc(centerX + size/4, centerY - size/6, size/8, 0, Math.PI * 2);
|
|
|
+ ctx.stroke();
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.moveTo(centerX - size/8, centerY - size/6);
|
|
|
+ ctx.lineTo(centerX + size/8, centerY - size/6);
|
|
|
+ ctx.stroke();
|
|
|
+ break;
|
|
|
+ case 2: // 耳朵
|
|
|
+ ctx.fillStyle = getRandomColor();
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(centerX - size/2, centerY, size/6, 0, Math.PI * 2);
|
|
|
+ ctx.arc(centerX + size/2, centerY, size/6, 0, Math.PI * 2);
|
|
|
+ ctx.fill();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 绘制像素风格眼睛
|
|
|
+function drawPixelEyes(ctx, gridSize, cols, rows) {
|
|
|
+ const centerX = cols / 2;
|
|
|
+ const centerY = rows / 2;
|
|
|
+
|
|
|
+ ctx.fillStyle = '#FFFFFF';
|
|
|
+ // 左眼
|
|
|
+ for (let y = centerY - 2; y <= centerY + 1; y++) {
|
|
|
+ for (let x = centerX - 4; x <= centerX - 2; x++) {
|
|
|
+ ctx.fillRect(x * gridSize, y * gridSize, gridSize, gridSize);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 右眼
|
|
|
+ for (let y = centerY - 2; y <= centerY + 1; y++) {
|
|
|
+ for (let x = centerX + 2; x <= centerX + 4; x++) {
|
|
|
+ ctx.fillRect(x * gridSize, y * gridSize, gridSize, gridSize);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ctx.fillStyle = '#000000';
|
|
|
+ // 左瞳孔
|
|
|
+ ctx.fillRect((centerX - 3) * gridSize, centerY * gridSize, gridSize, gridSize);
|
|
|
+ // 右瞳孔
|
|
|
+ ctx.fillRect((centerX + 3) * gridSize, centerY * gridSize, gridSize, gridSize);
|
|
|
+}
|
|
|
+
|
|
|
+// 绘制像素风格嘴巴
|
|
|
+function drawPixelMouth(ctx, gridSize, cols, rows) {
|
|
|
+ const centerX = cols / 2;
|
|
|
+ const centerY = rows / 2;
|
|
|
+
|
|
|
+ ctx.fillStyle = '#FF0000';
|
|
|
+ for (let x = centerX - 3; x <= centerX + 3; x++) {
|
|
|
+ ctx.fillRect(x * gridSize, (centerY + 3) * gridSize, gridSize, gridSize);
|
|
|
+ }
|
|
|
+ for (let x = centerX - 2; x <= centerX + 2; x++) {
|
|
|
+ ctx.fillRect(x * gridSize, (centerY + 4) * gridSize, gridSize, gridSize);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 保存头像
|
|
|
+function saveAvatar() {
|
|
|
+ const canvas = document.getElementById('avatarCanvas');
|
|
|
+ const dataURL = canvas.toDataURL('image/png');
|
|
|
+
|
|
|
+ // 如果自动保存开启,则保存到本地
|
|
|
+ if (document.getElementById('autoSave').checked) {
|
|
|
+ localStorage.setItem('lastAvatar', dataURL);
|
|
|
+ alert('头像已保存!');
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 添加到收藏
|
|
|
+function addToFavorites() {
|
|
|
+ const canvas = document.getElementById('avatarCanvas');
|
|
|
+ const dataURL = canvas.toDataURL('image/png');
|
|
|
+
|
|
|
+ // 检查是否已存在
|
|
|
+ const exists = favorites.some(fav => fav.dataURL === dataURL);
|
|
|
+ if (exists) {
|
|
|
+ alert('该头像已在收藏中!');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ favorites.push({
|
|
|
+ id: Date.now(),
|
|
|
+ dataURL: dataURL,
|
|
|
+ timestamp: new Date().toISOString()
|
|
|
+ });
|
|
|
+
|
|
|
+ localStorage.setItem('favorites', JSON.stringify(favorites));
|
|
|
+ loadFavorites();
|
|
|
+ alert('头像已添加到收藏!');
|
|
|
+}
|
|
|
+
|
|
|
+// 下载头像
|
|
|
+function downloadAvatar() {
|
|
|
+ const canvas = document.getElementById('avatarCanvas');
|
|
|
+ const link = document.createElement('a');
|
|
|
+ link.download = `pixel-avatar-${Date.now()}.png`;
|
|
|
+ link.href = canvas.toDataURL('image/png');
|
|
|
+ link.click();
|
|
|
+}
|
|
|
+
|
|
|
+// 加载收藏
|
|
|
+function loadFavorites() {
|
|
|
+ const grid = document.getElementById('favorites-grid');
|
|
|
+ grid.innerHTML = '';
|
|
|
+
|
|
|
+ if (favorites.length === 0) {
|
|
|
+ grid.innerHTML = '<p style="text-align: center; padding: 20px;">暂无收藏</p>';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ favorites.forEach(fav => {
|
|
|
+ const item = document.createElement('div');
|
|
|
+ item.className = 'favorite-item';
|
|
|
+
|
|
|
+ const img = document.createElement('img');
|
|
|
+ img.src = fav.dataURL;
|
|
|
+ img.alt = '收藏的头像';
|
|
|
+
|
|
|
+ const removeBtn = document.createElement('button');
|
|
|
+ removeBtn.className = 'remove-favorite';
|
|
|
+ removeBtn.textContent = '×';
|
|
|
+ removeBtn.addEventListener('click', () => removeFavorite(fav.id));
|
|
|
+
|
|
|
+ item.appendChild(img);
|
|
|
+ item.appendChild(removeBtn);
|
|
|
+ grid.appendChild(item);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 移除收藏
|
|
|
+function removeFavorite(id) {
|
|
|
+ favorites = favorites.filter(fav => fav.id !== id);
|
|
|
+ localStorage.setItem('favorites', JSON.stringify(favorites));
|
|
|
+ loadFavorites();
|
|
|
+}
|
|
|
+
|
|
|
+// 自动保存
|
|
|
+window.addEventListener('beforeunload', () => {
|
|
|
+ if (document.getElementById('autoSave').checked) {
|
|
|
+ saveAvatar();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+// 保存头像到历史记录
|
|
|
+function saveAvatarToHistory() {
|
|
|
+ const canvas = document.getElementById('avatarCanvas');
|
|
|
+ const dataURL = canvas.toDataURL('image/png');
|
|
|
+ const seedInput = document.getElementById('seedInput');
|
|
|
+ const seed = seedInput.value || 'random';
|
|
|
+
|
|
|
+ // 检查是否与最近的历史记录相同
|
|
|
+ if (avatarHistory.length > 0 && avatarHistory[0].dataURL === dataURL) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加新记录到历史
|
|
|
+ avatarHistory.unshift({
|
|
|
+ id: Date.now(),
|
|
|
+ dataURL: dataURL,
|
|
|
+ seed: seed,
|
|
|
+ timestamp: new Date().toISOString()
|
|
|
+ });
|
|
|
+
|
|
|
+ // 限制历史记录数量
|
|
|
+ if (avatarHistory.length > maxHistoryItems) {
|
|
|
+ avatarHistory = avatarHistory.slice(0, maxHistoryItems);
|
|
|
+ }
|
|
|
+
|
|
|
+ localStorage.setItem('avatarHistory', JSON.stringify(avatarHistory));
|
|
|
+
|
|
|
+ // 如果当前在历史记录界面,更新显示
|
|
|
+ if (document.getElementById('history-screen').classList.contains('active')) {
|
|
|
+ loadHistory();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 加载历史记录
|
|
|
+function loadHistory() {
|
|
|
+ const grid = document.getElementById('history-grid');
|
|
|
+ grid.innerHTML = '';
|
|
|
+
|
|
|
+ if (avatarHistory.length === 0) {
|
|
|
+ grid.innerHTML = '<p style="text-align: center; padding: 20px;">暂无历史记录</p>';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ avatarHistory.forEach(item => {
|
|
|
+ const historyItem = document.createElement('div');
|
|
|
+ historyItem.className = 'favorite-item';
|
|
|
+
|
|
|
+ const img = document.createElement('img');
|
|
|
+ img.src = item.dataURL;
|
|
|
+ img.alt = `历史头像 ${new Date(item.timestamp).toLocaleString()}`;
|
|
|
+
|
|
|
+ // 添加点击事件,可查看详细信息
|
|
|
+ img.addEventListener('click', () => {
|
|
|
+ // 将历史记录中的头像恢复到生成界面
|
|
|
+ const avatarCanvas = document.getElementById('avatarCanvas');
|
|
|
+ const ctx = avatarCanvas.getContext('2d');
|
|
|
+ const historyImg = new Image();
|
|
|
+ historyImg.onload = function() {
|
|
|
+ avatarCanvas.width = historyImg.width;
|
|
|
+ avatarCanvas.height = historyImg.height;
|
|
|
+ ctx.drawImage(historyImg, 0, 0);
|
|
|
+
|
|
|
+ // 设置种子
|
|
|
+ const seedInput = document.getElementById('seedInput');
|
|
|
+ seedInput.value = item.seed;
|
|
|
+ if (item.seed !== 'random') {
|
|
|
+ setSeed(item.seed);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 切换到生成界面
|
|
|
+ showScreen('generate-screen');
|
|
|
+ document.getElementById('nav-generate').classList.add('active');
|
|
|
+ document.getElementById('nav-history').classList.remove('active');
|
|
|
+ };
|
|
|
+ historyImg.src = item.dataURL;
|
|
|
+ });
|
|
|
+
|
|
|
+ historyItem.appendChild(img);
|
|
|
+ grid.appendChild(historyItem);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 清空历史记录
|
|
|
+function clearHistory() {
|
|
|
+ if (confirm('确定要清空所有历史记录吗?')) {
|
|
|
+ avatarHistory = [];
|
|
|
+ localStorage.removeItem('avatarHistory');
|
|
|
+ loadHistory();
|
|
|
+ alert('历史记录已清空!');
|
|
|
+ }
|
|
|
+}
|