fix: image progress display

This commit is contained in:
jialin
2025-01-15 09:51:29 +08:00
parent 35991ff5d6
commit 9553aa944a
5 changed files with 58 additions and 23 deletions
+4
View File
@@ -16,4 +16,8 @@
align-items: center; align-items: center;
overflow: hidden; overflow: hidden;
} }
.overlay-canvas:hover {
cursor: 'none !important';
}
} }
+30 -10
View File
@@ -18,6 +18,7 @@ type Stroke = Point[];
type CanvasImageEditorProps = { type CanvasImageEditorProps = {
imageSrc: string; imageSrc: string;
disabled?: boolean; disabled?: boolean;
imguid: string | number;
onSave: (imageData: { mask: string; img: string }) => void; onSave: (imageData: { mask: string; img: string }) => void;
uploadButton: React.ReactNode; uploadButton: React.ReactNode;
imageStatus: { imageStatus: {
@@ -33,6 +34,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
disabled, disabled,
imageStatus, imageStatus,
onSave, onSave,
imguid,
uploadButton uploadButton
}) => { }) => {
const MIN_SCALE = 0.5; const MIN_SCALE = 0.5;
@@ -55,8 +57,8 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
const translatePos = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); const translatePos = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
const contentPos = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); const contentPos = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
const animationFrameIdRef = useRef<number | null>(null); const animationFrameIdRef = useRef<number | null>(null);
const originRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); const strokeCache = useRef<any>({});
const preAutoScale = useRef<number>(1); const preImguid = useRef<string | number>('');
const getTransformedPoint = (offsetX: number, offsetY: number) => { const getTransformedPoint = (offsetX: number, offsetY: number) => {
const { current: scale } = autoScale; const { current: scale } = autoScale;
@@ -67,13 +69,13 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
const transformedY = (offsetY + lineWidth / 2 - translateY) / scale; const transformedY = (offsetY + lineWidth / 2 - translateY) / scale;
return { return {
x: Math.round(transformedX), x: _.round(transformedX),
y: Math.round(transformedY) y: _.round(transformedY)
}; };
}; };
const getTransformLineWidth = (lineWidth: number) => { const getTransformLineWidth = (lineWidth: number) => {
return lineWidth / autoScale.current; return lineWidth;
}; };
const setCanvasTransformOrigin = (e: React.MouseEvent<HTMLCanvasElement>) => { const setCanvasTransformOrigin = (e: React.MouseEvent<HTMLCanvasElement>) => {
@@ -214,6 +216,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
stroke.forEach((point, i) => { stroke.forEach((point, i) => {
const { x, y } = getTransformedPoint(point.x, point.y); const { x, y } = getTransformedPoint(point.x, point.y);
console.log('Drawing point:');
ctx.lineWidth = getTransformLineWidth(point.lineWidth); ctx.lineWidth = getTransformLineWidth(point.lineWidth);
if (i === 0) { if (i === 0) {
ctx.moveTo(x, y); ctx.moveTo(x, y);
@@ -487,6 +490,15 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
await drawImage(); await drawImage();
setImgLoaded(true); setImgLoaded(true);
console.log('Image Loaded:', imageStatus, strokesRef.current); console.log('Image Loaded:', imageStatus, strokesRef.current);
// if (strokeCache.current[imguid]) {
// strokesRef.current = strokeCache.current[imguid];
// } else if (preImguid.current !== imguid) {
// strokeCache.current[preImguid.current] = strokesRef.current;
// onReset();
// resetCanvas();
// preImguid.current = imguid;
// }
if (imageStatus.isOriginal) { if (imageStatus.isOriginal) {
redrawStrokes(strokesRef.current, 'initialize'); redrawStrokes(strokesRef.current, 'initialize');
} else if (imageStatus.isResetNeeded) { } else if (imageStatus.isResetNeeded) {
@@ -540,6 +552,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
const handleOnWheel = (event: any) => { const handleOnWheel = (event: any) => {
handleZoom(event); handleZoom(event);
updateCursorSize(); updateCursorSize();
// redrawStrokes(strokesRef.current);
}; };
const handleFitView = () => { const handleFitView = () => {
@@ -552,6 +565,11 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
redrawStrokes(strokesRef.current); redrawStrokes(strokesRef.current);
}; };
const handleBrushSizeChange = (value: number) => {
setLineWidth(value);
cursorRef.current!.style.width = `${value * autoScale.current}px`;
cursorRef.current!.style.height = `${value * autoScale.current}px`;
};
useEffect(() => { useEffect(() => {
initializeImage(); initializeImage();
}, [initializeImage]); }, [initializeImage]);
@@ -607,7 +625,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
defaultValue={lineWidth} defaultValue={lineWidth}
min={10} min={10}
max={60} max={60}
onChange={(value) => setLineWidth(value)} onChange={handleBrushSizeChange}
/> />
</div> </div>
} }
@@ -680,7 +698,8 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
<canvas ref={canvasRef} style={{ position: 'absolute', zIndex: 1 }} /> <canvas ref={canvasRef} style={{ position: 'absolute', zIndex: 1 }} />
<canvas <canvas
ref={overlayCanvasRef} ref={overlayCanvasRef}
style={{ position: 'absolute', zIndex: 2 }} className="overlay-canvas"
style={{ position: 'absolute', zIndex: 10, cursor: 'none' }}
onMouseDown={startDrawing} onMouseDown={startDrawing}
onMouseUp={endDrawing} onMouseUp={endDrawing}
onMouseEnter={handleMouseEnter} onMouseEnter={handleMouseEnter}
@@ -699,12 +718,13 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
style={{ style={{
display: 'none', display: 'none',
position: 'fixed', position: 'fixed',
width: lineWidth, width: lineWidth * autoScale.current,
height: lineWidth, height: lineWidth * autoScale.current,
backgroundColor: COLOR, backgroundColor: COLOR,
borderRadius: '50%', borderRadius: '50%',
pointerEvents: 'none', pointerEvents: 'none',
zIndex: 100 cursor: 'none',
zIndex: 5
}} }}
/> />
</div> </div>
+20 -10
View File
@@ -130,8 +130,10 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
isOriginal: false, isOriginal: false,
isResetNeeded: false isResetNeeded: false
}); });
const doneImage = useRef<boolean>(false);
const cacheFormData = useRef<any>({}); const cacheFormData = useRef<any>({});
const size = Form.useWatch('size', form.current?.form); const size = Form.useWatch('size', form.current?.form);
const [imguid, setImgUid] = useState<number>(0);
const { initialize, updateScrollerPosition } = useOverlayScroller(); const { initialize, updateScrollerPosition } = useOverlayScroller();
const { initialize: innitializeParams } = useOverlayScroller(); const { initialize: innitializeParams } = useOverlayScroller();
@@ -216,6 +218,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const imageFile = useMemo(() => { const imageFile = useMemo(() => {
if (!image) return null; if (!image) return null;
console.log('image>>>>>>>>>>>>>>', image);
return base64ToFile(image, 'image'); return base64ToFile(image, 'image');
}, [image]); }, [image]);
@@ -306,14 +309,12 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}; };
if (parameters.preview === 'preview') { if (parameters.preview === 'preview') {
stream_options = { stream_options = {
...stream_options,
stream_options_preview: true stream_options_preview: true
}; };
} }
if (parameters.preview === 'preview_faster') { if (parameters.preview === 'preview_faster') {
stream_options = { stream_options = {
...stream_options,
stream_options_preview_faster: true stream_options_preview_faster: true
}; };
} }
@@ -385,12 +386,8 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
} else if (item.b64_json) { } else if (item.b64_json) {
imgItem.dataUrl = `data:image/png;base64,${item.b64_json}`; imgItem.dataUrl = `data:image/png;base64,${item.b64_json}`;
} }
console.log(
'stream_options_chunk_result:',
params.stream_options_chunk_result
);
const progress = _.round(item.progress, 0); const progress = _.round(item.progress, 0);
console.log('progress:', item, progress);
newImageList[item.index] = { newImageList[item.index] = {
dataUrl: imgItem.dataUrl, dataUrl: imgItem.dataUrl,
height: imgSize[1], height: imgSize[1],
@@ -400,8 +397,8 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
uid: imgItem.uid, uid: imgItem.uid,
span: imgItem.span, span: imgItem.span,
loading: params.stream_options_chunk_result loading: params.stream_options_chunk_result
? false ? progress < 100
: progress < 100, : false,
preview: false, preview: false,
progress: progress progress: progress
}; };
@@ -628,6 +625,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const img = _.get(base64List, '[0].dataUrl', ''); const img = _.get(base64List, '[0].dataUrl', '');
setUploadList(base64List); setUploadList(base64List);
setImage(img); setImage(img);
setImgUid(_.get(base64List, '[0].uid', ''));
setImageStatus({ setImageStatus({
isOriginal: false, isOriginal: false,
isResetNeeded: true isResetNeeded: true
@@ -648,6 +646,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
if (image) { if (image) {
return ( return (
<CanvasImageEditor <CanvasImageEditor
imguid={imguid}
imageStatus={imageStatus} imageStatus={imageStatus}
imageSrc={image} imageSrc={image}
disabled={loading} disabled={loading}
@@ -689,10 +688,11 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}, [image, loading, imageStatus, handleOnSave, handleUpdateImageList]); }, [image, loading, imageStatus, handleOnSave, handleUpdateImageList]);
const handleOnImgClick = useCallback((item: any, isOrigin: boolean) => { const handleOnImgClick = useCallback((item: any, isOrigin: boolean) => {
console.log('item:', item); console.log('item:99', item);
if (item.progress < 100) { if (item.progress < 100) {
return; return;
} }
setImgUid(item.uid);
setImage(item.dataUrl); setImage(item.dataUrl);
setImageStatus({ setImageStatus({
isOriginal: isOrigin, isOriginal: isOrigin,
@@ -700,6 +700,16 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}); });
}, []); }, []);
useEffect(() => {
if (imageList.length > 0) {
const doneImg = imageList.find((item) => item.progress === 100);
if (doneImg && !doneImage.current) {
doneImage.current = true;
handleOnImgClick(doneImg, false);
}
}
}, [imageList, handleOnImgClick]);
const renderOriginImage = useMemo(() => { const renderOriginImage = useMemo(() => {
if (!uploadList.length) { if (!uploadList.length) {
return null; return null;
+2 -2
View File
@@ -32,12 +32,12 @@ const TextToImages: React.FC = () => {
const optionsList = [ const optionsList = [
{ {
label: 'Generate', label: intl.formatMessage({ id: 'playground.image.generate' }),
value: TabsValueMap.Tab1, value: TabsValueMap.Tab1,
icon: <DiffOutlined /> icon: <DiffOutlined />
}, },
{ {
label: 'Edit', label: intl.formatMessage({ id: 'playground.image.edit' }),
value: TabsValueMap.Tab2, value: TabsValueMap.Tab2,
icon: <HighlightOutlined /> icon: <HighlightOutlined />
} }
+2 -1
View File
@@ -149,7 +149,8 @@ export const generateRandomNumber = () => {
}; };
function base64ToBlob(base64: string, contentType = '', sliceSize = 512) { function base64ToBlob(base64: string, contentType = '', sliceSize = 512) {
const byteCharacters = atob(base64.split(',')[1]); // 去掉 Base64 前缀部分 const base64Content = base64.replace(/^data:image\/(png|jpg);base64,/, '');
const byteCharacters = atob(base64Content);
const byteArrays = []; const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {