diff --git a/src/tiny-image-editor/src/components/Download.tsx b/src/tiny-image-editor/src/components/Download.tsx index d8f69cbb9518d3592ee6cdac6372824103457804..9fb3cba32e75e0c2284593aab3d8ec04ef83d5c8 100644 --- a/src/tiny-image-editor/src/components/Download.tsx +++ b/src/tiny-image-editor/src/components/Download.tsx @@ -110,6 +110,8 @@ const useDownload = () => { annotations:annotations, imageWidth: canvas.backgroundImage.width, imageHeight: canvas.backgroundImage.height, + imageLeft: canvas.backgroundImage.left, + imageTop: canvas.backgroundImage.top, originalCanvasWidth: canvas.getWidth(), originalCanvasHeight: canvas.getHeight(), imgUrl: currentSrc, diff --git a/src/tiny-image-editor/src/components/Upload.tsx b/src/tiny-image-editor/src/components/Upload.tsx index 32022d1c055830e17ae21592e6169343af7d758f..b3f13ce4de85bf2c6c88d1612c0771231f56cef9 100644 --- a/src/tiny-image-editor/src/components/Upload.tsx +++ b/src/tiny-image-editor/src/components/Upload.tsx @@ -3,220 +3,237 @@ import React, { forwardRef, useContext, useImperativeHandle } from 'react'; import { ACTION, LANG, MENU_TYPE_ENUM, MENU_TYPE_TEXT } from '../constants'; import { EditorContext } from '../util'; import Popover from './setting/Popover'; -import {fabric} from 'fabric'; +import { fabric } from 'fabric'; import ArrowClass from '../helpers/Arrow'; -function annotationsInit(imgData,canvas,historyRef,positionInfo){ - - const { scaleX,scaleY} = positionInfo - console.log("scaleX,scaleY ",scaleX,scaleY,currentCanvasWidth,currentCanvasHeight,currentImageWidth,currentImageHeight,imageWidth,imageHeight,imgData) - // 遍历标注信息,重新创建元素并添加到画布上 - imgData.annotations.forEach((annotation) => { - let newObject; - - switch (annotation.type) { - case 'rect': - newObject = new fabric.Rect({ - left: annotation.left* scaleX, - top: annotation.top* scaleY, - originX: 'left', - originY: 'top', - width: annotation.width* scaleX, - height: annotation.height* scaleY, - angle: annotation.angle||0, - fill: annotation.fill || 'rgba(255,0,0,0)', - stroke: annotation.stroke, - strokeWidth: annotation.size* Math.max(scaleX, scaleY), - transparentCorners: false, - opacity: annotation.opacity || 1 - }); - break; - case 'textbox': - case 'i-text': - case 'text': - newObject = new fabric.IText(annotation.text, { - left: annotation.left* scaleX, - top: annotation.top* scaleY, - width: annotation.width* scaleX, - fontSize: annotation.fontSize, - fill: annotation.fill, - id: Math.random() * 4 + '_' + Date.now(), - opacity: annotation.opacity || 1 - }); - break; - case 'circle': - newObject = new fabric.Circle({ - left: annotation.left* scaleX, - top: annotation.top* scaleY, - radius: (annotation.width / 2)* Math.max(scaleX, scaleY), - angle: annotation.angle||0, - fill: annotation.fill||'', - originX: 'left', - originY: 'top', - stroke: annotation.stroke, - strokeWidth: annotation.size* Math.max(scaleX, scaleY), - opacity: annotation.opacity || 1 - }); - break; - case 'arrow' : - let pointList = annotation.pointList||[annotation.left,annotation.top,annotation.left,annotation.top] - pointList[0] = pointList[0]*scaleX; - pointList[1] = pointList[1]*scaleY; - pointList[2] = pointList[2]*scaleX; - pointList[3] = pointList[3]*scaleY; - newObject = new ArrowClass(pointList, { - strokeWidth: annotation.size* Math.max(scaleX, scaleY), - stroke: annotation.stroke, - id: new Date().valueOf() + '_' + Math.random() * 4, - }); - newObject.strokeUniform = true; - break; - case 'path' : - const adjustedPath = annotation.path.map((segment) => { - const newSegment = [...segment]; - for (let i = 1; i < newSegment.length; i++) { - if (typeof newSegment[i] === 'number') { - if (i % 2 === 1) { - newSegment[i] *= scaleX; - } else { - newSegment[i] *= scaleY; - } - } - } - return newSegment; - }); - newObject = new fabric.Path(adjustedPath, { - fill: annotation.fill, - stroke: annotation.stroke, - strokeWidth: annotation.size* Math.max(scaleX, scaleY), - opacity: annotation.opacity || 1 - }); - break; - // 可以根据需要添加更多元素类型的处理 - } - - if (newObject) { - - console.log(`annotation`,newObject,annotation,canvas) - canvas.add(newObject) - canvas.setActiveObject(newObject); - historyRef.current.updateCanvasState(ACTION.add, true, true); - // canvas.setActiveObject(newObject); +function annotationsInit(imgData, canvas, historyRef, positionInfo) { + + const { scaleX, scaleY, leftOffset, topOffset, } = positionInfo + + // 遍历标注信息,重新创建元素并添加到画布上 + imgData.annotations.forEach((annotation) => { + let newObject; + + switch (annotation.type) { + case 'rect': + newObject = new fabric.Rect({ + left: annotation.left * scaleX + leftOffset, + top: annotation.top * scaleY + topOffset, + originX: 'left', + originY: 'top', + width: annotation.width * scaleX, + height: annotation.height * scaleY, + angle: annotation.angle || 0, + fill: annotation.fill || 'rgba(255,0,0,0)', + stroke: annotation.stroke, + strokeWidth: annotation.size * Math.max(scaleX, scaleY), + transparentCorners: false, + opacity: annotation.opacity || 1 + }); + break; + case 'textbox': + case 'i-text': + case 'text': + newObject = new fabric.IText(annotation.text, { + left: annotation.left * scaleX + leftOffset, + top: annotation.top * scaleY + topOffset, + width: annotation.width * scaleX, + fontSize: annotation.fontSize, + fill: annotation.fill, + id: Math.random() * 4 + '_' + Date.now(), + opacity: annotation.opacity || 1 + }); + break; + case 'circle': + newObject = new fabric.Circle({ + left: annotation.left * scaleX + leftOffset, + top: annotation.top * scaleY + topOffset, + radius: (annotation.width / 2) * Math.max(scaleX, scaleY), + angle: annotation.angle || 0, + fill: annotation.fill || '', + originX: 'left', + originY: 'top', + stroke: annotation.stroke, + strokeWidth: annotation.size * Math.max(scaleX, scaleY), + opacity: annotation.opacity || 1 + }); + break; + case 'arrow': + let pointList = annotation.pointList || [annotation.left, annotation.top, annotation.left, annotation.top] + pointList[0] = pointList[0] * scaleX + leftOffset; + pointList[1] = pointList[1] * scaleY + topOffset; + pointList[2] = pointList[2] * scaleX + leftOffset; + pointList[3] = pointList[3] * scaleY + topOffset; + newObject = new ArrowClass(pointList, { + strokeWidth: annotation.size * Math.max(scaleX, scaleY), + stroke: annotation.stroke, + id: new Date().valueOf() + '_' + Math.random() * 4, + }); + newObject.strokeUniform = true; + break; + case 'path': + const adjustedPath = annotation.path.map((segment) => { + const newSegment = [...segment]; + for (let i = 1; i < newSegment.length; i++) { + if (typeof newSegment[i] === 'number') { + if (i % 2 === 1) { + newSegment[i] = newSegment[i] * scaleX + leftOffset; + } else { + newSegment[i] = newSegment[i] * scaleY + topOffset; + } + } } + return newSegment; + }); + newObject = new fabric.Path(adjustedPath, { + fill: annotation.fill, + stroke: annotation.stroke, + strokeWidth: annotation.size * Math.max(scaleX, scaleY), + opacity: annotation.opacity || 1 }); + break; + // 可以根据需要添加更多元素类型的处理 + } + + if (newObject) { + + console.log(`annotation`, newObject, annotation, canvas) + canvas.add(newObject) + canvas.setActiveObject(newObject); + historyRef.current.updateCanvasState(ACTION.add, true, true); + // canvas.setActiveObject(newObject); + } + }); } export const useUpload = () => { - const { - canvasInstanceRef, - canvasEl, - currentMenuRef, - historyRef, - setCurrentMenu, - initBackGroundImage, - } = useContext(EditorContext); - - const handleUpload = (e: any,imgData?:any) => { - console.log(`e`,e,imgData) - const canvas = canvasInstanceRef.current; - if(canvasEl?.current&&typeof e === 'string'){ - let imgObj = new Image(); - if(imgData){ - // 获取当前图片和画布尺寸 + const { + canvasInstanceRef, + canvasEl, + currentMenuRef, + historyRef, + setCurrentMenu, + initBackGroundImage, + } = useContext(EditorContext); + + const handleUpload = (e: any, imgData?: any) => { + console.log(`e`, e, imgData) + const canvas = canvasInstanceRef.current; + if (canvasEl ?.current && typeof e === 'string') { + let imgObj = new Image(); + if (imgData) { + // 获取当前图片和画布尺寸 const currentImageWidth = canvas.backgroundImage.width; const currentImageHeight = canvas.backgroundImage.height; const currentCanvasWidth = canvas.getWidth(); const currentCanvasHeight = canvas.getHeight(); - let imageWidth = imgData.imageWidth||imgData.imgWidth; - let imageHeight = imgData.imageHeight||imgData.imgHeight; - // 计算缩放比例 - - const originalScaleX = imgData.originalCanvasWidth / imageWidth; - const originalScaleY = imgData.originalCanvasHeight / imageHeight; - const currentScaleX = currentCanvasWidth / currentImageWidth; - const currentScaleY = currentCanvasHeight / currentImageHeight; - - const scaleX = currentScaleX / originalScaleX; - const scaleY = currentScaleY / originalScaleY; - const newScaleFactor = Math.min(currentCanvasWidth / imageWidth, currentCanvasHeight / imageHeight); - - - - annotationsInit(imgData,canvas,historyRef,{ - scaleX, - scaleY, - }); - } - }) - - } else{ - - } - imgObj.src = e as string; - initBackGroundImage(e as string, true, () => { - historyRef.current.updateCanvasState(ACTION.add); - - - return; - } - if ( - !canvas || - !canvasEl.current || - !e.target.files.length || - !e.target.files[0]?.type?.includes('image') + let imageWidth = imgData.imageWidth || imgData.imgWidth; + let imageHeight = imgData.imageHeight || imgData.imgHeight; + // 计算缩放比例 + + const originalScaleX = imgData.originalCanvasWidth / imageWidth; + const originalScaleY = imgData.originalCanvasHeight / imageHeight; + const currentScaleX = currentCanvasWidth / currentImageWidth; + const currentScaleY = currentCanvasHeight / currentImageHeight; + + const scaleX = currentScaleX / originalScaleX; + const scaleY = currentScaleY / originalScaleY; + const newScaleFactor = Math.min(currentCanvasWidth / imageWidth, currentCanvasHeight / imageHeight); + const newLeft = (currentCanvasWidth - imageWidth * newScaleFactor) / 2; + const newTop = (currentCanvasHeight - imageHeight * newScaleFactor) / 2; + + const leftOffset = newLeft - imgData.imageLeft * scaleX; + const topOffset = newTop - imgData.imageTop * scaleY; + imgObj.src = e as string; + initBackGroundImage(e as string, true, () => { + historyRef.current.updateCanvasState(ACTION.add); + annotationsInit(imgData, canvas, historyRef, { + scaleX, + scaleY, + newLeft, + newTop, + leftOffset, + topOffset, + + }); + return; + }, { + newLeft, + newTop, + newScaleFactor, + }) + + } else { + imgObj.src = e as string; + initBackGroundImage(e as string, true, () => { + historyRef.current.updateCanvasState(ACTION.add); + + return; + }) + } + + return; + } + + + if ( + !canvas || + !canvasEl.current || + !e.target.files.length || + !e.target.files[0] ?.type ?.includes('image') ) { - return; - } - - if (currentMenuRef.current !== MENU_TYPE_ENUM.upload) { - setCurrentMenu(MENU_TYPE_ENUM.upload); - } - - const reader = new FileReader(); - reader.onload = function (event) { - if (!event || !event.target) { - return; - } - - let imgObj = new Image(); - imgObj.src = event.target.result as string; - initBackGroundImage(event.target.result as string, true, () => { - historyRef.current.updateCanvasState(ACTION.add); - }); + return; + } + + if (currentMenuRef.current !== MENU_TYPE_ENUM.upload) { + setCurrentMenu(MENU_TYPE_ENUM.upload); + } + + const reader = new FileReader(); + reader.onload = function (event) { + if (!event || !event.target) { + return; + } + + let imgObj = new Image(); + imgObj.src = event.target.result as string; + initBackGroundImage(event.target.result as string, true, () => { + historyRef.current.updateCanvasState(ACTION.add); + }); + }; + reader.readAsDataURL(e.target.files[0]); }; - reader.readAsDataURL(e.target.files[0]); - }; - return { handleUpload }; + return { handleUpload }; }; /** 上传 */ export const Upload = forwardRef((props, ref) => { - const { - lang = LANG.en - } = useContext(EditorContext); - const { handleUpload } = useUpload(); - useImperativeHandle( - ref, - () => ({ - handleUpload: handleUpload, - }), - [handleUpload], - ); - return ( - <> - {/*
*/} - {/* */} - {/* */} - {/* ({ + handleUpload: handleUpload, + }), + [handleUpload], + ); + return ( + <> + {/*
*/} + {/* */} + {/* */} + {/* */} - {/* */} - {/* */} - {/*
*/} - - ); + {/*
*/} + {/*
*/} + {/*
*/} + + ); }) diff --git a/src/tiny-image-editor/src/components/init.tsx b/src/tiny-image-editor/src/components/init.tsx index 47d7942e3402410bc31e33f0872ee7bdfaf19b45..b8fedf87c3b2dd7c59eb8debeda91351c30516f8 100644 --- a/src/tiny-image-editor/src/components/init.tsx +++ b/src/tiny-image-editor/src/components/init.tsx @@ -142,12 +142,19 @@ export const useInit = ({ url }: IProps) => { (oImg: any) => { const center = canvas.getCenter(); const imgHeight = oImg.height; - /** 图片过大,使其大小正好跟容器一致 */ - oImg.scale(height / imgHeight); + if(annotationsData){ - + let imgScaleFactor = height / imgHeight + let newScaleFactor = imgScaleFactor/annotationsData.newScaleFactor + oImg.scale(imgScaleFactor); + oImg.set({ + left:annotationsData.newLeft*newScaleFactor, + top: annotationsData.newTop*newScaleFactor, + }); }else{ + /** 图片过大,使其大小正好跟容器一致 */ + oImg.scale(height / imgHeight); /** 使得图片在canvas中间 */ oImg.set({ left: center.left - (oImg.width * (height / imgHeight)) / 2,