zydx-plus 1.36.641 → 1.36.643
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/flip/src/flip.vue +351 -158
- package/src/components/graph/src/graph.css +3 -0
- package/src/components/graph/src/graph.vue +35 -1
- package/src/components/graph/src/lineTool.vue +13 -2
- package/src/components/graph/src/tool.vue +20 -2
- package/src/index.js +1 -1
|
@@ -1,41 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* flip 组件 - PDF翻书/阅读器组件
|
|
3
|
+
* 基于 PDF.js 实现 PDF 文档的在线预览,支持单页/双页模式、画笔批注、
|
|
4
|
+
* 文字标注、链接添加、拓展阅读等功能。提供 Canvas 绘制能力,支持
|
|
5
|
+
* 画笔、矩形、圆形、直线、箭头、文字等批注工具。
|
|
6
|
+
*/
|
|
1
7
|
<template>
|
|
8
|
+
<!-- 文档视图主容器 -->
|
|
2
9
|
<div class="docView" @click="extendRightDel" @mouseleave="mouseUpTest" @mouseup="mouseUpTest">
|
|
10
|
+
<!-- 全屏/视图切换工具栏(单/双页切换) -->
|
|
3
11
|
<div class="full-screen" v-if="false">
|
|
4
12
|
<div class="full-screen-img" @click.stop="fullScreen">
|
|
5
|
-
<!-- <div class="full-screen-title" style="" v-if="showText">全屏查看</div>-->
|
|
6
13
|
<img @mouseover="showText=true" @mouseout="showText=false" src="../img/full-screen.png" alt="" title="全屏查看">
|
|
7
14
|
</div>
|
|
15
|
+
<!-- 双页视图下的切换按钮 -->
|
|
8
16
|
<div class="full-screen-img" v-if="doublePage" @click.stop="changeView">
|
|
9
|
-
<!-- <div class="full-screen-title" style="" v-if="showMultiText">多页查看</div>-->
|
|
10
17
|
<img @mouseover="showMultiText=true" @mouseout="showMultiText=false" src="../img/multi-page.png" alt="" title="多页查看">
|
|
11
18
|
</div>
|
|
19
|
+
<!-- 单页视图下的切换按钮 -->
|
|
12
20
|
<div class="full-screen-img" v-else @click.stop="changeView">
|
|
13
|
-
<!-- <div class="full-screen-title" style="" v-if="showSingleText">单页查看</div>-->
|
|
14
21
|
<img @mouseover="showSingleText=true" @mouseout="showSingleText=false" src="../img/single-page.png" alt="" title="单页查看">
|
|
15
22
|
</div>
|
|
23
|
+
<!-- 笔迹工具按钮 -->
|
|
16
24
|
<div class="full-screen-img" v-if="!doublePage&&isShowPen" @click.stop="showPen">
|
|
17
|
-
<!-- <div class="full-screen-title" style="" v-if="showSingleText">单页查看</div>-->
|
|
18
|
-
<!-- <div class="full-screen-title" style="" v-if="showSingleText">单页查看</div>-->
|
|
19
25
|
<i class="iconfont zydx-huabi1" title="笔迹"/>
|
|
20
26
|
</div>
|
|
21
27
|
</div>
|
|
28
|
+
|
|
29
|
+
<!-- PDF 画布区域 -->
|
|
22
30
|
<div>
|
|
23
31
|
<div class="book" ref="book" @click.right="rightMenu($event)">
|
|
24
32
|
<div class="pages">
|
|
33
|
+
<!-- 双页模式渲染 -->
|
|
25
34
|
<div class="wrap-box" ref="wrap-box" v-show="doublePage">
|
|
26
35
|
<div class="wrap wrap-block" :ref="`wrap-${item.id}`" v-for="(item,index) in pageInfoArr" :key="index">
|
|
27
36
|
<div class="wrap-can" v-show="!loading" ref="wrapCanBox">
|
|
37
|
+
<!-- 右键菜单:添加链接 -->
|
|
28
38
|
<div class="extend-right" v-if="rightMenuShow" :style="extendStyle">
|
|
29
39
|
<div class="extend-right-cont" @click.stop="extendRight(null)">
|
|
30
|
-
<!-- <img src="../img/qubiezhen.svg" alt=""> -->
|
|
31
40
|
<p>添加链接</p>
|
|
32
41
|
</div>
|
|
33
42
|
</div>
|
|
43
|
+
<!-- 文本层:显示 PDF 提取的文字内容 -->
|
|
34
44
|
<div class="textLayer" ref="textLayer">
|
|
35
45
|
<span :dir="item2.dir" :style="styleText(item2,item.styles, item.id)" v-for="(item2) in item.items">{{ item2.str }}</span>
|
|
36
46
|
</div>
|
|
47
|
+
<!-- 批注层:显示链接和拓展阅读标注 -->
|
|
37
48
|
<div class="annotationLayer" ref="annotationLayer">
|
|
38
49
|
<template v-for="(item,index) in annotations">
|
|
50
|
+
<!-- 拓展阅读类型标注 -->
|
|
39
51
|
<div :style="styleAnnotation(item)" class="magnifier" v-if="item.type === 'tag'">
|
|
40
52
|
<div class="magnifier-head">
|
|
41
53
|
<div class="magnifier-title">拓展阅读</div>
|
|
@@ -49,14 +61,18 @@
|
|
|
49
61
|
<div class="magnifier-list-item" @click="annotationTap(item2)" v-for="(item2,index2) in item.list">{{ index2+1 }}.{{ item2?.title }}</div>
|
|
50
62
|
</div>
|
|
51
63
|
</div>
|
|
64
|
+
<!-- 普通链接类型标注 -->
|
|
52
65
|
<section v-else tabindex="1000" @click="annotationTap(item,item.id)" :style="styleAnnotation(item)">
|
|
53
66
|
<a :href="item.url" target="_blank"></a>
|
|
54
67
|
</section>
|
|
55
68
|
</template>
|
|
56
69
|
</div>
|
|
70
|
+
<!-- 批注绘制画布(上层,可交互) -->
|
|
57
71
|
<canvas @click.stop="turnText" class="wrap-can-one" :class="{isPointer: isPointer}" @mousedown.stop="mouseDown"
|
|
58
72
|
@mousemove.stop="mouseMove" :id="item.id"></canvas>
|
|
73
|
+
<!-- PDF 渲染画布(底层) -->
|
|
59
74
|
<canvas :id="`${item.id}2`"></canvas>
|
|
75
|
+
<!-- 文字批注输入框/拖拽框 -->
|
|
60
76
|
<div
|
|
61
77
|
v-show="state === 'text'&&textY2>0&&textX2>0"
|
|
62
78
|
class="text-frame"
|
|
@@ -75,19 +91,24 @@
|
|
|
75
91
|
</div>
|
|
76
92
|
</div>
|
|
77
93
|
</div>
|
|
94
|
+
|
|
95
|
+
<!-- 单页模式渲染 -->
|
|
78
96
|
<div class="wrap" ref="wrap" v-show="!doublePage">
|
|
79
97
|
<div class="wrap-can" v-show="!loading" ref="wrapCan">
|
|
98
|
+
<!-- 右键菜单:添加链接 -->
|
|
80
99
|
<div class="extend-right" v-if="rightMenuShow" :style="extendStyle">
|
|
81
100
|
<div class="extend-right-cont" @click.stop="extendRight(null)">
|
|
82
|
-
<!-- <img src="../img/qubiezhen.svg" alt=""> -->
|
|
83
101
|
<p>添加链接</p>
|
|
84
102
|
</div>
|
|
85
103
|
</div>
|
|
104
|
+
<!-- 文本层 -->
|
|
86
105
|
<div class="textLayer" ref="textLayer">
|
|
87
106
|
<span :dir="item.dir" :style="styleText(item,styles)" v-for="(item,index) in items">{{ item.str }}</span>
|
|
88
107
|
</div>
|
|
108
|
+
<!-- 批注层 -->
|
|
89
109
|
<div class="annotationLayer" ref="annotationLayer">
|
|
90
110
|
<template v-for="(item,index) in annotations">
|
|
111
|
+
<!-- 拓展阅读类型标注(单页模式,带弹出列表) -->
|
|
91
112
|
<div :style="styleAnnotation(item)" class="magnifier" v-if="item.type === 'tag'">
|
|
92
113
|
<img @click.stop="magnifierTap($event,item)" src="../img/dingwei.png" alt="" />
|
|
93
114
|
<div class="magnifier-list" v-if="item.show" :style="item.style">
|
|
@@ -104,14 +125,18 @@
|
|
|
104
125
|
</div>
|
|
105
126
|
</div>
|
|
106
127
|
</div>
|
|
128
|
+
<!-- 普通链接标注 -->
|
|
107
129
|
<section v-else tabindex="1000" @click="annotationTap(item)" :style="styleAnnotation(item)">
|
|
108
130
|
<a :href="item.url" target="_blank"></a>
|
|
109
131
|
</section>
|
|
110
132
|
</template>
|
|
111
133
|
</div>
|
|
134
|
+
<!-- 批注绘制画布 -->
|
|
112
135
|
<canvas @click.stop="turnText" class="wrap-can-one" :class="{isPointer: isPointer}" @mousedown.stop="mouseDown"
|
|
113
136
|
@mousemove.stop="mouseMove" :id="`${id}`"></canvas>
|
|
137
|
+
<!-- PDF 内容画布 -->
|
|
114
138
|
<canvas :id="`${id}2`"></canvas>
|
|
139
|
+
<!-- 文字批注输入框 -->
|
|
115
140
|
<div
|
|
116
141
|
v-show="state === 'text'&&textY2>0&&textX2>0"
|
|
117
142
|
class="text-frame"
|
|
@@ -129,20 +154,25 @@
|
|
|
129
154
|
</div>
|
|
130
155
|
</div>
|
|
131
156
|
</div>
|
|
157
|
+
|
|
158
|
+
<!-- 左侧翻页按钮(上一页) -->
|
|
132
159
|
<div class="page-but-left" :style="{cursor: pageIndex === 1?'default':'pointer'}" v-if="!loading&&!doublePage"
|
|
133
160
|
@click.stop="flipRight(pageIndex-=1,false)">
|
|
134
161
|
<img v-if="pageIndex !== 1"
|
|
135
|
-
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAB/dJREFUeF7t2tFRrDcMhuF/
|
|
162
|
+
src="data:image/png;base64,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"
|
|
136
163
|
alt=""/>
|
|
137
164
|
</div>
|
|
165
|
+
<!-- 右侧翻页按钮(下一页) -->
|
|
138
166
|
<div class="page-but-right" :style="{cursor: pageIndex === pdfPages?'default':'pointer'}" v-if="!loading&&!doublePage"
|
|
139
167
|
@click.stop="flipLeft(pageIndex+=1,false)">
|
|
140
168
|
<img v-if="pageIndex !== pdfPages"
|
|
141
|
-
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAACB9JREFUeF7tms1xW0kMBh8zUSgOxT5IxSzWTkM8rDOxExO5JRdVprQiOYMBMMCgfbQHP68/dOkg7zb+QAACVwnsYAMBCFwngCBcBwRuEEAQzgMCCMINQEBGgJ8gMm5UFSGAIEWC5jNlBBBExo2qIgQQpEjQfKaMAILIuFFVhACCFAmaz5QRQBAZN6qKEECQIkHzmTICCCLjRlURAghSJGg+U0YAQWTcqCpCAEGKBM1nygggiIwbVUUIIEiRoPlMGQEEueC23+8fXl5e/t3tdr+fn59/yJBStRIBBDmneSHHl/NffUeSlU5d9i0Ism3bJ3K80UQS2V0tU1VekBtyIMkyZy7/kNKCNMiBJPLbWqKyrCAdciDJEqcu+4iSggjkQBLZfaWvKifIgBxIkv7c+z+glCAKciBJ/42lrigjiKIcSJL65PuWLyGIgRxI0ndnaV8vL4ihHEiS9uzbF19ekMfHx6+73e6fbdse2rF0v+Q37t3IchQsL8hrDE9PT6+CfEWSHEcZacsSgiBJpJPLtUsZQZAk12FG2baUIEgS5ezy7FFOECTJc5wRNi0pCJJEOL0cO5QVBElyHOjsLUsLgiSzzy/+/PKCIEn8I525IYKc6fPLxJlnGHc2glxkgyRxD3XWZgjygTySzDrFmHMR5JNckCTmsc7YCkGuUEeSGecYbyaC3MgESeIdrPdGCHKHOJJ4n2SseQjSkAeSNEBa9AmCNAaLJI2gFnuGIB2BIkkHrEWeIkhnkEjSCSz5cwQRBIgkAmhJSxBEGBySCMElK0OQgcCQZABeklIEGQwKSQYBBi9HEIWAkEQBYtAWCKIUDJIogQzWBkEUA0ESRZhBWiGIchBIogx0cjsEMQgASQygTmqJIEbgkcQIrHNbBDEEjiSGcJ1aI4gxaCQxBmzcHkGMAb+2RxIHyEYjEMQI7Me2SOIEWnkMgigDvdUOSRxhK41CECWQrW2QpJVUjHcIMiEHJJkAXTgSQYTgRsuQZJSgTz2C+HD+dAqSTITfOBpBGkFZPUMSK7I6fRFEh+NQFyQZwmdajCCmeNubI0k7K8+XCOJJ+84sJAkUxnkVBAmWCZLECgRBYuXxZxskiRMKgsTJ4t0mSBIjGASJkQO/
|
|
169
|
+
src="data:image/png;base64,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"
|
|
142
170
|
alt=""/>
|
|
143
171
|
</div>
|
|
144
172
|
</div>
|
|
145
173
|
</div>
|
|
174
|
+
|
|
175
|
+
<!-- 底部翻页按钮(上一页/下一页) -->
|
|
146
176
|
<div class="but-wrap" v-if="butShow && !doublePage">
|
|
147
177
|
<button class="but-brown" :disabled="pageIndex === 1" :class="{'but-act': pageIndex === 1}"
|
|
148
178
|
@click.stop="flipRight(pageIndex-=1,false)">上一页
|
|
@@ -152,6 +182,8 @@
|
|
|
152
182
|
</button>
|
|
153
183
|
</div>
|
|
154
184
|
</div>
|
|
185
|
+
|
|
186
|
+
<!-- 加载动画遮罩层 -->
|
|
155
187
|
<div v-if="loading" class="loading-back">
|
|
156
188
|
<div class="loading-cont">
|
|
157
189
|
<div class="loadings">Loading</div>
|
|
@@ -161,6 +193,7 @@
|
|
|
161
193
|
</template>
|
|
162
194
|
|
|
163
195
|
<script>
|
|
196
|
+
// ==================== 依赖导入 ====================
|
|
164
197
|
import Mess from '../../tipBox/index'
|
|
165
198
|
import {debounce} from '../../utils'
|
|
166
199
|
import * as PdfJs from 'pdfjs-dist'
|
|
@@ -168,154 +201,177 @@ import "pdfjs-dist/build/pdf.worker.mjs";
|
|
|
168
201
|
import Range from "../../tagging/src/range";
|
|
169
202
|
|
|
170
203
|
import img from '../img/huabi.png'
|
|
204
|
+
// 缓存已加载的 PDF 文档对象
|
|
171
205
|
let pdfs = {};
|
|
172
206
|
|
|
173
207
|
export default {
|
|
174
208
|
name: "zydx-flip",
|
|
209
|
+
|
|
210
|
+
// ==================== 组件状态数据 ====================
|
|
175
211
|
data() {
|
|
176
212
|
return {
|
|
177
|
-
mouseImg:img,
|
|
178
|
-
pdfPages: 0,
|
|
179
|
-
imgArr: '',
|
|
213
|
+
mouseImg:img, // 画笔光标图标
|
|
214
|
+
pdfPages: 0, // PDF 总页数
|
|
215
|
+
imgArr: '', // 当前页 Canvas Base64 数据
|
|
180
216
|
hei: 0,
|
|
181
|
-
pageIndex: this.page,
|
|
217
|
+
pageIndex: this.page, // 当前页码(从 props.page 初始化)
|
|
182
218
|
show: false,
|
|
183
219
|
load: 0,
|
|
184
220
|
loadWidth: 0,
|
|
185
221
|
pages: false,
|
|
186
222
|
pagesData: [],
|
|
187
223
|
opacity: 1,
|
|
188
|
-
id: null,
|
|
189
|
-
loading: false,
|
|
190
|
-
canvasStyle: {},
|
|
224
|
+
id: null, // Canvas 元素唯一标识
|
|
225
|
+
loading: false, // 加载状态
|
|
226
|
+
canvasStyle: {}, // Canvas 容器样式配置
|
|
191
227
|
oneShow: false,
|
|
192
|
-
flipRights: false,
|
|
193
|
-
flipLefts: false,
|
|
194
|
-
oneIndex: 'right',
|
|
195
|
-
scales: 1.35,
|
|
196
|
-
timer: null,
|
|
228
|
+
flipRights: false, // 右翻动画状态
|
|
229
|
+
flipLefts: false, // 左翻动画状态
|
|
230
|
+
oneIndex: 'right', // 翻页方向(left/right)
|
|
231
|
+
scales: 1.35, // PDF 缩放比例
|
|
232
|
+
timer: null, // 防抖定时器
|
|
197
233
|
resultImg: '',
|
|
198
|
-
startX: 0,
|
|
199
|
-
startY: 0,
|
|
200
|
-
isDrawing: false,
|
|
201
|
-
sratio: 2,
|
|
202
|
-
ctx: null,
|
|
203
|
-
lineWidth: 2,
|
|
204
|
-
points: [],
|
|
234
|
+
startX: 0, // 画笔起始 X 坐标
|
|
235
|
+
startY: 0, // 画笔起始 Y 坐标
|
|
236
|
+
isDrawing: false, // 是否正在绘制
|
|
237
|
+
sratio: 2, // Canvas 清晰度系数(retina 屏适配)
|
|
238
|
+
ctx: null, // 批注画布 2D 上下文
|
|
239
|
+
lineWidth: 2, // 画笔线宽
|
|
240
|
+
points: [], // 所有批注数据
|
|
205
241
|
setShow: false,
|
|
206
242
|
flipToolShow2: false,
|
|
207
243
|
flipToolShow: false,
|
|
208
|
-
color: '#000',
|
|
244
|
+
color: '#000', // 画笔/文字颜色
|
|
209
245
|
text: '',
|
|
210
|
-
state: null,
|
|
211
|
-
fontSize: 14,
|
|
212
|
-
textX: 0,
|
|
213
|
-
textY: 0,
|
|
214
|
-
textX2: 0,
|
|
215
|
-
textY2: 0,
|
|
216
|
-
textStart: false,
|
|
217
|
-
contenteditable: false,
|
|
218
|
-
linkId: null,
|
|
219
|
-
pointsSelect: [],
|
|
220
|
-
checkDrawing: false, //
|
|
221
|
-
checkX: 0,
|
|
222
|
-
checkY: 0,
|
|
223
|
-
textWidth: 0,
|
|
224
|
-
textHeight: 0,
|
|
225
|
-
textDownX: 0,
|
|
226
|
-
textDownY: 0,
|
|
227
|
-
textMoveStart: false,
|
|
246
|
+
state: null, // 当前工具状态: null/mouse | brush | rectangle | circular | straight | arrow | text | del
|
|
247
|
+
fontSize: 14, // 文字字号
|
|
248
|
+
textX: 0, // 文字起始 X 坐标
|
|
249
|
+
textY: 0, // 文字起始 Y 坐标
|
|
250
|
+
textX2: 0, // 文字当前 X 坐标
|
|
251
|
+
textY2: 0, // 文字当前 Y 坐标
|
|
252
|
+
textStart: false, // 是否开始输入文字
|
|
253
|
+
contenteditable: false, // 文字框是否可编辑
|
|
254
|
+
linkId: null, // 当前绘制图形的链接 ID
|
|
255
|
+
pointsSelect: [], // 当前选中的图形数据
|
|
256
|
+
checkDrawing: false, // 是否在画板以外开始交互
|
|
257
|
+
checkX: 0, // 选中操作的起始 X
|
|
258
|
+
checkY: 0, // 选中操作的起始 Y
|
|
259
|
+
textWidth: 0, // 文字框最小宽度
|
|
260
|
+
textHeight: 0, // 文字框最小高度
|
|
261
|
+
textDownX: 0, // 文字框拖拽起始 X
|
|
262
|
+
textDownY: 0, // 文字框拖拽起始 Y
|
|
263
|
+
textMoveStart: false, // 是否开始拖拽文字框
|
|
228
264
|
chartIndexID: null, // 当前点击的图形索引
|
|
229
|
-
signStart: false,
|
|
230
|
-
doublePage:false,
|
|
231
|
-
doubleImgArr: [],
|
|
232
|
-
pageInfoArr:[],
|
|
265
|
+
signStart: false, // 是否开始标记模式
|
|
266
|
+
doublePage:false, // 是否为双页视图
|
|
267
|
+
doubleImgArr: [], // 双页模式下各页的 Canvas Base64 数据
|
|
268
|
+
pageInfoArr:[], // 双页模式下各页的配置信息
|
|
233
269
|
showText:false,
|
|
234
270
|
showMultiText:false,
|
|
235
271
|
showSingleText:false,
|
|
236
|
-
boxWidth:'',
|
|
237
|
-
resizeObserver: null,
|
|
272
|
+
boxWidth:'', // 容器宽度
|
|
273
|
+
resizeObserver: null, // 容器尺寸变化监听器
|
|
238
274
|
totalPages: 0,
|
|
239
|
-
items: [],
|
|
240
|
-
styles: {},
|
|
241
|
-
viewport: null,
|
|
242
|
-
doc: null,
|
|
243
|
-
viewWidth: 0,
|
|
244
|
-
viewHeight: 0,
|
|
245
|
-
annotations: [],
|
|
246
|
-
annotationsInit: [],
|
|
275
|
+
items: [], // PDF 文本内容数组
|
|
276
|
+
styles: {}, // PDF 文本样式映射
|
|
277
|
+
viewport: null, // PDF 视口对象
|
|
278
|
+
doc: null, // PDF 页面对象
|
|
279
|
+
viewWidth: 0, // 视口宽度
|
|
280
|
+
viewHeight: 0, // 视口高度
|
|
281
|
+
annotations: [], // 标注数据(合并外部传入和PDF内置标注)
|
|
282
|
+
annotationsInit: [], // PDF 自带标注原始数据
|
|
247
283
|
extendStyle: {
|
|
248
284
|
left: '0px',
|
|
249
285
|
top: '0px'
|
|
250
|
-
},
|
|
251
|
-
rightMenuShow: false,
|
|
252
|
-
annData: {}
|
|
286
|
+
}, // 右键菜单定位样式
|
|
287
|
+
rightMenuShow: false, // 是否显示右键菜单
|
|
288
|
+
annData: {} // 预存的标注数据
|
|
253
289
|
}
|
|
254
290
|
},
|
|
291
|
+
|
|
292
|
+
// ==================== Props 属性定义 ====================
|
|
255
293
|
props: {
|
|
294
|
+
// 是否禁用右键菜单
|
|
256
295
|
isDisableRightClick: {
|
|
257
296
|
type: Boolean,
|
|
258
297
|
default: false
|
|
259
298
|
},
|
|
299
|
+
// PDF 文件 URL 地址
|
|
260
300
|
source: {
|
|
261
301
|
type: String,
|
|
262
302
|
default: ''
|
|
263
303
|
},
|
|
304
|
+
// 是否为单页模式(已废弃,建议使用 isDoublePage)
|
|
264
305
|
singlePage: {
|
|
265
306
|
type: Boolean,
|
|
266
307
|
default: false
|
|
267
308
|
},
|
|
309
|
+
// 是否显示底部翻页按钮
|
|
268
310
|
butShow: {
|
|
269
311
|
type: Boolean,
|
|
270
312
|
default: false
|
|
271
313
|
},
|
|
314
|
+
// 初始页码
|
|
272
315
|
page: {
|
|
273
316
|
type: Number,
|
|
274
317
|
default: 1
|
|
275
318
|
},
|
|
319
|
+
// PDF 缩放比例
|
|
276
320
|
scale: {
|
|
277
321
|
type: Number,
|
|
278
322
|
default: 1.35
|
|
279
323
|
},
|
|
324
|
+
// 外部容器尺寸样式(用于自适应缩放计算)
|
|
280
325
|
scaleStyle: {
|
|
281
326
|
type: Object,
|
|
282
327
|
default: () => {
|
|
283
328
|
}
|
|
284
329
|
},
|
|
330
|
+
// 外部传入的已有批注数据
|
|
285
331
|
pointsData: {
|
|
286
332
|
type: Array,
|
|
287
333
|
default: () => []
|
|
288
334
|
},
|
|
335
|
+
// 阅读笔模式
|
|
289
336
|
readingPen: {
|
|
290
337
|
type: Boolean,
|
|
291
338
|
default: false
|
|
292
339
|
},
|
|
340
|
+
// 是否为双页模式
|
|
293
341
|
isDoublePage: {
|
|
294
342
|
type: Boolean,
|
|
295
343
|
default: false
|
|
296
344
|
},
|
|
345
|
+
// 是否显示画笔工具
|
|
297
346
|
isShowPen:{
|
|
298
347
|
type: Boolean,
|
|
299
348
|
default: true
|
|
300
349
|
},
|
|
350
|
+
// 是否允许鼠标点击穿透(批注层穿透)
|
|
301
351
|
isPointer: {
|
|
302
352
|
type: Boolean,
|
|
303
353
|
default: true
|
|
304
354
|
},
|
|
355
|
+
// 外部传入的标注数据
|
|
305
356
|
annotationsData: {
|
|
306
357
|
type: Array,
|
|
307
358
|
default: () => []
|
|
308
359
|
},
|
|
360
|
+
// 是否允许右键交互
|
|
309
361
|
rightClick: {
|
|
310
362
|
type: Boolean,
|
|
311
363
|
default: true
|
|
312
364
|
},
|
|
365
|
+
// 是否为只读模式(禁止添加标注)
|
|
313
366
|
readOnly: {
|
|
314
367
|
type: Boolean,
|
|
315
368
|
default: true
|
|
316
369
|
}
|
|
317
370
|
},
|
|
371
|
+
|
|
372
|
+
// ==================== 监听器 ====================
|
|
318
373
|
watch: {
|
|
374
|
+
// 监听外部标注数据变化
|
|
319
375
|
annotationsData: {
|
|
320
376
|
handler: function (val) {
|
|
321
377
|
if(typeof val === Object) {
|
|
@@ -340,27 +396,31 @@ export default {
|
|
|
340
396
|
deep: true,
|
|
341
397
|
immediate: true
|
|
342
398
|
},
|
|
399
|
+
// 监听外部批注数据变化,重新渲染
|
|
343
400
|
pointsData: {
|
|
344
401
|
handler: function (val) {
|
|
345
402
|
if (!val) return
|
|
346
403
|
this.points = val
|
|
347
|
-
this.processing()
|
|
404
|
+
this.processing() // 重绘所有批注
|
|
348
405
|
},
|
|
349
406
|
deep:true,
|
|
350
407
|
immediate: true
|
|
351
408
|
},
|
|
409
|
+
// 监听双页模式切换
|
|
352
410
|
isDoublePage: {
|
|
353
411
|
handler: function (val) {
|
|
354
412
|
this.doublePage = val
|
|
355
413
|
},
|
|
356
414
|
immediate: true
|
|
357
415
|
},
|
|
416
|
+
// 监听页码外部变化
|
|
358
417
|
page: {
|
|
359
418
|
handler: function (val) {
|
|
360
419
|
this.pageIndex = val
|
|
361
420
|
},
|
|
362
421
|
immediate: true
|
|
363
422
|
},
|
|
423
|
+
// 监听 PDF 源文件变化,重新加载
|
|
364
424
|
source: {
|
|
365
425
|
handler: function (v) {
|
|
366
426
|
this.sourceUrl()
|
|
@@ -368,6 +428,7 @@ export default {
|
|
|
368
428
|
deep: true,
|
|
369
429
|
immediate: true
|
|
370
430
|
},
|
|
431
|
+
// 监听容器尺寸变化,重新计算缩放比例
|
|
371
432
|
scaleStyle: {
|
|
372
433
|
handler: function (val) {
|
|
373
434
|
if (!val) return
|
|
@@ -375,18 +436,21 @@ export default {
|
|
|
375
436
|
clearTimeout(this.timer)
|
|
376
437
|
}
|
|
377
438
|
this.timer = setTimeout(() => {
|
|
439
|
+
// 根据容器宽度动态计算缩放比
|
|
378
440
|
this.scales = val.width / 550
|
|
379
441
|
if (this.scales >= this.scale) {
|
|
380
|
-
this.scales = this.scale
|
|
442
|
+
this.scales = this.scale // 不超过最大缩放比
|
|
381
443
|
}
|
|
382
444
|
}, 200)
|
|
383
445
|
},
|
|
384
446
|
deep: true
|
|
385
447
|
},
|
|
448
|
+
// 监听双页/单页切换,重新初始化页面信息
|
|
386
449
|
doublePage:{
|
|
387
450
|
handler: function (newVal,oldVal){
|
|
388
451
|
if(oldVal !== undefined){
|
|
389
452
|
if(newVal){
|
|
453
|
+
// 切换到双页模式
|
|
390
454
|
this.pageInfoArr = []
|
|
391
455
|
this.doubleImgArr = []
|
|
392
456
|
this.pageIndex = this.page
|
|
@@ -398,6 +462,7 @@ export default {
|
|
|
398
462
|
}
|
|
399
463
|
this.sourceUrl()
|
|
400
464
|
}else {
|
|
465
|
+
// 切换到单页模式
|
|
401
466
|
this.id = 'canvas-wrap' + this.generateUniqueKey()
|
|
402
467
|
this.sourceUrl()
|
|
403
468
|
}
|
|
@@ -406,6 +471,7 @@ export default {
|
|
|
406
471
|
deep: true,
|
|
407
472
|
immediate: true
|
|
408
473
|
},
|
|
474
|
+
// 监听缩放比例变化
|
|
409
475
|
scale:{
|
|
410
476
|
handler: function (val){
|
|
411
477
|
this.scales = val
|
|
@@ -413,10 +479,12 @@ export default {
|
|
|
413
479
|
deep: true,
|
|
414
480
|
immediate: true
|
|
415
481
|
},
|
|
482
|
+
// 监听工具状态变化,切换画笔光标样式
|
|
416
483
|
state:{
|
|
417
484
|
handler: function (val){
|
|
418
485
|
this.$nextTick(()=>{
|
|
419
486
|
if(val==='brush'){
|
|
487
|
+
// 画笔模式下使用自定义光标图标
|
|
420
488
|
this.$refs.wrapCan.setAttribute('style',`cursor:url(${this.mouseImg}) 0 16, auto;`)
|
|
421
489
|
}else {
|
|
422
490
|
this.$refs.wrapCan.style.cursor = "auto"
|
|
@@ -427,31 +495,42 @@ export default {
|
|
|
427
495
|
immediate: true
|
|
428
496
|
}
|
|
429
497
|
},
|
|
498
|
+
|
|
499
|
+
// ==================== 事件声明 ====================
|
|
430
500
|
emits: ['flip','annotationTap', 'annotationsSend', 'empty'],
|
|
501
|
+
|
|
502
|
+
// ==================== 生命周期 ====================
|
|
431
503
|
mounted() {
|
|
504
|
+
// 单页模式下生成 Canvas 唯一标识
|
|
432
505
|
if (!this.doublePage) {
|
|
433
506
|
this.id = 'canvas-wrap' + this.generateUniqueKey()
|
|
434
507
|
}
|
|
508
|
+
// 监听键盘事件(用于删除批注)
|
|
435
509
|
window.addEventListener('keydown', this.handleKeyEvent)
|
|
436
|
-
//
|
|
437
|
-
// document.onmouseup = () => {
|
|
438
|
-
// if (this.isDrawing || this.checkDrawing) this.mouseUp()
|
|
439
|
-
// this.textMoveStart = false
|
|
440
|
-
// }
|
|
510
|
+
// 注册容器尺寸变化监听(响应式重新渲染)
|
|
441
511
|
this.setResizeObserver()
|
|
442
512
|
},
|
|
443
513
|
beforeDestroy() {
|
|
514
|
+
// 清理键盘事件监听
|
|
444
515
|
window.removeEventListener('keydown', this.handleKeyEvent)
|
|
516
|
+
// 取消尺寸变化监听
|
|
445
517
|
this.cancelResizeObserver()
|
|
446
518
|
},
|
|
519
|
+
|
|
520
|
+
// ==================== 方法定义 ====================
|
|
447
521
|
methods: {
|
|
522
|
+
// ----- 标注相关方法 -----
|
|
523
|
+
|
|
524
|
+
// 清空拓展阅读列表
|
|
448
525
|
annEmpty(v) {
|
|
449
526
|
this.$emit('empty',v)
|
|
450
527
|
},
|
|
528
|
+
// 点击拓展阅读图标,显示/隐藏弹出列表
|
|
451
529
|
magnifierTap(e,v) {
|
|
452
|
-
if(!v.show) this.extendRightDel()
|
|
530
|
+
if(!v.show) this.extendRightDel() // 关闭其他弹出框
|
|
453
531
|
v.show = !v.show
|
|
454
532
|
setTimeout(() => {
|
|
533
|
+
// 计算弹出框位置:靠近右侧时向左弹出,靠近底部时向上弹出
|
|
455
534
|
const x = (v.rect[0] * this.scales / this.viewport?.width) * 100
|
|
456
535
|
const y = ((this.viewport?.height - (v.rect[1] * this.scales)) / this.viewport?.height) * 100
|
|
457
536
|
if(x > 50) {
|
|
@@ -466,6 +545,7 @@ export default {
|
|
|
466
545
|
}
|
|
467
546
|
},20)
|
|
468
547
|
},
|
|
548
|
+
// 关闭右键菜单
|
|
469
549
|
extendRightDel() {
|
|
470
550
|
this.rightMenuShow = false
|
|
471
551
|
this.annotations.map(x => {
|
|
@@ -473,9 +553,11 @@ export default {
|
|
|
473
553
|
return x
|
|
474
554
|
})
|
|
475
555
|
},
|
|
556
|
+
// 点击标注(链接跳转或添加标注)
|
|
476
557
|
annotationTap(v, n ) {
|
|
477
|
-
if(v.url) return
|
|
558
|
+
if(v.url) return // 有链接的标注直接导航
|
|
478
559
|
if(n === 'add') {
|
|
560
|
+
// 触发添加标注事件(带回标注参数让外部保存)
|
|
479
561
|
this.$emit('annotationsSend', {
|
|
480
562
|
id: v.id,
|
|
481
563
|
page: v.page,
|
|
@@ -487,7 +569,7 @@ export default {
|
|
|
487
569
|
this.$emit('annotationTap',v)
|
|
488
570
|
}
|
|
489
571
|
},
|
|
490
|
-
//
|
|
572
|
+
// 右键添加链接/标注
|
|
491
573
|
extendRight(i) {
|
|
492
574
|
this.extendRightDel()
|
|
493
575
|
this.$emit('annotationsSend', {
|
|
@@ -496,7 +578,14 @@ export default {
|
|
|
496
578
|
page: i? i + 1 : this.pageIndex,
|
|
497
579
|
})
|
|
498
580
|
},
|
|
499
|
-
//
|
|
581
|
+
// 查看点是否存在
|
|
582
|
+
doesThereExistAPoint(rect) {
|
|
583
|
+
const currenRect = JSON.stringify(rect)
|
|
584
|
+
return this.annotationsData.some(item => {
|
|
585
|
+
return JSON.stringify(item.rect) === currenRect
|
|
586
|
+
})
|
|
587
|
+
},
|
|
588
|
+
// 右键菜单处理:在文本上右键时弹出"添加链接"
|
|
500
589
|
rightMenu(e) {
|
|
501
590
|
if (this.isDisableRightClick) {
|
|
502
591
|
return
|
|
@@ -506,6 +595,7 @@ export default {
|
|
|
506
595
|
if(!this.rightClick) return;
|
|
507
596
|
if(this.doublePage) return;
|
|
508
597
|
if(e.target.nodeName === 'SPAN') {
|
|
598
|
+
// 计算文本位置以生成标注矩形区域
|
|
509
599
|
const wid = this.$refs.wrap.offsetWidth - 10
|
|
510
600
|
const endOffset = this.getRange().endOffset
|
|
511
601
|
const style = e.target.attributes.style.value
|
|
@@ -516,30 +606,36 @@ export default {
|
|
|
516
606
|
const x2 = x1 + 15
|
|
517
607
|
const y2 = y1 + 15
|
|
518
608
|
const left = e.target.offsetLeft + e.offsetX
|
|
519
|
-
this.rightMenuShow = true
|
|
609
|
+
// this.rightMenuShow = true
|
|
520
610
|
this.extendStyle = {
|
|
521
611
|
left: left + 'px',
|
|
522
|
-
// top: `calc(${Number(topMatch) + '%'} - 50px)`
|
|
523
612
|
top: `calc(${Number(topMatch) + '%'} - 30px)`
|
|
524
613
|
}
|
|
614
|
+
// 预存标注数据
|
|
525
615
|
this.annData = {
|
|
526
616
|
rect: [x1/this.scales,y1/this.scales,x2/this.scales,y2/this.scales],
|
|
527
617
|
type: 'tag',
|
|
528
618
|
borderStyle: {width: 0},
|
|
529
619
|
borderColor: [0,0,0]
|
|
530
620
|
}
|
|
621
|
+
// 判断当前坐标点是否存在,存在不显示右键菜单
|
|
622
|
+
if(this.annotationsData.length > 0) {
|
|
623
|
+
this.rightMenuShow = !this.doesThereExistAPoint(this.annData.rect)
|
|
624
|
+
} else {
|
|
625
|
+
this.rightMenuShow = true
|
|
626
|
+
}
|
|
531
627
|
}
|
|
532
628
|
},
|
|
533
|
-
//
|
|
629
|
+
// 选中文本后添加标注(翻转文本标注)
|
|
534
630
|
flipText(next) {
|
|
535
631
|
let timestamp = 'flip' + Math.random().toString(36).substr(2)
|
|
536
|
-
this.replaceSelectedStrByEle(timestamp)
|
|
632
|
+
this.replaceSelectedStrByEle(timestamp) // 给选中文本添加标记类名
|
|
537
633
|
const elements = document.querySelectorAll(`.${timestamp}`)[0];
|
|
538
634
|
if(!elements) return next(false)
|
|
539
635
|
const wid = this.$refs.wrap.offsetWidth - 10
|
|
540
636
|
const hei = this.$refs.wrap.offsetHeight - 10
|
|
541
637
|
const hei2 = elements.offsetHeight - 8
|
|
542
|
-
if(elements.offsetParent.nodeName === 'SPAN') { //
|
|
638
|
+
if(elements.offsetParent.nodeName === 'SPAN') { // 选中的文本有父级 span 标签
|
|
543
639
|
const parent = elements.offsetParent
|
|
544
640
|
const x1 = this.viewport.width * ((elements.offsetLeft + parent.offsetLeft + 3)/wid)
|
|
545
641
|
const y1 = this.viewport.height * (1 - (parent.offsetTop + hei2)/hei)
|
|
@@ -555,7 +651,7 @@ export default {
|
|
|
555
651
|
page: this.pageIndex,
|
|
556
652
|
data: ann
|
|
557
653
|
})
|
|
558
|
-
}else {
|
|
654
|
+
}else { // 直接选中的文本节点
|
|
559
655
|
const style = elements.firstChild.attributes.style.value
|
|
560
656
|
const leftMatch = style.match(/left:\s*([^;]+)/);
|
|
561
657
|
const topMatch = style.match(/top:\s*([^;]+)/);
|
|
@@ -581,7 +677,7 @@ export default {
|
|
|
581
677
|
})
|
|
582
678
|
}
|
|
583
679
|
},
|
|
584
|
-
//
|
|
680
|
+
// 给选中文本包裹 inline 元素添加样式
|
|
585
681
|
replaceSelectedStrByEle(className) {
|
|
586
682
|
const range = this.getRange();
|
|
587
683
|
range.applyInlineStyle('i', {
|
|
@@ -589,7 +685,7 @@ export default {
|
|
|
589
685
|
});
|
|
590
686
|
range.select();
|
|
591
687
|
},
|
|
592
|
-
//
|
|
688
|
+
// 获取当前选中的文本 Range 对象
|
|
593
689
|
getRange() {
|
|
594
690
|
const range = new Range(window.document);
|
|
595
691
|
const sel = window.getSelection();
|
|
@@ -600,6 +696,7 @@ export default {
|
|
|
600
696
|
}
|
|
601
697
|
return range
|
|
602
698
|
},
|
|
699
|
+
// 根据标注数据计算 CSS 定位样式(百分比定位)
|
|
603
700
|
styleAnnotation(v) {
|
|
604
701
|
if(!v) return {}
|
|
605
702
|
const x1 = (v.rect[0] * this.scales / this.viewport?.width) * 100
|
|
@@ -614,6 +711,7 @@ export default {
|
|
|
614
711
|
'border': `${v.borderStyle.width}px solid rgb(${v.borderColor[0]},${v.borderColor[1]},${v.borderColor[2]})`
|
|
615
712
|
}
|
|
616
713
|
},
|
|
714
|
+
// 根据文本位置计算 CSS 定位样式(用于 textLayer 渲染)
|
|
617
715
|
styleText(v,n, id) {
|
|
618
716
|
if(!v) return {}
|
|
619
717
|
const textLayer = id? this.$refs[`wrap-${id}`][0] : this.$refs.textLayer;
|
|
@@ -630,16 +728,26 @@ export default {
|
|
|
630
728
|
'top': `${top}%`,
|
|
631
729
|
}
|
|
632
730
|
},
|
|
731
|
+
|
|
732
|
+
// ----- 批注数据管理方法 -----
|
|
733
|
+
|
|
734
|
+
// 添加批注到 points 数组
|
|
633
735
|
pointsAdd(v) {
|
|
634
736
|
this.points.push(v)
|
|
635
737
|
},
|
|
738
|
+
// 获取当前页码
|
|
636
739
|
getPage() {
|
|
637
740
|
return this.pageIndex
|
|
638
741
|
},
|
|
742
|
+
// 在画板外松开鼠标时结束绘制(从父组件 mouseleave/mouseup 调用)
|
|
639
743
|
mouseUpTest(){
|
|
640
744
|
if (this.isDrawing || this.checkDrawing) this.mouseUp()
|
|
641
745
|
this.textMoveStart = false
|
|
642
746
|
},
|
|
747
|
+
|
|
748
|
+
// ----- ResizeObserver 容器尺寸监听 -----
|
|
749
|
+
|
|
750
|
+
// 初始化容器尺寸监听,尺寸变化时重新渲染 PDF
|
|
643
751
|
setResizeObserver() {
|
|
644
752
|
setTimeout(() => {
|
|
645
753
|
const el = this.$refs.book;
|
|
@@ -652,19 +760,24 @@ export default {
|
|
|
652
760
|
} else {
|
|
653
761
|
this.readPdf()
|
|
654
762
|
}
|
|
655
|
-
}, 150);
|
|
763
|
+
}, 150);
|
|
656
764
|
});
|
|
657
765
|
this.resizeObserver.observe(el);
|
|
658
766
|
}, 300)
|
|
659
767
|
},
|
|
768
|
+
// 取消容器尺寸监听
|
|
660
769
|
cancelResizeObserver() {
|
|
661
770
|
const el = this.$refs.book;
|
|
662
771
|
this.resizeObserver.unobserve(el);
|
|
663
772
|
},
|
|
773
|
+
|
|
774
|
+
// ----- 视图控制方法 -----
|
|
775
|
+
|
|
776
|
+
// 显示画笔工具
|
|
664
777
|
showPen() {
|
|
665
778
|
this.$emit('showPen', true)
|
|
666
|
-
// this.isDraw = true
|
|
667
779
|
},
|
|
780
|
+
// 切换单页/双页视图
|
|
668
781
|
changeView() {
|
|
669
782
|
this.$emit('changeViewDoublePage', !this.doublePage)
|
|
670
783
|
setTimeout(() => {
|
|
@@ -674,9 +787,13 @@ export default {
|
|
|
674
787
|
}
|
|
675
788
|
}, 500)
|
|
676
789
|
},
|
|
790
|
+
// 全屏查看(在新窗口打开 PDF)
|
|
677
791
|
fullScreen() {
|
|
678
792
|
window.open(this.source)
|
|
679
793
|
},
|
|
794
|
+
|
|
795
|
+
// ----- 工具配置方法 -----
|
|
796
|
+
|
|
680
797
|
colorTap(v) {
|
|
681
798
|
this.color = v
|
|
682
799
|
},
|
|
@@ -686,32 +803,42 @@ export default {
|
|
|
686
803
|
lineWidthTap(v) {
|
|
687
804
|
this.lineWidth = Number(v)
|
|
688
805
|
},
|
|
806
|
+
|
|
807
|
+
// ----- 键盘事件处理 -----
|
|
808
|
+
|
|
689
809
|
handleKeyEvent(e) {
|
|
690
810
|
const {key} = e
|
|
811
|
+
// Backspace/Delete 删除最后一个批注
|
|
691
812
|
if (key === 'Backspace' || key === 'Delete') {
|
|
692
813
|
if (this.contenteditable) return
|
|
693
814
|
this.backward()
|
|
694
815
|
}
|
|
695
816
|
},
|
|
696
|
-
|
|
817
|
+
|
|
818
|
+
// ----- 工具状态切换方法 -----
|
|
819
|
+
|
|
820
|
+
// 删除模式
|
|
697
821
|
delTap() {
|
|
698
822
|
this.state = 'del'
|
|
699
823
|
},
|
|
824
|
+
// 清空所有批注
|
|
700
825
|
empty() {
|
|
701
826
|
this.setShow = false
|
|
702
827
|
this.points = []
|
|
703
828
|
this.clearRect(true)
|
|
704
829
|
this.$emit('drawEnd', this.points,'empty')
|
|
705
830
|
},
|
|
831
|
+
// 持久化批注数据
|
|
706
832
|
preserve() {
|
|
707
833
|
this.setShow = false
|
|
708
834
|
return this.points
|
|
709
835
|
},
|
|
710
|
-
//
|
|
836
|
+
// 撤销最后一个批注(后退)
|
|
711
837
|
backward() {
|
|
712
838
|
this.setShow = false
|
|
713
839
|
if (this.points.length === 0) return
|
|
714
840
|
if (this.points[this.points.length - 1].type === 'line') {
|
|
841
|
+
// 线条类型需删除同 ID 的所有点
|
|
715
842
|
const id = this.points[this.points.length - 1].id
|
|
716
843
|
for (let i = 0; i < this.points.length; i++) {
|
|
717
844
|
if (this.points[i].id === id) {
|
|
@@ -725,41 +852,41 @@ export default {
|
|
|
725
852
|
this.$emit('drawEnd', this.points,'backward')
|
|
726
853
|
this.clearRect()
|
|
727
854
|
},
|
|
728
|
-
//
|
|
855
|
+
// 鼠标模式(选择/移动工具)
|
|
729
856
|
mouse() {
|
|
730
857
|
this.state = null
|
|
731
858
|
this.setShow = false
|
|
732
859
|
},
|
|
733
|
-
//
|
|
860
|
+
// 画笔模式
|
|
734
861
|
brush() {
|
|
735
862
|
this.state = 'brush'
|
|
736
863
|
this.setShow = true
|
|
737
864
|
},
|
|
738
|
-
//
|
|
865
|
+
// 设置文字字号
|
|
739
866
|
textSizeTap(v) {
|
|
740
867
|
this.fontSize = Number(v)
|
|
741
868
|
},
|
|
742
|
-
//
|
|
869
|
+
// 矩形工具
|
|
743
870
|
rectangleTap() {
|
|
744
871
|
this.state = 'rectangle'
|
|
745
872
|
this.setShow = true
|
|
746
873
|
},
|
|
747
|
-
//
|
|
874
|
+
// 圆形工具
|
|
748
875
|
circularTap() {
|
|
749
876
|
this.state = 'circular'
|
|
750
877
|
this.setShow = true
|
|
751
878
|
},
|
|
752
|
-
//
|
|
879
|
+
// 直线工具
|
|
753
880
|
straightTap() {
|
|
754
881
|
this.state = 'straight'
|
|
755
882
|
this.setShow = true
|
|
756
883
|
},
|
|
757
|
-
//
|
|
884
|
+
// 箭头工具
|
|
758
885
|
arrowTap() {
|
|
759
886
|
this.state = 'arrow'
|
|
760
887
|
this.setShow = true
|
|
761
888
|
},
|
|
762
|
-
//
|
|
889
|
+
// 文字工具
|
|
763
890
|
textTap(v) {
|
|
764
891
|
this.turnText()
|
|
765
892
|
this.state = 'text'
|
|
@@ -771,15 +898,20 @@ export default {
|
|
|
771
898
|
this.textWidth = 100
|
|
772
899
|
this.textHeight = this.fontSize + 1
|
|
773
900
|
this.$refs.textInput.innerText = ''
|
|
774
|
-
if (v === 'sign') this.signStart = true
|
|
901
|
+
if (v === 'sign') this.signStart = true // 签名标记模式
|
|
775
902
|
},
|
|
903
|
+
// 设置画笔颜色
|
|
776
904
|
strokeColTap(v) {
|
|
777
905
|
this.color = v
|
|
778
906
|
},
|
|
907
|
+
// 设置画笔线宽
|
|
779
908
|
strokeTap(v) {
|
|
780
909
|
this.lineWidth = Number(v)
|
|
781
910
|
},
|
|
782
|
-
|
|
911
|
+
|
|
912
|
+
// ----- 鼠标交互:选择/移动/删除图形 -----
|
|
913
|
+
|
|
914
|
+
// 按下时检测点击位置对应的图形
|
|
783
915
|
checkDown(e) {
|
|
784
916
|
e = e || event
|
|
785
917
|
e.preventDefault()
|
|
@@ -794,7 +926,7 @@ export default {
|
|
|
794
926
|
if (this.points[i].index === this.pageIndex) {
|
|
795
927
|
const x1 = this.points[i].x * this.scales / this.points[i].scale
|
|
796
928
|
const y1 = this.points[i].y * this.scales / this.points[i].scale
|
|
797
|
-
//
|
|
929
|
+
// 判断点击的是否是圆形
|
|
798
930
|
if (this.points[i]?.type === 'circular') {
|
|
799
931
|
const x2 = this.points[i].x * this.scales / this.points[i].scale + this.points[i].width * this.scales / this.points[i].scale
|
|
800
932
|
const y2 = this.points[i].y * this.scales / this.points[i].scale + this.points[i].width * this.scales / this.points[i].scale
|
|
@@ -809,8 +941,8 @@ export default {
|
|
|
809
941
|
this.points.splice(i, 1)
|
|
810
942
|
}
|
|
811
943
|
}
|
|
944
|
+
// 判断点击的是否是文字
|
|
812
945
|
if (this.points[i]?.type === 'text') {
|
|
813
|
-
// 取最长的一行文字
|
|
814
946
|
let len = 0
|
|
815
947
|
this.points[i].text.forEach(item => {
|
|
816
948
|
if (item.length > len) len = item.length
|
|
@@ -851,19 +983,17 @@ export default {
|
|
|
851
983
|
this.points.splice(i, 1)
|
|
852
984
|
}
|
|
853
985
|
}
|
|
854
|
-
//
|
|
986
|
+
// 判断点击的是否是直线/自由线条
|
|
855
987
|
if (this.points[i]?.type === 'line') {
|
|
856
988
|
const x2 = this.points[i + 1] ? this.points[i + 1].x * this.scales / this.points[i].scale : 0
|
|
857
989
|
const y2 = this.points[i + 1] ? this.points[i + 1].y * this.scales / this.points[i].scale : 0
|
|
858
990
|
const x3 = obj.x
|
|
859
991
|
const y3 = obj.y
|
|
860
|
-
// const a = Math.abs((x1-x2)*(y1-y3)-(x1-x3)*(y1-y2))
|
|
861
|
-
// const b = Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2))
|
|
862
992
|
const c = Math.sqrt(Math.pow(x1 - x3, 2) + Math.pow(y1 - y3, 2))
|
|
863
993
|
const d = Math.sqrt(Math.pow(x2 - x3, 2) + Math.pow(y2 - y3, 2))
|
|
864
994
|
const scope = this.lineWidth / 2 + 15
|
|
865
|
-
// if(a/b <= 5 && c <= b && d <= b) {
|
|
866
995
|
if (c < scope && d < scope && this.points[i].id === this.points[i + 1].id) {
|
|
996
|
+
// 删除同 ID 的所有线条段
|
|
867
997
|
const id = this.points[i].id
|
|
868
998
|
for (let j = 0; j < this.points.length; j++) {
|
|
869
999
|
if (this.points[j].id === id) {
|
|
@@ -876,7 +1006,7 @@ export default {
|
|
|
876
1006
|
return
|
|
877
1007
|
}
|
|
878
1008
|
}
|
|
879
|
-
//
|
|
1009
|
+
// 判断点击的是否是箭头或直线(两段式)
|
|
880
1010
|
if (this.points[i]?.type === 'straight' || this.points[i]?.type === 'arrow') {
|
|
881
1011
|
const x2 = this.points[i].x2 * this.scales / this.points[i].scale
|
|
882
1012
|
const y2 = this.points[i].y2 * this.scales / this.points[i].scale
|
|
@@ -899,6 +1029,7 @@ export default {
|
|
|
899
1029
|
}
|
|
900
1030
|
}
|
|
901
1031
|
},
|
|
1032
|
+
// 移动鼠标时平移选中的图形
|
|
902
1033
|
checkMove(e) {
|
|
903
1034
|
if (this.pointsSelect.length === 0) return
|
|
904
1035
|
let obj = {
|
|
@@ -924,11 +1055,13 @@ export default {
|
|
|
924
1055
|
}
|
|
925
1056
|
}
|
|
926
1057
|
},
|
|
1058
|
+
// 松开鼠标时提交选中的图形的新位置
|
|
927
1059
|
checkUp(e) {
|
|
928
1060
|
let obj = {
|
|
929
1061
|
x: e.offsetX * this.sratio - this.checkX,
|
|
930
1062
|
y: e.offsetY * this.sratio - this.checkY
|
|
931
1063
|
}
|
|
1064
|
+
// 将移动后的像素坐标转换回原始比例坐标
|
|
932
1065
|
for (let i = 0; i < this.pointsSelect.length; i++) {
|
|
933
1066
|
this.pointsSelect[i].x = this.pointsSelect[i].x * this.scales / this.pointsSelect[i].scale + obj.x
|
|
934
1067
|
this.pointsSelect[i].y = this.pointsSelect[i].y * this.scales / this.pointsSelect[i].scale + obj.y
|
|
@@ -947,6 +1080,10 @@ export default {
|
|
|
947
1080
|
this.points.push(this.pointsSelect[i])
|
|
948
1081
|
}
|
|
949
1082
|
},
|
|
1083
|
+
|
|
1084
|
+
// ----- 鼠标事件:绘制流程入口 -----
|
|
1085
|
+
|
|
1086
|
+
// 鼠标按下:开始绘制或开始选中操作
|
|
950
1087
|
mouseDown(e) {
|
|
951
1088
|
if (this.doublePage) {
|
|
952
1089
|
return;
|
|
@@ -955,11 +1092,13 @@ export default {
|
|
|
955
1092
|
e = e || event
|
|
956
1093
|
e.preventDefault()
|
|
957
1094
|
if (this.state === null || this.state === 'del') {
|
|
1095
|
+
// 选择/删除模式 -> 进入选中交互
|
|
958
1096
|
this.$emit('mouseClick')
|
|
959
1097
|
this.checkDrawing = true
|
|
960
1098
|
this.checkDown(e)
|
|
961
1099
|
return
|
|
962
1100
|
}
|
|
1101
|
+
// 绘制模式 -> 开始绘制
|
|
963
1102
|
this.isDrawing = true
|
|
964
1103
|
let obj = {
|
|
965
1104
|
x: e.offsetX * this.sratio,
|
|
@@ -968,16 +1107,22 @@ export default {
|
|
|
968
1107
|
this.drawStart(obj)
|
|
969
1108
|
if (this.signStart) this.sign()
|
|
970
1109
|
},
|
|
1110
|
+
|
|
1111
|
+
// ----- 文字框交互 -----
|
|
1112
|
+
|
|
1113
|
+
// 双击文字框进入编辑模式
|
|
971
1114
|
textDblclick() {
|
|
972
1115
|
if (!this.contenteditable) this.contenteditable = true
|
|
973
1116
|
},
|
|
1117
|
+
// 文字框拖拽开始
|
|
974
1118
|
textMouseDown(e) {
|
|
975
1119
|
e = e || event
|
|
976
1120
|
this.textDownX = e.offsetX
|
|
977
1121
|
this.textDownY = e.offsetY
|
|
978
1122
|
this.textMoveStart = true
|
|
979
1123
|
},
|
|
980
|
-
|
|
1124
|
+
|
|
1125
|
+
// 鼠标移动:绘制中/拖拽文字框/选中移动中
|
|
981
1126
|
mouseMove(e) {
|
|
982
1127
|
if (this.doublePage) {
|
|
983
1128
|
return;
|
|
@@ -985,6 +1130,7 @@ export default {
|
|
|
985
1130
|
e = e || event
|
|
986
1131
|
e.preventDefault()
|
|
987
1132
|
if (this.textMoveStart) {
|
|
1133
|
+
// 拖拽文字框
|
|
988
1134
|
this.textX2 = e.offsetX * this.sratio - this.textDownX
|
|
989
1135
|
this.textY2 = e.offsetY * this.sratio - this.textDownY
|
|
990
1136
|
if (this.points[this.points.length - 1].type === 'sign') {
|
|
@@ -994,10 +1140,11 @@ export default {
|
|
|
994
1140
|
}
|
|
995
1141
|
}
|
|
996
1142
|
if (this.state === null) {
|
|
997
|
-
if (this.checkDrawing) this.checkMove(e)
|
|
1143
|
+
if (this.checkDrawing) this.checkMove(e) // 选择模式平移
|
|
998
1144
|
return
|
|
999
1145
|
}
|
|
1000
1146
|
if (this.isDrawing) {
|
|
1147
|
+
// 绘制模式下更新绘制
|
|
1001
1148
|
let obj = {
|
|
1002
1149
|
x: e.offsetX * this.sratio,
|
|
1003
1150
|
y: e.offsetY * this.sratio
|
|
@@ -1005,7 +1152,8 @@ export default {
|
|
|
1005
1152
|
this.drawMove(obj)
|
|
1006
1153
|
}
|
|
1007
1154
|
},
|
|
1008
|
-
|
|
1155
|
+
|
|
1156
|
+
// 鼠标松开:结束绘制或提交选中操作
|
|
1009
1157
|
mouseUp(e) {
|
|
1010
1158
|
e = e || event
|
|
1011
1159
|
e.preventDefault()
|
|
@@ -1013,7 +1161,7 @@ export default {
|
|
|
1013
1161
|
this.checkDrawing = false
|
|
1014
1162
|
this.checkUp(e)
|
|
1015
1163
|
if (this.state === 'del') {
|
|
1016
|
-
this.delChart()
|
|
1164
|
+
this.delChart() // 删除选中的图形
|
|
1017
1165
|
}
|
|
1018
1166
|
return
|
|
1019
1167
|
}
|
|
@@ -1026,9 +1174,12 @@ export default {
|
|
|
1026
1174
|
this.signStart = false
|
|
1027
1175
|
this.pointsSelect = []
|
|
1028
1176
|
},
|
|
1177
|
+
|
|
1178
|
+
// 删除选中的图形
|
|
1029
1179
|
delChart() {
|
|
1030
1180
|
if (this.pointsSelect.length === 0) return
|
|
1031
1181
|
const id = this.pointsSelect[0].id
|
|
1182
|
+
// 删除同 ID 的所有图形数据
|
|
1032
1183
|
for (let i = 0; i < this.points.length; i++) {
|
|
1033
1184
|
if (this.points[i].id === id) {
|
|
1034
1185
|
this.points.splice(i, 1)
|
|
@@ -1038,14 +1189,18 @@ export default {
|
|
|
1038
1189
|
this.$emit('drawEnd', this.points,'del')
|
|
1039
1190
|
this.clearRect()
|
|
1040
1191
|
},
|
|
1041
|
-
|
|
1192
|
+
|
|
1193
|
+
// ----- 绘制核心方法 -----
|
|
1194
|
+
|
|
1195
|
+
// 开始绘制(记录起始点,初始化图形参数)
|
|
1042
1196
|
drawStart(obj) {
|
|
1043
1197
|
obj.index = this.pageIndex
|
|
1044
1198
|
obj.start = 'start'
|
|
1045
|
-
this.linkId = Math.random().toString(36).substr(2)
|
|
1199
|
+
this.linkId = Math.random().toString(36).substr(2) // 生成唯一 ID
|
|
1046
1200
|
this.startX = obj.x
|
|
1047
1201
|
this.startY = obj.y
|
|
1048
1202
|
if (this.textStart) {
|
|
1203
|
+
// 文字工具:定位文字框位置
|
|
1049
1204
|
this.textX2 = obj.x
|
|
1050
1205
|
this.textY2 = obj.y
|
|
1051
1206
|
this.contenteditable = true
|
|
@@ -1062,6 +1217,7 @@ export default {
|
|
|
1062
1217
|
if (this.state === 'straight') this.straight(obj)
|
|
1063
1218
|
if (this.state === 'arrow') this.arrow(obj)
|
|
1064
1219
|
},
|
|
1220
|
+
// 结束绘制(保存最终图形数据)
|
|
1065
1221
|
drawEnd(obj) {
|
|
1066
1222
|
obj.index = this.pageIndex
|
|
1067
1223
|
obj.start = 'end'
|
|
@@ -1071,6 +1227,7 @@ export default {
|
|
|
1071
1227
|
if (this.state === 'straight') this.straight(obj, 'end')
|
|
1072
1228
|
if (this.state === 'arrow') this.arrow(obj, 'end')
|
|
1073
1229
|
},
|
|
1230
|
+
// 绘制过程中更新图形(实时预览)
|
|
1074
1231
|
drawMove(obj) {
|
|
1075
1232
|
obj.index = this.pageIndex
|
|
1076
1233
|
obj.start = 'move'
|
|
@@ -1082,6 +1239,8 @@ export default {
|
|
|
1082
1239
|
this.startY = obj.y
|
|
1083
1240
|
this.startX = obj.x
|
|
1084
1241
|
},
|
|
1242
|
+
|
|
1243
|
+
// 点击 Canvas 空白处时提交文字
|
|
1085
1244
|
turnText() {
|
|
1086
1245
|
if (this.textStart) return
|
|
1087
1246
|
if (this.state === 'text') {
|
|
@@ -1096,7 +1255,10 @@ export default {
|
|
|
1096
1255
|
this.addText(text)
|
|
1097
1256
|
}
|
|
1098
1257
|
},
|
|
1099
|
-
|
|
1258
|
+
|
|
1259
|
+
// ----- 各图形绘制方法 -----
|
|
1260
|
+
|
|
1261
|
+
// 绘制标记(带编号的红色标记)
|
|
1100
1262
|
sign() {
|
|
1101
1263
|
const x = this.textX2
|
|
1102
1264
|
const y = this.textY2
|
|
@@ -1107,9 +1269,9 @@ export default {
|
|
|
1107
1269
|
this.ctx.fill();
|
|
1108
1270
|
this.ctx.closePath();
|
|
1109
1271
|
this.ctx.beginPath();
|
|
1110
|
-
this.ctx.moveTo(x - 50, y + 15);
|
|
1111
|
-
this.ctx.lineTo(x - 10, y + 15);
|
|
1112
|
-
this.ctx.lineTo(x - 30, y + 40);
|
|
1272
|
+
this.ctx.moveTo(x - 50, y + 15);
|
|
1273
|
+
this.ctx.lineTo(x - 10, y + 15);
|
|
1274
|
+
this.ctx.lineTo(x - 30, y + 40);
|
|
1113
1275
|
this.ctx.fillStyle = 'red';
|
|
1114
1276
|
this.ctx.fill();
|
|
1115
1277
|
this.ctx.closePath()
|
|
@@ -1130,6 +1292,7 @@ export default {
|
|
|
1130
1292
|
num: num
|
|
1131
1293
|
})
|
|
1132
1294
|
},
|
|
1295
|
+
// 计算标记编号(自动递增)
|
|
1133
1296
|
signNum() {
|
|
1134
1297
|
let num = []
|
|
1135
1298
|
this.points.forEach(item => {
|
|
@@ -1139,7 +1302,7 @@ export default {
|
|
|
1139
1302
|
})
|
|
1140
1303
|
return num.length === 0 ? 1 : Math.max(...num) + 1
|
|
1141
1304
|
},
|
|
1142
|
-
//
|
|
1305
|
+
// 添加文字到 Canvas 并保存数据
|
|
1143
1306
|
addText(v) {
|
|
1144
1307
|
let obj = {}
|
|
1145
1308
|
obj.index = this.pageIndex
|
|
@@ -1148,8 +1311,7 @@ export default {
|
|
|
1148
1311
|
obj.color = this.color
|
|
1149
1312
|
obj.size = this.fontSize
|
|
1150
1313
|
obj.id = this.linkId
|
|
1151
|
-
//
|
|
1152
|
-
const arr = v.split('\n')
|
|
1314
|
+
const arr = v.split('\n') // 按换行符分割
|
|
1153
1315
|
for (let i = 0; i < arr.length; i++) {
|
|
1154
1316
|
this.ctx.beginPath();
|
|
1155
1317
|
this.ctx.font = `${this.fontSize * this.sratio}px 黑体`;
|
|
@@ -1159,7 +1321,7 @@ export default {
|
|
|
1159
1321
|
this.ctx.closePath()
|
|
1160
1322
|
}
|
|
1161
1323
|
const poi = this.points[this.points.length - 1]
|
|
1162
|
-
if (poi?.type === 'sign') poi.id = this.linkId
|
|
1324
|
+
if (poi?.type === 'sign') poi.id = this.linkId // 标记与文字共享 ID
|
|
1163
1325
|
this.points.push({
|
|
1164
1326
|
x: this.textX2,
|
|
1165
1327
|
y: this.textY2,
|
|
@@ -1173,7 +1335,7 @@ export default {
|
|
|
1173
1335
|
})
|
|
1174
1336
|
this.$emit('drawEnd', this.points)
|
|
1175
1337
|
},
|
|
1176
|
-
//
|
|
1338
|
+
// 绘制箭头(从起始点到鼠标位置,带箭头尖端)
|
|
1177
1339
|
arrow(obj, type) {
|
|
1178
1340
|
obj.index = this.pageIndex
|
|
1179
1341
|
obj.type = 'arrow'
|
|
@@ -1181,6 +1343,7 @@ export default {
|
|
|
1181
1343
|
obj.color = this.color
|
|
1182
1344
|
obj.border = this.lineWidth
|
|
1183
1345
|
obj.id = this.linkId
|
|
1346
|
+
// 计算箭头角度
|
|
1184
1347
|
const angle = Math.atan2(this.textY - obj.y, this.textX - obj.x) * 180 / Math.PI
|
|
1185
1348
|
const angle1 = (angle + 20) * Math.PI / 180
|
|
1186
1349
|
const angle2 = (angle - 20) * Math.PI / 180
|
|
@@ -1205,6 +1368,7 @@ export default {
|
|
|
1205
1368
|
this.ctx.stroke()
|
|
1206
1369
|
this.ctx.closePath()
|
|
1207
1370
|
if (type === 'end') {
|
|
1371
|
+
// 绘制结束时保存数据
|
|
1208
1372
|
this.points.push({
|
|
1209
1373
|
x: this.textX,
|
|
1210
1374
|
y: this.textY,
|
|
@@ -1220,7 +1384,7 @@ export default {
|
|
|
1220
1384
|
this.$emit('drawEnd', this.points)
|
|
1221
1385
|
}
|
|
1222
1386
|
},
|
|
1223
|
-
//
|
|
1387
|
+
// 绘制直线
|
|
1224
1388
|
straight(obj, type) {
|
|
1225
1389
|
obj.index = this.pageIndex
|
|
1226
1390
|
obj.type = 'straight'
|
|
@@ -1252,9 +1416,9 @@ export default {
|
|
|
1252
1416
|
this.$emit('drawEnd', this.points)
|
|
1253
1417
|
}
|
|
1254
1418
|
},
|
|
1255
|
-
//
|
|
1419
|
+
// 绘制圆形(从起点到鼠标位置的距离为半径)
|
|
1256
1420
|
circular(obj, type) {
|
|
1257
|
-
if (obj.x - this.textX <= 0) return
|
|
1421
|
+
if (obj.x - this.textX <= 0) return // 半径不能为负
|
|
1258
1422
|
obj.index = this.pageIndex
|
|
1259
1423
|
obj.type = 'circular'
|
|
1260
1424
|
obj.scale = this.scales
|
|
@@ -1284,7 +1448,7 @@ export default {
|
|
|
1284
1448
|
this.$emit('drawEnd', this.points)
|
|
1285
1449
|
}
|
|
1286
1450
|
},
|
|
1287
|
-
//
|
|
1451
|
+
// 绘制矩形
|
|
1288
1452
|
rectangle(obj, type) {
|
|
1289
1453
|
obj.index = this.pageIndex
|
|
1290
1454
|
obj.type = 'rectangle'
|
|
@@ -1315,7 +1479,7 @@ export default {
|
|
|
1315
1479
|
this.$emit('drawEnd', this.points)
|
|
1316
1480
|
}
|
|
1317
1481
|
},
|
|
1318
|
-
//
|
|
1482
|
+
// 绘制自由线条(画笔)
|
|
1319
1483
|
line(obj) {
|
|
1320
1484
|
obj.index = this.pageIndex
|
|
1321
1485
|
obj.type = 'line'
|
|
@@ -1335,13 +1499,18 @@ export default {
|
|
|
1335
1499
|
this.points.push(obj)
|
|
1336
1500
|
this.$emit('drawEnd', obj,'line')
|
|
1337
1501
|
},
|
|
1502
|
+
|
|
1503
|
+
// ----- Canvas 重绘相关方法 -----
|
|
1504
|
+
|
|
1505
|
+
// 清除 Canvas 并重绘所有批注
|
|
1338
1506
|
clearRect(v) {
|
|
1339
1507
|
const width = this.canvasStyle.widthCanvas
|
|
1340
1508
|
const height = this.canvasStyle.heightCanvas
|
|
1341
1509
|
this.ctx.clearRect(0, 0, width, height)
|
|
1342
|
-
if (v) return
|
|
1510
|
+
if (v) return // 仅清空不重绘
|
|
1343
1511
|
this.processing()
|
|
1344
1512
|
},
|
|
1513
|
+
// 重绘线条
|
|
1345
1514
|
lineProcessing(data, data2, v) {
|
|
1346
1515
|
this.ctx.beginPath()
|
|
1347
1516
|
this.ctx.moveTo(data.x * this.scales / data.scale + v.x, data.y * this.scales / data.scale + v.y)
|
|
@@ -1355,6 +1524,7 @@ export default {
|
|
|
1355
1524
|
this.ctx.stroke()
|
|
1356
1525
|
this.ctx.closePath()
|
|
1357
1526
|
},
|
|
1527
|
+
// 重绘矩形
|
|
1358
1528
|
rectangleProcessing(data, v) {
|
|
1359
1529
|
this.ctx.beginPath()
|
|
1360
1530
|
this.ctx.lineWidth = data.border * this.sratio
|
|
@@ -1363,6 +1533,7 @@ export default {
|
|
|
1363
1533
|
this.ctx.stroke()
|
|
1364
1534
|
this.ctx.closePath()
|
|
1365
1535
|
},
|
|
1536
|
+
// 重绘圆形
|
|
1366
1537
|
circularProcessing(data, v) {
|
|
1367
1538
|
this.ctx.beginPath()
|
|
1368
1539
|
this.ctx.lineWidth = data.border * this.sratio
|
|
@@ -1371,6 +1542,7 @@ export default {
|
|
|
1371
1542
|
this.ctx.stroke()
|
|
1372
1543
|
this.ctx.closePath()
|
|
1373
1544
|
},
|
|
1545
|
+
// 重绘直线
|
|
1374
1546
|
straightProcessing(data, v) {
|
|
1375
1547
|
this.ctx.beginPath()
|
|
1376
1548
|
this.ctx.lineWidth = data.border * this.sratio
|
|
@@ -1380,6 +1552,7 @@ export default {
|
|
|
1380
1552
|
this.ctx.stroke()
|
|
1381
1553
|
this.ctx.closePath()
|
|
1382
1554
|
},
|
|
1555
|
+
// 重绘箭头
|
|
1383
1556
|
arrowProcessing(data, v) {
|
|
1384
1557
|
const angle = Math.atan2(data.y * this.scales / data.scale - data.y2 * this.scales / data.scale, data.x * this.scales / data.scale - data.x2 * this.scales / data.scale) * 180 / Math.PI
|
|
1385
1558
|
const angle1 = (angle + 20) * Math.PI / 180
|
|
@@ -1404,6 +1577,7 @@ export default {
|
|
|
1404
1577
|
this.ctx.stroke()
|
|
1405
1578
|
this.ctx.closePath()
|
|
1406
1579
|
},
|
|
1580
|
+
// 重绘文字
|
|
1407
1581
|
textProcessing(data, v) {
|
|
1408
1582
|
const arr = data.text
|
|
1409
1583
|
for (let i = 0; i < arr.length; i++) {
|
|
@@ -1415,6 +1589,7 @@ export default {
|
|
|
1415
1589
|
this.ctx.closePath()
|
|
1416
1590
|
}
|
|
1417
1591
|
},
|
|
1592
|
+
// 重绘标记
|
|
1418
1593
|
signProcessing(data, v) {
|
|
1419
1594
|
const x = data.x * this.scales / data.scale + v.x
|
|
1420
1595
|
const y = data.y * this.scales / data.scale + v.y
|
|
@@ -1424,9 +1599,9 @@ export default {
|
|
|
1424
1599
|
this.ctx.fill();
|
|
1425
1600
|
this.ctx.closePath();
|
|
1426
1601
|
this.ctx.beginPath();
|
|
1427
|
-
this.ctx.moveTo(x - 50, y + 15);
|
|
1428
|
-
this.ctx.lineTo(x - 10, y + 15);
|
|
1429
|
-
this.ctx.lineTo(x - 30, y + 40);
|
|
1602
|
+
this.ctx.moveTo(x - 50, y + 15);
|
|
1603
|
+
this.ctx.lineTo(x - 10, y + 15);
|
|
1604
|
+
this.ctx.lineTo(x - 30, y + 40);
|
|
1430
1605
|
this.ctx.fillStyle = 'red';
|
|
1431
1606
|
this.ctx.fill();
|
|
1432
1607
|
this.ctx.closePath()
|
|
@@ -1437,7 +1612,8 @@ export default {
|
|
|
1437
1612
|
this.ctx.stroke();
|
|
1438
1613
|
this.ctx.closePath()
|
|
1439
1614
|
},
|
|
1440
|
-
|
|
1615
|
+
|
|
1616
|
+
// 处理所有批注数据并重绘到 Canvas
|
|
1441
1617
|
processing() {
|
|
1442
1618
|
for (let i = 0; i < this.points.length; i++) {
|
|
1443
1619
|
if (this.points[i].index === this.pageIndex) {
|
|
@@ -1465,6 +1641,10 @@ export default {
|
|
|
1465
1641
|
}
|
|
1466
1642
|
}
|
|
1467
1643
|
},
|
|
1644
|
+
|
|
1645
|
+
// ----- 翻页与PDF加载 -----
|
|
1646
|
+
|
|
1647
|
+
// 下一页(向左翻页)
|
|
1468
1648
|
flipLeft(e, v) {
|
|
1469
1649
|
this.extendRightDel()
|
|
1470
1650
|
if (e > this.pdfPages) {
|
|
@@ -1486,6 +1666,7 @@ export default {
|
|
|
1486
1666
|
})
|
|
1487
1667
|
}
|
|
1488
1668
|
},
|
|
1669
|
+
// 上一页(向右翻页)
|
|
1489
1670
|
flipRight(e, v) {
|
|
1490
1671
|
this.extendRightDel()
|
|
1491
1672
|
if (e < 1) {
|
|
@@ -1507,18 +1688,19 @@ export default {
|
|
|
1507
1688
|
})
|
|
1508
1689
|
}
|
|
1509
1690
|
},
|
|
1691
|
+
// 加载 PDF 源文件
|
|
1510
1692
|
sourceUrl() {
|
|
1511
1693
|
if (this.source === '' || this.source === undefined || this.source === null) return
|
|
1512
1694
|
let that = this
|
|
1513
1695
|
that.loading = true
|
|
1514
1696
|
const loadingTask = PdfJs.getDocument({
|
|
1515
1697
|
url: that.source,
|
|
1516
|
-
cMapUrl: "/zydx/static/cmaps/",
|
|
1698
|
+
cMapUrl: "/zydx/static/cmaps/", // 中文字符映射表路径
|
|
1517
1699
|
cMapPacked: true
|
|
1518
1700
|
})
|
|
1519
1701
|
loadingTask.promise.then((pdf) => {
|
|
1520
1702
|
pdfs[that.id] = pdf
|
|
1521
|
-
that.pdfPages = pdf.numPages
|
|
1703
|
+
that.pdfPages = pdf.numPages
|
|
1522
1704
|
that.$nextTick(() => {
|
|
1523
1705
|
if (that.doublePage) {
|
|
1524
1706
|
that.readDoublePdf(pdf)
|
|
@@ -1534,14 +1716,16 @@ export default {
|
|
|
1534
1716
|
})
|
|
1535
1717
|
})
|
|
1536
1718
|
},
|
|
1719
|
+
// 获取字体信息
|
|
1537
1720
|
fontName(v,n) {
|
|
1538
1721
|
return n[v]
|
|
1539
1722
|
},
|
|
1723
|
+
// 单页模式:渲染单页 PDF
|
|
1540
1724
|
readPdf: debounce(function () {
|
|
1541
1725
|
if(Object.keys(pdfs).length === 0) return
|
|
1542
1726
|
setTimeout(() => {
|
|
1543
1727
|
let that = this
|
|
1544
|
-
that.mouse()
|
|
1728
|
+
that.mouse() // 重置工具状态
|
|
1545
1729
|
that.$nextTick(() => {
|
|
1546
1730
|
pdfs[that.id]?.getPage(that.pageIndex).then(function (page) {
|
|
1547
1731
|
that.doc = page
|
|
@@ -1551,6 +1735,7 @@ export default {
|
|
|
1551
1735
|
let canvas2 = document.getElementById(`${that.id}2`)
|
|
1552
1736
|
that.ctx = canvas?.getContext('2d');
|
|
1553
1737
|
let ctx2 = canvas2?.getContext('2d');
|
|
1738
|
+
// 计算合适的缩放比例
|
|
1554
1739
|
let viewport1 = page.getViewport({scale: 1.5})
|
|
1555
1740
|
const sc1 = (viewport1.width / viewport1.height).toFixed(2)
|
|
1556
1741
|
that.boxWidth = that.$refs.wrap?.offsetWidth
|
|
@@ -1565,6 +1750,7 @@ export default {
|
|
|
1565
1750
|
const sc = (viewport.width / viewport.height).toFixed(2)
|
|
1566
1751
|
const wid = that.$refs.wrap?.offsetWidth - 10
|
|
1567
1752
|
const hei = wid / sc
|
|
1753
|
+
// 设置 Canvas 尺寸(sratio倍提高清晰度)
|
|
1568
1754
|
canvas.width = wid * that.sratio
|
|
1569
1755
|
canvas.height = hei * that.sratio
|
|
1570
1756
|
canvas.style.width = wid + 'px'
|
|
@@ -1583,13 +1769,15 @@ export default {
|
|
|
1583
1769
|
let renderContext = {
|
|
1584
1770
|
canvasContext: ctx2,
|
|
1585
1771
|
viewport: viewport,
|
|
1586
|
-
transform: [1, 0, 0, 1, 0, 0]
|
|
1772
|
+
transform: [1, 0, 0, 1, 0, 0] // 避免放大导致的模糊
|
|
1587
1773
|
}
|
|
1588
1774
|
page.render(renderContext)
|
|
1775
|
+
// 获取文本内容用于 textLayer 渲染
|
|
1589
1776
|
page.getTextContent().then((res) => {
|
|
1590
1777
|
that.items = res.items
|
|
1591
1778
|
that.styles = res.styles
|
|
1592
1779
|
})
|
|
1780
|
+
// 获取 PDF 内置的标注数据
|
|
1593
1781
|
page.getAnnotations().then((res) => {
|
|
1594
1782
|
that.annotationsInit = res
|
|
1595
1783
|
const arr = that.annotationsData.map(x => {
|
|
@@ -1610,18 +1798,19 @@ export default {
|
|
|
1610
1798
|
that.flipRights = false
|
|
1611
1799
|
that.flipLefts = true
|
|
1612
1800
|
}
|
|
1613
|
-
//
|
|
1801
|
+
// 延迟生成 Canvas Base64 数据用于翻页过渡动画
|
|
1614
1802
|
setTimeout(() => {
|
|
1615
1803
|
that.flipRights = false
|
|
1616
1804
|
that.flipLefts = false
|
|
1617
1805
|
that.oneShow = false
|
|
1618
1806
|
that.imgArr = canvas2.toDataURL('image/jpeg', 1)
|
|
1619
|
-
that.processing()
|
|
1807
|
+
that.processing() // 重绘批注
|
|
1620
1808
|
}, 1000)
|
|
1621
1809
|
})
|
|
1622
1810
|
})
|
|
1623
1811
|
}, 200)
|
|
1624
1812
|
}, 200),
|
|
1813
|
+
// 双页模式:渲染所有页的 PDF
|
|
1625
1814
|
readDoublePdf: debounce(function () {
|
|
1626
1815
|
setTimeout(() => {
|
|
1627
1816
|
let that = this
|
|
@@ -1668,7 +1857,7 @@ export default {
|
|
|
1668
1857
|
let renderContext = {
|
|
1669
1858
|
canvasContext: item.ctx2,
|
|
1670
1859
|
viewport: viewport,
|
|
1671
|
-
transform: [1, 0, 0, 1, 0, 0]
|
|
1860
|
+
transform: [1, 0, 0, 1, 0, 0]
|
|
1672
1861
|
}
|
|
1673
1862
|
page.render(renderContext)
|
|
1674
1863
|
page.getTextContent().then((res) => {
|
|
@@ -1687,7 +1876,6 @@ export default {
|
|
|
1687
1876
|
that.flipRights = false
|
|
1688
1877
|
that.flipLefts = true
|
|
1689
1878
|
}
|
|
1690
|
-
// 获取canvas的base64数据
|
|
1691
1879
|
setTimeout(() => {
|
|
1692
1880
|
that.flipRights = false
|
|
1693
1881
|
that.flipLefts = false
|
|
@@ -1700,8 +1888,8 @@ export default {
|
|
|
1700
1888
|
})
|
|
1701
1889
|
}, 200)
|
|
1702
1890
|
}, 200),
|
|
1891
|
+
// 生成唯一 Canvas ID(时间戳+随机字符串)
|
|
1703
1892
|
generateUniqueKey() {
|
|
1704
|
-
// Math.random().toString(36).substr(2)
|
|
1705
1893
|
return `${new Date().getTime()}${Math.random().toString(36).substr(2)}`;
|
|
1706
1894
|
}
|
|
1707
1895
|
}
|
|
@@ -1713,6 +1901,7 @@ export default {
|
|
|
1713
1901
|
@import './icon.css';
|
|
1714
1902
|
@import './annotationLayer.css';
|
|
1715
1903
|
@import './textLayer.css';
|
|
1904
|
+
/* 拓展阅读批注容器 */
|
|
1716
1905
|
.magnifier{
|
|
1717
1906
|
position: absolute;
|
|
1718
1907
|
text-align: initial;
|
|
@@ -1727,6 +1916,7 @@ export default {
|
|
|
1727
1916
|
display: block;
|
|
1728
1917
|
margin: 0 auto;
|
|
1729
1918
|
}
|
|
1919
|
+
/* 拓展阅读弹出列表 */
|
|
1730
1920
|
.magnifier-list{
|
|
1731
1921
|
position: absolute;
|
|
1732
1922
|
width: 200px;
|
|
@@ -1739,6 +1929,7 @@ export default {
|
|
|
1739
1929
|
opacity: 0;
|
|
1740
1930
|
overflow: hidden;
|
|
1741
1931
|
}
|
|
1932
|
+
/* 拓展阅读列表头部 */
|
|
1742
1933
|
.magnifier-head{
|
|
1743
1934
|
height: 20px;
|
|
1744
1935
|
width: 100%;
|
|
@@ -1760,6 +1951,7 @@ export default {
|
|
|
1760
1951
|
font-size: 12px;
|
|
1761
1952
|
color: #fff;
|
|
1762
1953
|
}
|
|
1954
|
+
/* 拓展阅读内容区 */
|
|
1763
1955
|
.magnifier-cont{
|
|
1764
1956
|
padding: 5px;
|
|
1765
1957
|
}
|
|
@@ -1783,12 +1975,10 @@ export default {
|
|
|
1783
1975
|
opacity: 1;
|
|
1784
1976
|
}
|
|
1785
1977
|
}
|
|
1978
|
+
/* 右键菜单-添加链接 */
|
|
1786
1979
|
.extend-right{
|
|
1787
1980
|
position: absolute;
|
|
1788
1981
|
z-index: 5;
|
|
1789
|
-
/* border-radius: 20px; */
|
|
1790
|
-
/* box-shadow: 0 0 10px rgba(0, 0, 0, 0.25); */
|
|
1791
|
-
/* padding: 10px; */
|
|
1792
1982
|
background-color: #DEDCDC;
|
|
1793
1983
|
cursor: pointer;
|
|
1794
1984
|
transform: scaleX(-1);
|
|
@@ -1799,17 +1989,6 @@ export default {
|
|
|
1799
1989
|
display: flex;
|
|
1800
1990
|
transform: scaleX(-1);
|
|
1801
1991
|
}
|
|
1802
|
-
/* .extend-right:after {
|
|
1803
|
-
content: '';
|
|
1804
|
-
position: absolute;
|
|
1805
|
-
top: 54%;
|
|
1806
|
-
right: 0;
|
|
1807
|
-
width: 30px;
|
|
1808
|
-
height: 30px;
|
|
1809
|
-
background: url("../img/sanjiao.png") no-repeat 0 0;
|
|
1810
|
-
background-size: 100% 100%;
|
|
1811
|
-
transform: rotate(-85deg) scaleY(-1);
|
|
1812
|
-
} */
|
|
1813
1992
|
.extend-right-cont>img{
|
|
1814
1993
|
width: 14px !important;
|
|
1815
1994
|
height: 14px !important;
|
|
@@ -1820,8 +1999,8 @@ export default {
|
|
|
1820
1999
|
line-height: 20px;
|
|
1821
2000
|
font-size: 12px;
|
|
1822
2001
|
color: #fff;
|
|
1823
|
-
/* padding-left: 5px; */
|
|
1824
2002
|
}
|
|
2003
|
+
/* 鼠标穿透*/
|
|
1825
2004
|
.isPointer{
|
|
1826
2005
|
pointer-events: none;
|
|
1827
2006
|
}
|
|
@@ -1829,6 +2008,7 @@ export default {
|
|
|
1829
2008
|
width: 20px !important;
|
|
1830
2009
|
font-size: 12px !important;
|
|
1831
2010
|
}
|
|
2011
|
+
/* 标注层 */
|
|
1832
2012
|
.annotationLayer{
|
|
1833
2013
|
width: 100%;
|
|
1834
2014
|
height: 100%;
|
|
@@ -1848,12 +2028,14 @@ export default {
|
|
|
1848
2028
|
width: 100%;
|
|
1849
2029
|
height: 100%;
|
|
1850
2030
|
}
|
|
2031
|
+
/* 文本层 */
|
|
1851
2032
|
.textLayer>:is(i){
|
|
1852
2033
|
position: absolute;
|
|
1853
2034
|
}
|
|
1854
2035
|
.textLayer :is(span){
|
|
1855
2036
|
color: transparent;
|
|
1856
2037
|
}
|
|
2038
|
+
/* 批注绘制画布 */
|
|
1857
2039
|
.wrap-can-one {
|
|
1858
2040
|
position: absolute;
|
|
1859
2041
|
top: 0;
|
|
@@ -1861,6 +2043,7 @@ export default {
|
|
|
1861
2043
|
z-index: 10;
|
|
1862
2044
|
}
|
|
1863
2045
|
|
|
2046
|
+
/* 文字批注拖拽框 */
|
|
1864
2047
|
.text-frame {
|
|
1865
2048
|
position: absolute;
|
|
1866
2049
|
top: 0;
|
|
@@ -1883,6 +2066,7 @@ export default {
|
|
|
1883
2066
|
height: 100%;
|
|
1884
2067
|
}
|
|
1885
2068
|
|
|
2069
|
+
/* 页面容器 */
|
|
1886
2070
|
.wrap {
|
|
1887
2071
|
width: 100%;
|
|
1888
2072
|
height: calc(100% - 20px);
|
|
@@ -1892,6 +2076,7 @@ export default {
|
|
|
1892
2076
|
padding: 5px;
|
|
1893
2077
|
}
|
|
1894
2078
|
|
|
2079
|
+
/* 双页模式奇数偶数页间距 */
|
|
1895
2080
|
.wrap-block:nth-child(2n+1) {
|
|
1896
2081
|
padding: 5px 5px 5px 10px;
|
|
1897
2082
|
}
|
|
@@ -1900,6 +2085,7 @@ export default {
|
|
|
1900
2085
|
padding: 5px 10px 5px 5px;
|
|
1901
2086
|
}
|
|
1902
2087
|
|
|
2088
|
+
/* Canvas 容器 */
|
|
1903
2089
|
.wrap-can {
|
|
1904
2090
|
width: 100%;
|
|
1905
2091
|
/*display: inline-block;*/
|
|
@@ -1918,11 +2104,13 @@ export default {
|
|
|
1918
2104
|
height: 100%;
|
|
1919
2105
|
}
|
|
1920
2106
|
|
|
2107
|
+
/* 底部翻页按钮 */
|
|
1921
2108
|
.but-wrap {
|
|
1922
2109
|
text-align: center;
|
|
1923
2110
|
margin-top: 20px;
|
|
1924
2111
|
}
|
|
1925
2112
|
|
|
2113
|
+
/* pages 区域 */
|
|
1926
2114
|
.pages {
|
|
1927
2115
|
width: 100%;
|
|
1928
2116
|
height: 100%;
|
|
@@ -1930,6 +2118,7 @@ export default {
|
|
|
1930
2118
|
overflow-y: auto;
|
|
1931
2119
|
}
|
|
1932
2120
|
|
|
2121
|
+
/* 左侧翻页按钮区域 */
|
|
1933
2122
|
.page-but-left {
|
|
1934
2123
|
position: absolute;
|
|
1935
2124
|
top: 0;
|
|
@@ -1947,6 +2136,7 @@ export default {
|
|
|
1947
2136
|
left: 0;
|
|
1948
2137
|
}
|
|
1949
2138
|
|
|
2139
|
+
/* 右侧翻页按钮区域 */
|
|
1950
2140
|
.page-but-right {
|
|
1951
2141
|
position: absolute;
|
|
1952
2142
|
top: 0;
|
|
@@ -1972,11 +2162,13 @@ export default {
|
|
|
1972
2162
|
font-size: 14px;
|
|
1973
2163
|
}
|
|
1974
2164
|
|
|
2165
|
+
/* 文档视图主容器 */
|
|
1975
2166
|
.docView {
|
|
1976
2167
|
height: 100%;
|
|
1977
2168
|
position: relative;
|
|
1978
2169
|
}
|
|
1979
2170
|
|
|
2171
|
+
/* 翻页按钮样式 */
|
|
1980
2172
|
.but-brown {
|
|
1981
2173
|
background-color: #c64c10;
|
|
1982
2174
|
padding: 0 20px;
|
|
@@ -1990,25 +2182,24 @@ export default {
|
|
|
1990
2182
|
margin-left: 10px;
|
|
1991
2183
|
}
|
|
1992
2184
|
|
|
2185
|
+
/* PDF 书本容器 */
|
|
1993
2186
|
.book {
|
|
1994
2187
|
width: 100%;
|
|
1995
|
-
/*min-height: 600px;*/
|
|
1996
|
-
/*max-height: 1200px;
|
|
1997
|
-
overflow-y: auto;*/
|
|
1998
2188
|
}
|
|
1999
2189
|
|
|
2000
2190
|
.book::-webkit-scrollbar {
|
|
2001
2191
|
display: none;
|
|
2002
2192
|
}
|
|
2003
2193
|
|
|
2194
|
+
/* 按钮禁用态 */
|
|
2004
2195
|
.but-act {
|
|
2005
2196
|
background-color: #bbbbbb;
|
|
2006
2197
|
color: #fff;
|
|
2007
2198
|
}
|
|
2008
2199
|
|
|
2200
|
+
/* 加载动画遮罩 */
|
|
2009
2201
|
.loading-back {
|
|
2010
2202
|
min-height: 600px;
|
|
2011
|
-
/*position: absolute;*/
|
|
2012
2203
|
top: 0;
|
|
2013
2204
|
left: 0;
|
|
2014
2205
|
right: 0;
|
|
@@ -2023,6 +2214,7 @@ export default {
|
|
|
2023
2214
|
margin: 0 auto;
|
|
2024
2215
|
}
|
|
2025
2216
|
|
|
2217
|
+
/* 加载文字动画 */
|
|
2026
2218
|
.loadings {
|
|
2027
2219
|
display: inline-block;
|
|
2028
2220
|
font-size: 28px;
|
|
@@ -2056,6 +2248,7 @@ export default {
|
|
|
2056
2248
|
}
|
|
2057
2249
|
}
|
|
2058
2250
|
|
|
2251
|
+
/* 双页模式容器 */
|
|
2059
2252
|
.wrap-box {
|
|
2060
2253
|
display: flex;
|
|
2061
2254
|
flex-flow: row wrap;
|
|
@@ -2070,6 +2263,7 @@ div {
|
|
|
2070
2263
|
box-sizing: border-box;
|
|
2071
2264
|
}
|
|
2072
2265
|
|
|
2266
|
+
/* 全屏查看工具栏 */
|
|
2073
2267
|
.full-screen {
|
|
2074
2268
|
position: absolute;
|
|
2075
2269
|
top: 20px;
|
|
@@ -2104,6 +2298,5 @@ div {
|
|
|
2104
2298
|
.full-screen-img > img {
|
|
2105
2299
|
width: 20px;
|
|
2106
2300
|
height: 20px;
|
|
2107
|
-
/*margin-left: 5px;*/
|
|
2108
2301
|
}
|
|
2109
2302
|
</style>
|