You've already forked Nano-Banana-AI-Image-Editor
新增 连续生成功能;
添加了自动化测试套件;
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import React, { useRef, useEffect, useState, useCallback } from 'react';
|
||||
import { Stage, Layer, Image as KonvaImage, Line } from 'react-konva';
|
||||
import type { KonvaEventObject } from 'konva/lib/Node';
|
||||
import { useAppStore } from '../store/useAppStore';
|
||||
import { Button } from './ui/Button';
|
||||
import { ZoomIn, ZoomOut, RotateCcw, Download } from 'lucide-react';
|
||||
@@ -8,7 +9,7 @@ export const ImageCanvas: React.FC = () => {
|
||||
const {
|
||||
canvasImage,
|
||||
canvasZoom,
|
||||
canvasPan,
|
||||
// canvasPan,
|
||||
setCanvasZoom,
|
||||
setCanvasPan,
|
||||
brushStrokes,
|
||||
@@ -16,6 +17,8 @@ export const ImageCanvas: React.FC = () => {
|
||||
showMasks,
|
||||
selectedTool,
|
||||
isGenerating,
|
||||
isContinuousGenerating,
|
||||
retryCount,
|
||||
brushSize,
|
||||
showHistory,
|
||||
showPromptPanel
|
||||
@@ -296,14 +299,16 @@ export const ImageCanvas: React.FC = () => {
|
||||
return () => container.removeEventListener('wheel', handleWheel);
|
||||
}, [canvasZoom, handleZoom]);
|
||||
|
||||
const handleMouseDown = (e: Konva.KonvaEventObject<MouseEvent>) => {
|
||||
const handleMouseDown = (e: KonvaEventObject<MouseEvent>) => {
|
||||
if (selectedTool !== 'mask' || !image) return;
|
||||
|
||||
setIsDrawing(true);
|
||||
const stage = e.target.getStage();
|
||||
if (!stage) return;
|
||||
|
||||
// 使用 Konva 的 getRelativePointerPosition 获取准确坐标
|
||||
const relativePos = stage.getRelativePointerPosition();
|
||||
if (!relativePos) return;
|
||||
|
||||
// 计算图像在舞台上的边界
|
||||
const imageX = (stageSize.width / canvasZoom - image.width) / 2;
|
||||
@@ -319,13 +324,15 @@ export const ImageCanvas: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseMove = (e: Konva.KonvaEventObject<MouseEvent>) => {
|
||||
const handleMouseMove = (e: KonvaEventObject<MouseEvent>) => {
|
||||
if (!isDrawing || selectedTool !== 'mask' || !image) return;
|
||||
|
||||
const stage = e.target.getStage();
|
||||
if (!stage) return;
|
||||
|
||||
// 使用 Konva 的 getRelativePointerPosition 获取准确坐标
|
||||
const relativePos = stage.getRelativePointerPosition();
|
||||
if (!relativePos) return;
|
||||
|
||||
// 计算图像在舞台上的边界
|
||||
const imageX = (stageSize.width / canvasZoom - image.width) / 2;
|
||||
@@ -353,6 +360,7 @@ export const ImageCanvas: React.FC = () => {
|
||||
id: `stroke-${Date.now()}`,
|
||||
points: currentStroke,
|
||||
brushSize,
|
||||
color: '#A855F7',
|
||||
});
|
||||
setCurrentStroke([]);
|
||||
};
|
||||
@@ -424,12 +432,14 @@ export const ImageCanvas: React.FC = () => {
|
||||
console.error('下载图像失败:', error);
|
||||
// 如果fetch失败,回退到直接使用a标签
|
||||
const link = document.createElement('a');
|
||||
link.href = uploadResult.url;
|
||||
link.download = `nano-banana-${Date.now()}.png`;
|
||||
link.target = '_blank';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
if (uploadResult.url) {
|
||||
link.href = uploadResult.url;
|
||||
link.download = `nano-banana-${Date.now()}.png`;
|
||||
link.target = '_blank';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
});
|
||||
|
||||
// 立即返回
|
||||
@@ -571,6 +581,12 @@ export const ImageCanvas: React.FC = () => {
|
||||
<div className="text-center bg-white/90 rounded-xl p-6 card-lg backdrop-blur-sm animate-in scale-in duration-200">
|
||||
<div className="animate-spin rounded-full h-10 w-10 border-2 border-yellow-400 border-t-transparent mx-auto mb-3" />
|
||||
<p className="text-gray-700 text-sm font-medium">正在创建图像...</p>
|
||||
{/* 显示重试次数 */}
|
||||
{isContinuousGenerating && (
|
||||
<p className="text-gray-500 text-xs mt-2">
|
||||
重试次数: {retryCount}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -592,8 +608,8 @@ export const ImageCanvas: React.FC = () => {
|
||||
}
|
||||
}}
|
||||
onMouseDown={handleMouseDown}
|
||||
onMousemove={handleMouseMove}
|
||||
onMouseup={handleMouseUp}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseUp={handleMouseUp}
|
||||
style={{
|
||||
cursor: selectedTool === 'mask' ? 'crosshair' : 'default',
|
||||
zIndex: 10
|
||||
|
||||
Reference in New Issue
Block a user