Skip to content

Commit

Permalink
Merge pull request #34 from orca-team/dev_lzh
Browse files Browse the repository at this point in the history
Dev lzh
  • Loading branch information
hongzelin authored Aug 7, 2024
2 parents b79799c + 235291d commit d6fb025
Show file tree
Hide file tree
Showing 15 changed files with 58,817 additions and 15 deletions.
6 changes: 6 additions & 0 deletions .changeset/ten-needles-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@orca-fe/pdf-viewer': minor
'@orca-fe/painter': minor
---

feat: 增加 PDFMarkPlugin 插件;fix:修复大文件卡顿问题;修复 PDF 缓存 page,出现个别 page 黑屏问题;
1 change: 1 addition & 0 deletions packages/painter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"ahooks": "^3.7.8",
"classnames": "^2.3.2",
"color": "^4.2.3",
"lodash-es": "^4.17.21",
"react-colorful": "^5.6.1",
"tslib": "^2.6.2",
"@orca-fe/transformer": "^0.3.31"
Expand Down
39 changes: 39 additions & 0 deletions packages/painter/src/Painter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { CSSProperties, Ref } from 'react';
import React, { forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react';
import { useControllableValue, useMemoizedFn } from 'ahooks';
import { flattenDeep } from 'lodash-es';
import { useCombineKeyListener, useStaticClick } from '@orca-fe/hooks';
import type { TransformerBoxContextType } from '@orca-fe/transformer';
import { TransformerBoxContext, TransformerLayout } from '@orca-fe/transformer';
Expand Down Expand Up @@ -86,6 +87,9 @@ export interface PainterProps<T extends ShapeDataType> extends Omit<React.HTMLAt

/** 开始拖拽事件 */
onChangeStart?: (index: number) => void;

/** 整个PDF,所有图型的数据 */
dataList?: T[][];
}

const Painter = forwardRef(function <T extends ShapeDataType>(props: PainterProps<T>, pRef: Ref<PainterRef>) {
Expand All @@ -106,6 +110,7 @@ const Painter = forwardRef(function <T extends ShapeDataType>(props: PainterProp
style,
autoCheck = true,
onChangeStart = ef,
dataList,
...otherProps
} = props;
const styles = useStyle();
Expand All @@ -128,8 +133,33 @@ const Painter = forwardRef(function <T extends ShapeDataType>(props: PainterProp
defaultValuePropName: 'defaultData',
});

const getMaxMarkNum = useMemoizedFn((list: T[]) => {
let max = 0;
list.forEach(item => {
if (item && item.type === 'mark') {
max = Math.max(max, item.markNum);
}
});
return max;
});

// 处理 dataList,返回 maxMarkNum
const {
maxMarkNum,
} = useMemo(() => {

// 合并二维数组为一维数组
const mergedData = flattenDeep(dataList);
const maxMarkNum = getMaxMarkNum(mergedData);

return {
maxMarkNum,
};
}, [dataList]);

// 将 data 拆分为 graphShapeList 和 imageList,并保留 index 映射
const {
graphMarkList,
graphShapeList,
imageList,
graphIndexMap: shapeIndexMap,
Expand All @@ -143,7 +173,13 @@ const Painter = forwardRef(function <T extends ShapeDataType>(props: PainterProp
const dataTypeMap: Record<number, 'shape' | 'image'> = {};
const graphIndexMap: Record<number, number> = {};
const imageIndexMap: Record<number, number> = {};
const graphMarkList: GraphShapeType[] = [];

data.forEach((item, index) => {
if (item.type === 'mark') {
graphMarkList.push(item);
}

if (isGraphShapeType(item)) {
graphShapeList.push(item);
graphIndexMap[graphShapeList.length - 1] = index;
Expand All @@ -163,6 +199,7 @@ const Painter = forwardRef(function <T extends ShapeDataType>(props: PainterProp
graphIndexMap,
imageIndexMap,
dataIndexMap,
graphMarkList,
};
}, [data]);

Expand Down Expand Up @@ -378,6 +415,8 @@ const Painter = forwardRef(function <T extends ShapeDataType>(props: PainterProp
<ShapeCreator
pointMapping={getPointMapping}
shapeType={drawMode.shapeType}
graphMarkList={graphMarkList}
maxMarkNum={maxMarkNum}
onCancel={() => {
setTempShape(false);
setDrawMode(false);
Expand Down
11 changes: 8 additions & 3 deletions packages/painter/src/ShapeCreator/ShapeCreator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ export interface ShapeCreatorProps extends React.HTMLAttributes<HTMLDivElement>
onCreate?: (shape: GraphShapeType) => void;
onCancel?: () => void;
pointMapping?: (point: { x: number; y: number }) => { x: number; y: number };
graphMarkList?: GraphShapeType[];
maxMarkNum?: number;
}

const ShapeCreator = (props: ShapeCreatorProps) => {
const { className = '', shapeType = 'line', onCreate = ef, onDrawing = ef, onCancel = ef, pointMapping = a => a, ...otherProps } = props;
const { className = '', shapeType = 'line', onCreate = ef, onDrawing = ef, onCancel = ef, pointMapping = a => a, maxMarkNum = 0, ...otherProps } = props;
const styles = useStyle();

const rootRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -56,8 +58,11 @@ const ShapeCreator = (props: ShapeCreatorProps) => {
rotate: 0,
};
break;
case 'rectangle':
_this.data = { type: 'rectangle', x, y, width, height, rotate: 0 };
case 'rectangle':
_this.data = { type: 'rectangle', x, y, width, height, rotate: 0 };
break;
case 'mark':
_this.data = { type: 'mark', x, y, width, height, rotate: 0, markNum: maxMarkNum + 1 };
break;
case 'line-path':
// 折线
Expand Down
44 changes: 44 additions & 0 deletions packages/painter/src/ShapeRenderer/ShapeRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,50 @@ const ShapeRenderer = <T extends GraphShapeType>(props: ShapeRendererProps<T>) =
/>
);
break;
case 'mark':
element = (
<g>
<rect
x={shape.x}
y={shape.y}
width={shape.width}
height={shape.height}
rotate={`${shape.rotate}deg`}
style={{
fill: 'rgba(255, 77, 79, 0.05)',
transformOrigin: `${shape.x}px ${shape.y}px`,
transform: `rotate(${shape.rotate}deg)`,
}}
{...strokeStyle}
/>

{/* 圆形背景 */}
<circle
cx={shape.x + shape.width + 5} // 圆心在矩形右边缘外20px
cy={shape.y + shape.height + 5} // 圆心在矩形下边缘外20px
r={12}
fill='#F33B40' // 圆形背景颜色
stroke='#F33B40' // 圆形边框颜色
strokeWidth='1'
/>

{/* 文字 */}
<text
x={shape.x + shape.width + 5} // 文字开始于圆心x坐标
y={shape.y + shape.height + 5} // 文字开始于圆心y坐标
textAnchor="middle" // 文字水平居中
dominantBaseline="central" // 文字垂直居中
fill="#fff" // 文字填充为无色
stroke="#fff" // 边框颜色
strokeWidth="1" // 边框宽度
fontSize={14} // 文字大小
>
{shape.markNum}
</text>
</g>

);
break;
case 'line-path':
element = (
<path
Expand Down
13 changes: 12 additions & 1 deletion packages/painter/src/def.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ export type EllipseType = StrokeStyle &
rotate: number;
};

export type MarkType = StrokeStyle &
CommonShapeType & {
type: 'mark';
x: number;
y: number;
width: number;
height: number;
rotate: number;
markNum: number;
};

export type RectangleType = StrokeStyle &
CommonShapeType & {
type: 'rectangle';
Expand Down Expand Up @@ -59,7 +70,7 @@ export type ImageType = CommonShapeType & {
src: string;
};

export type GraphShapeType = LineShapeType | EllipseType | RectangleType | LinePathType;
export type GraphShapeType = LineShapeType | EllipseType | RectangleType | LinePathType | MarkType;

export type ShapeDataType = GraphShapeType | ImageType;

Expand Down
59 changes: 54 additions & 5 deletions packages/pdf-viewer/demo/DemoDev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,58 @@
* debug: true
*/

import React from 'react';
import PdfViewer, { PDFContextPrintPlugin, PDFOpenFileButtonPlugin, PDFPainterPlugin, PDFTooltipPlugin, usePdfViewerRef } from '@orca-fe/pdf-viewer';
import { useRef, useState } from 'react';
import type { PDFPainterPluginHandle, ShapeDataType } from '@orca-fe/pdf-viewer';
import PdfViewer, { PDFOpenFileButtonPlugin, PDFPainterPlugin, usePdfViewerRef, PDFMarkPlugin } from '@orca-fe/pdf-viewer';

const dataSource: ShapeDataType[][] = [
[
{
"type": "mark",
"x": 90.62429565049962,
"y": 211.45196318889847,
"width": 200.56173332509258,
"height": 23.595498038246205,
"rotate": 0,
"markNum": 4,
"strokeWidth": 1,
"stroke": "#CC0000"
},
{
"type": "mark",
"x": 638.7658654620648,
"y": 208.729405722947,
"width": 79.86168566791014,
"height": 26.318055504197673,
"rotate": 0,
"markNum": 5,
"strokeWidth": 1,
"stroke": "#CC0000"
},
{
"type": "mark",
"x": 100.60700635898839,
"y": 352.11743226305845,
"width": 398.4009091842336,
"height": 19.965421416977506,
"rotate": 0,
"markNum": 36,
"strokeWidth": 1,
"stroke": "#CC0000"
}
]
];

const Demo1 = () => {
const pdfViewerRef = usePdfViewerRef();
const painter = useRef<PDFPainterPluginHandle>(null);
const painter2 = useRef<PDFPainterPluginHandle>(null);
const [dataList, setMarkData] = useState<ShapeDataType[][]>(dataSource);

const onDataChange = (_newDataList, action, pageIndex, index) => {
setMarkData(_newDataList);
};

return (
<div>
<input
Expand All @@ -19,16 +66,18 @@ const Demo1 = () => {
const file = files[0];
const pdfViewer = pdfViewerRef.current;
if (pdfViewer) {
pdfViewer.close();
pdfViewer.load(file);
}
}
}}
/>
<PdfViewer ref={pdfViewerRef} dropFile pdfJsParams={{ cMapUrl: '/pdfjs-bcmaps/' }} style={{ height: 600 }}>
<PDFOpenFileButtonPlugin />
<PDFPainterPlugin />
<PDFTooltipPlugin />
<PDFContextPrintPlugin />

<PDFMarkPlugin data={dataList} ref={painter} onDataChange={onDataChange} buttonName="畫圖標註" popupVisible={false} autoCheck={false} drawingPluginId="drawingPluginId1" />

<PDFPainterPlugin ref={painter2} />
</PdfViewer>
</div>
);
Expand Down
10 changes: 9 additions & 1 deletion packages/pdf-viewer/src/PDFPage/PDFPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ export interface PdfPageProps extends React.HTMLAttributes<HTMLDivElement> {
zoom?: number;
maxPixel?: number;
outputScale?: number;
onRenderFinish?: (pageNumber: number) => void;
}

const PDFPage = (props: PdfPageProps) => {
const { className = '', index, render, zoom = 0, maxPixel = defaultMaxPixel, outputScale = globalOutputScale, ...otherProps } = props;
const { className = '', index, render, zoom = 0, maxPixel = defaultMaxPixel, outputScale = globalOutputScale, onRenderFinish, ...otherProps } = props;
const styles = useStyle();

const rootRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -96,6 +97,13 @@ const PDFPage = (props: PdfPageProps) => {
});
_this.canvasList = _this.canvasList.filter(node => node === canvas);
}
// 解决 canvas 渲染黑屏问题,重新绘制一次
if ('fillRule' in context && context.fillRule) {
onRenderFinish?.(index);
} else {
// 黑屏
renderPdfDebounce.run();
}
})
.catch((err) => {
if (err.name !== 'RenderingCancelledException') {
Expand Down
Loading

0 comments on commit d6fb025

Please sign in to comment.