提交 51c6405e 编写于 作者: Q qq_41923622

Fri Feb 7 11:15:00 CST 2025 inscode

上级 d75f300f
...@@ -110,6 +110,8 @@ const useDownload = () => { ...@@ -110,6 +110,8 @@ const useDownload = () => {
annotations:annotations, annotations:annotations,
imageWidth: canvas.backgroundImage.width, imageWidth: canvas.backgroundImage.width,
imageHeight: canvas.backgroundImage.height, imageHeight: canvas.backgroundImage.height,
imageLeft: canvas.backgroundImage.left,
imageTop: canvas.backgroundImage.top,
originalCanvasWidth: canvas.getWidth(), originalCanvasWidth: canvas.getWidth(),
originalCanvasHeight: canvas.getHeight(), originalCanvasHeight: canvas.getHeight(),
imgUrl: currentSrc, imgUrl: currentSrc,
......
...@@ -3,220 +3,237 @@ import React, { forwardRef, useContext, useImperativeHandle } from 'react'; ...@@ -3,220 +3,237 @@ import React, { forwardRef, useContext, useImperativeHandle } from 'react';
import { ACTION, LANG, MENU_TYPE_ENUM, MENU_TYPE_TEXT } from '../constants'; import { ACTION, LANG, MENU_TYPE_ENUM, MENU_TYPE_TEXT } from '../constants';
import { EditorContext } from '../util'; import { EditorContext } from '../util';
import Popover from './setting/Popover'; import Popover from './setting/Popover';
import {fabric} from 'fabric'; import { fabric } from 'fabric';
import ArrowClass from '../helpers/Arrow'; import ArrowClass from '../helpers/Arrow';
function annotationsInit(imgData,canvas,historyRef,positionInfo){ function annotationsInit(imgData, canvas, historyRef, positionInfo) {
const { scaleX,scaleY} = positionInfo const { scaleX, scaleY, leftOffset, topOffset, } = positionInfo
console.log("scaleX,scaleY ",scaleX,scaleY,currentCanvasWidth,currentCanvasHeight,currentImageWidth,currentImageHeight,imageWidth,imageHeight,imgData)
// 遍历标注信息,重新创建元素并添加到画布上 // 遍历标注信息,重新创建元素并添加到画布上
imgData.annotations.forEach((annotation) => { imgData.annotations.forEach((annotation) => {
let newObject; let newObject;
switch (annotation.type) { switch (annotation.type) {
case 'rect': case 'rect':
newObject = new fabric.Rect({ newObject = new fabric.Rect({
left: annotation.left* scaleX, left: annotation.left * scaleX + leftOffset,
top: annotation.top* scaleY, top: annotation.top * scaleY + topOffset,
originX: 'left', originX: 'left',
originY: 'top', originY: 'top',
width: annotation.width* scaleX, width: annotation.width * scaleX,
height: annotation.height* scaleY, height: annotation.height * scaleY,
angle: annotation.angle||0, angle: annotation.angle || 0,
fill: annotation.fill || 'rgba(255,0,0,0)', fill: annotation.fill || 'rgba(255,0,0,0)',
stroke: annotation.stroke, stroke: annotation.stroke,
strokeWidth: annotation.size* Math.max(scaleX, scaleY), strokeWidth: annotation.size * Math.max(scaleX, scaleY),
transparentCorners: false, transparentCorners: false,
opacity: annotation.opacity || 1 opacity: annotation.opacity || 1
}); });
break; break;
case 'textbox': case 'textbox':
case 'i-text': case 'i-text':
case 'text': case 'text':
newObject = new fabric.IText(annotation.text, { newObject = new fabric.IText(annotation.text, {
left: annotation.left* scaleX, left: annotation.left * scaleX + leftOffset,
top: annotation.top* scaleY, top: annotation.top * scaleY + topOffset,
width: annotation.width* scaleX, width: annotation.width * scaleX,
fontSize: annotation.fontSize, fontSize: annotation.fontSize,
fill: annotation.fill, fill: annotation.fill,
id: Math.random() * 4 + '_' + Date.now(), id: Math.random() * 4 + '_' + Date.now(),
opacity: annotation.opacity || 1 opacity: annotation.opacity || 1
}); });
break; break;
case 'circle': case 'circle':
newObject = new fabric.Circle({ newObject = new fabric.Circle({
left: annotation.left* scaleX, left: annotation.left * scaleX + leftOffset,
top: annotation.top* scaleY, top: annotation.top * scaleY + topOffset,
radius: (annotation.width / 2)* Math.max(scaleX, scaleY), radius: (annotation.width / 2) * Math.max(scaleX, scaleY),
angle: annotation.angle||0, angle: annotation.angle || 0,
fill: annotation.fill||'', fill: annotation.fill || '',
originX: 'left', originX: 'left',
originY: 'top', originY: 'top',
stroke: annotation.stroke, stroke: annotation.stroke,
strokeWidth: annotation.size* Math.max(scaleX, scaleY), strokeWidth: annotation.size * Math.max(scaleX, scaleY),
opacity: annotation.opacity || 1 opacity: annotation.opacity || 1
}); });
break; break;
case 'arrow' : case 'arrow':
let pointList = annotation.pointList||[annotation.left,annotation.top,annotation.left,annotation.top] let pointList = annotation.pointList || [annotation.left, annotation.top, annotation.left, annotation.top]
pointList[0] = pointList[0]*scaleX; pointList[0] = pointList[0] * scaleX + leftOffset;
pointList[1] = pointList[1]*scaleY; pointList[1] = pointList[1] * scaleY + topOffset;
pointList[2] = pointList[2]*scaleX; pointList[2] = pointList[2] * scaleX + leftOffset;
pointList[3] = pointList[3]*scaleY; pointList[3] = pointList[3] * scaleY + topOffset;
newObject = new ArrowClass(pointList, { newObject = new ArrowClass(pointList, {
strokeWidth: annotation.size* Math.max(scaleX, scaleY), strokeWidth: annotation.size * Math.max(scaleX, scaleY),
stroke: annotation.stroke, stroke: annotation.stroke,
id: new Date().valueOf() + '_' + Math.random() * 4, id: new Date().valueOf() + '_' + Math.random() * 4,
}); });
newObject.strokeUniform = true; newObject.strokeUniform = true;
break; break;
case 'path' : case 'path':
const adjustedPath = annotation.path.map((segment) => { const adjustedPath = annotation.path.map((segment) => {
const newSegment = [...segment]; const newSegment = [...segment];
for (let i = 1; i < newSegment.length; i++) { for (let i = 1; i < newSegment.length; i++) {
if (typeof newSegment[i] === 'number') { if (typeof newSegment[i] === 'number') {
if (i % 2 === 1) { if (i % 2 === 1) {
newSegment[i] *= scaleX; newSegment[i] = newSegment[i] * scaleX + leftOffset;
} else { } else {
newSegment[i] *= scaleY; 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);
} }
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 = () => { export const useUpload = () => {
const { const {
canvasInstanceRef, canvasInstanceRef,
canvasEl, canvasEl,
currentMenuRef, currentMenuRef,
historyRef, historyRef,
setCurrentMenu, setCurrentMenu,
initBackGroundImage, initBackGroundImage,
} = useContext(EditorContext); } = useContext(EditorContext);
const handleUpload = (e: any,imgData?:any) => { const handleUpload = (e: any, imgData?: any) => {
console.log(`e`,e,imgData) console.log(`e`, e, imgData)
const canvas = canvasInstanceRef.current; const canvas = canvasInstanceRef.current;
if(canvasEl?.current&&typeof e === 'string'){ if (canvasEl ?.current && typeof e === 'string') {
let imgObj = new Image(); let imgObj = new Image();
if(imgData){ if (imgData) {
// 获取当前图片和画布尺寸 // 获取当前图片和画布尺寸
const currentImageWidth = canvas.backgroundImage.width; const currentImageWidth = canvas.backgroundImage.width;
const currentImageHeight = canvas.backgroundImage.height; const currentImageHeight = canvas.backgroundImage.height;
const currentCanvasWidth = canvas.getWidth(); const currentCanvasWidth = canvas.getWidth();
const currentCanvasHeight = canvas.getHeight(); const currentCanvasHeight = canvas.getHeight();
let imageWidth = imgData.imageWidth||imgData.imgWidth; let imageWidth = imgData.imageWidth || imgData.imgWidth;
let imageHeight = imgData.imageHeight||imgData.imgHeight; let imageHeight = imgData.imageHeight || imgData.imgHeight;
// 计算缩放比例 // 计算缩放比例
const originalScaleX = imgData.originalCanvasWidth / imageWidth; const originalScaleX = imgData.originalCanvasWidth / imageWidth;
const originalScaleY = imgData.originalCanvasHeight / imageHeight; const originalScaleY = imgData.originalCanvasHeight / imageHeight;
const currentScaleX = currentCanvasWidth / currentImageWidth; const currentScaleX = currentCanvasWidth / currentImageWidth;
const currentScaleY = currentCanvasHeight / currentImageHeight; const currentScaleY = currentCanvasHeight / currentImageHeight;
const scaleX = currentScaleX / originalScaleX; const scaleX = currentScaleX / originalScaleX;
const scaleY = currentScaleY / originalScaleY; const scaleY = currentScaleY / originalScaleY;
const newScaleFactor = Math.min(currentCanvasWidth / imageWidth, currentCanvasHeight / imageHeight); const newScaleFactor = Math.min(currentCanvasWidth / imageWidth, currentCanvasHeight / imageHeight);
const newLeft = (currentCanvasWidth - imageWidth * newScaleFactor) / 2;
const newTop = (currentCanvasHeight - imageHeight * newScaleFactor) / 2;
annotationsInit(imgData,canvas,historyRef,{ const leftOffset = newLeft - imgData.imageLeft * scaleX;
scaleX, const topOffset = newTop - imgData.imageTop * scaleY;
scaleY, imgObj.src = e as string;
}); initBackGroundImage(e as string, true, () => {
} historyRef.current.updateCanvasState(ACTION.add);
}) annotationsInit(imgData, canvas, historyRef, {
scaleX,
} else{ scaleY,
newLeft,
} newTop,
imgObj.src = e as string; leftOffset,
initBackGroundImage(e as string, true, () => { topOffset,
historyRef.current.updateCanvasState(ACTION.add);
});
return;
return; }, {
} newLeft,
if ( newTop,
!canvas || newScaleFactor,
!canvasEl.current || })
!e.target.files.length ||
!e.target.files[0]?.type?.includes('image') } 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; return;
} }
if (currentMenuRef.current !== MENU_TYPE_ENUM.upload) { if (currentMenuRef.current !== MENU_TYPE_ENUM.upload) {
setCurrentMenu(MENU_TYPE_ENUM.upload); setCurrentMenu(MENU_TYPE_ENUM.upload);
} }
const reader = new FileReader(); const reader = new FileReader();
reader.onload = function (event) { reader.onload = function (event) {
if (!event || !event.target) { if (!event || !event.target) {
return; return;
} }
let imgObj = new Image(); let imgObj = new Image();
imgObj.src = event.target.result as string; imgObj.src = event.target.result as string;
initBackGroundImage(event.target.result as string, true, () => { initBackGroundImage(event.target.result as string, true, () => {
historyRef.current.updateCanvasState(ACTION.add); 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) => { export const Upload = forwardRef((props, ref) => {
const { const {
lang = LANG.en lang = LANG.en
} = useContext(EditorContext); } = useContext(EditorContext);
const { handleUpload } = useUpload(); const { handleUpload } = useUpload();
useImperativeHandle( useImperativeHandle(
ref, ref,
() => ({ () => ({
handleUpload: handleUpload, handleUpload: handleUpload,
}), }),
[handleUpload], [handleUpload],
); );
return ( return (
<> <>
{/* <div className="tie-image-editor_tool-item tie-image-editor_tool-upload"> */} {/* <div className="tie-image-editor_tool-item tie-image-editor_tool-upload"> */}
{/* <Popover content={MENU_TYPE_TEXT.upload[lang]} placement="top"> */} {/* <Popover content={MENU_TYPE_TEXT.upload[lang]} placement="top"> */}
{/* <i className="tie-image-editor_icon"> */} {/* <i className="tie-image-editor_icon"> */}
{/* <input {/* <input
onChange={handleUpload} onChange={handleUpload}
type="file" type="file"
className="tie-image-editor_tool-upload-input" className="tie-image-editor_tool-upload-input"
accept="image/*" accept="image/*"
/> */} /> */}
{/* </i> */} {/* </i> */}
{/* </Popover> */} {/* </Popover> */}
{/* </div> */} {/* </div> */}
</> </>
); );
}) })
...@@ -142,12 +142,19 @@ export const useInit = ({ url }: IProps) => { ...@@ -142,12 +142,19 @@ export const useInit = ({ url }: IProps) => {
(oImg: any) => { (oImg: any) => {
const center = canvas.getCenter(); const center = canvas.getCenter();
const imgHeight = oImg.height; const imgHeight = oImg.height;
/** 图片过大,使其大小正好跟容器一致 */
oImg.scale(height / imgHeight);
if(annotationsData){ 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{ }else{
/** 图片过大,使其大小正好跟容器一致 */
oImg.scale(height / imgHeight);
/** 使得图片在canvas中间 */ /** 使得图片在canvas中间 */
oImg.set({ oImg.set({
left: center.left - (oImg.width * (height / imgHeight)) / 2, left: center.left - (oImg.width * (height / imgHeight)) / 2,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册