PDF 渲染优化

This commit is contained in:
yupeng12 2024-03-06 15:19:29 +08:00
parent 7334b8088a
commit 28ee659a2c
6 changed files with 82 additions and 43 deletions

View File

@ -14,7 +14,8 @@ order: 24
{
"type": "pdf-viewer",
"id": "pdf-viewer",
"src": "/examples/static/simple.pdf"
"src": "/examples/static/simple.pdf",
"width": 500
}
```
@ -38,7 +39,8 @@ order: 24
{
"type": "pdf-viewer",
"id": "pdf-viewer",
"name": "file"
"name": "file",
"width": 500
}
]
}
@ -49,6 +51,6 @@ order: 24
| 属性名 | 类型 | 默认值 | 说明 |
| ---------- | ------ | ------ | ---------- |
| src | Api | | 文档地址 |
| width | number | 500 | 宽度 |
| width | number | | 宽度 |
| height | number | - | 高度 |
| background | string | #fff | PDF 背景色 |

View File

@ -16,7 +16,8 @@ export default {
{
type: 'pdf-viewer',
id: 'pdf-viewer',
name: 'file'
name: 'file',
width: 500
}
]
}

View File

@ -73,7 +73,7 @@ export interface RendererProps
env: RendererEnv;
$path: string; // 当前组件所在的层级信息
$schema: any; // 原始 schema 配置
testIdBuild: TestIdBuilder;
testIdBuilder?: TestIdBuilder;
store?: IIRendererStore;
syncSuperStore?: boolean;
data: {

View File

@ -1,7 +1,8 @@
.#{$ns}PdfViewer {
position: relative;
width: 100%;
min-width: 300px;
height: 100%;
min-height: 500px;
display: flex;
justify-content: center;
padding: 50px 0;
@ -14,6 +15,7 @@
}
&-Loading {
width: 100%;
text-align: center;
}

View File

@ -20,15 +20,17 @@ export interface PdfViewerProps extends ThemeProps {
width?: number;
height?: number;
background?: string;
loading: boolean;
}
const PdfViewer: React.FC<PdfViewerProps> = props => {
const {classnames: cx, className, width = 500} = props;
const {classnames: cx, className, loading, width = 300} = props;
const [file, setFile] = React.useState(props.file);
const [loaded, setLoaded] = React.useState(false);
const [page, setPage] = React.useState(1);
const [scale, setScale] = React.useState(1);
const [total, setTotal] = React.useState(1);
const wrapper = React.useRef<HTMLDivElement>(null);
const inputRef = React.useRef<HTMLInputElement>();
React.useEffect(() => {
@ -67,13 +69,9 @@ const PdfViewer: React.FC<PdfViewerProps> = props => {
setScale(scale * t);
}
if (!file) {
return null;
}
function renderLoading() {
return (
<div className={cx('PdfViewer-Loading')} style={{width: `${width}px`}}>
<div className={cx('PdfViewer-Loading')}>
<Spinner />
</div>
);
@ -115,27 +113,33 @@ const PdfViewer: React.FC<PdfViewerProps> = props => {
}
return (
<div className={cx(className, 'PdfViewer')}>
<div className={cx('PdfViewer-Content', {'is-loaded': loaded})}>
<Document
file={file}
onLoadSuccess={handleLoadSuccess}
loading={renderLoading()}
>
<Page
className={cx('PdfViewer-Content-Page')}
pageNumber={page}
width={width}
height={props.height}
loading={renderLoading()}
noData={<div>No PDF data</div>}
scale={scale}
renderTextLayer={false}
renderAnnotationLayer={false}
/>
</Document>
</div>
{loaded ? renderTool() : null}
<div className={cx(className, 'PdfViewer')} ref={wrapper}>
{!file || loading ? (
renderLoading()
) : (
<>
<div className={cx('PdfViewer-Content', {'is-loaded': loaded})}>
<Document
file={file}
onLoadSuccess={handleLoadSuccess}
loading={renderLoading()}
>
<Page
className={cx('PdfViewer-Content-Page')}
pageNumber={page}
width={width}
height={props.height}
loading={renderLoading()}
noData={<div>No PDF data</div>}
scale={scale}
renderTextLayer={false}
renderAnnotationLayer={false}
/>
</Document>
</div>
{loaded ? renderTool() : null}
</>
)}
</div>
);
};

View File

@ -4,7 +4,7 @@
* @created: 2024/02/26
*/
import React from 'react';
import React, {Suspense} from 'react';
import {
autobind,
getVariable,
@ -40,6 +40,8 @@ export interface PdfViewerProps extends RendererProps {}
interface PdfViewerState {
loading: boolean;
inited: boolean;
width?: number;
}
export default class PdfViewer extends React.Component<
@ -49,14 +51,21 @@ export default class PdfViewer extends React.Component<
file?: ArrayBuffer;
reader?: FileReader;
fetchCancel?: Function;
wrapper = React.createRef<HTMLDivElement>();
constructor(props: PdfViewerProps) {
super(props);
this.state = {
inited: false,
loading: false
};
}
componentDidMount() {
if (this.wrapper.current) {
this.setState({
width: this.wrapper.current.clientWidth - 100
});
}
this.renderPdf();
}
@ -79,6 +88,10 @@ export default class PdfViewer extends React.Component<
}
}
componentWillUnmount() {
this.abortLoad();
}
@autobind
abortLoad() {
if (this.fetchCancel) {
@ -117,6 +130,7 @@ export default class PdfViewer extends React.Component<
}
this.setState({
inited: true,
loading: true
});
@ -140,11 +154,18 @@ export default class PdfViewer extends React.Component<
async renderFormFile() {
const {name, data} = this.props;
const file = getVariable(data, name);
this.setState({
inited: true,
loading: true
});
if (file instanceof File) {
const reader = new FileReader();
reader.onload = _e => {
const data = reader.result as ArrayBuffer;
this.file = data;
this.setState({
loading: false
});
this.forceUpdate();
};
reader.readAsArrayBuffer(file);
@ -153,17 +174,26 @@ export default class PdfViewer extends React.Component<
}
render() {
const {className, classnames: cx, width, height, background} = this.props;
const {className, classnames: cx, height, background} = this.props;
const {loading, inited} = this.state;
const width = Math.max(this.props.width || this.state.width, 300);
return (
<PdfView
file={this.file}
className={className}
classnames={cx}
width={width}
height={height}
background={background}
/>
<div ref={this.wrapper}>
<Suspense fallback={<div>...</div>}>
{inited ? (
<PdfView
file={this.file}
loading={loading}
className={className}
classnames={cx}
width={width}
height={height}
background={background}
/>
) : null}
</Suspense>
</div>
);
}
}