Mercurial > hg > orthanc-stone
comparison Applications/StoneWebViewer/WebApplication/pdf-viewer.js @ 1652:fa9e6bf84958
integrating pdf.js into Stone Web viewer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 16 Nov 2020 20:47:53 +0100 |
parents | |
children | 66e5fcdf5597 |
comparison
equal
deleted
inserted
replaced
1651:00674f3695f2 | 1652:fa9e6bf84958 |
---|---|
1 /** | |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 | |
23 | |
24 // Loaded via <script> tag, create shortcut to access PDF.js exports. | |
25 var pdfjsLib = window['pdfjs-dist/build/pdf']; | |
26 | |
27 // The workerSrc property shall be specified. | |
28 pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.5.207/build/pdf.worker.min.js'; | |
29 | |
30 | |
31 | |
32 var ZOOM_FACTOR = 1.3; | |
33 var FIT_MARGIN = 10; | |
34 | |
35 Vue.component('pdf-viewer', { | |
36 props: [ 'prefix', 'pdf' ], // "pdf" must correspond to a "Uint8Array" | |
37 template: '#pdf-viewer', | |
38 data: function() { | |
39 return { | |
40 container: null, | |
41 canvas: null, | |
42 ctx: null, | |
43 | |
44 scale: 1, | |
45 countPages: 0, | |
46 currentPage: 0, | |
47 pdfDoc: null, | |
48 isRendering: false, | |
49 pageNumPending: null | |
50 } | |
51 }, | |
52 watch: { | |
53 pdf: function(newVal, oldVal) { | |
54 this.LoadPdf(); | |
55 } | |
56 }, | |
57 mounted: function() { | |
58 this.container = document.getElementById(this.prefix + '-container'); | |
59 this.canvas = document.getElementById(this.prefix + '-canvas'); | |
60 this.ctx = this.canvas.getContext('2d'); | |
61 | |
62 if (this.container === null || | |
63 this.canvas === null || | |
64 this.ctx === null) { | |
65 alert('Bad viewer configuration'); | |
66 } | |
67 | |
68 var that = this; | |
69 this.container.addEventListener('wheel', function(event) { | |
70 that.MouseWheel(event); | |
71 }); | |
72 }, | |
73 methods: { | |
74 NextPage: function() { | |
75 if (this.pdfDoc !== null && | |
76 this.currentPage < this.pdfDoc.numPages) { | |
77 this.QueueRenderPage(this.currentPage + 1); | |
78 } | |
79 }, | |
80 PreviousPage: function() { | |
81 if (this.pdfDoc !== null && | |
82 this.currentPage > 1) { | |
83 this.QueueRenderPage(this.currentPage - 1); | |
84 } | |
85 }, | |
86 FitWidth: function() { | |
87 if (this.pdfDoc !== null) { | |
88 var that = this; | |
89 this.pdfDoc.getPage(this.currentPage).then(function(page) { | |
90 // https://github.com/mozilla/pdf.js/issues/5628 | |
91 // https://stackoverflow.com/a/21064102/881731 | |
92 // https://stackoverflow.com/a/60008044/881731 | |
93 var scrollbarWidth = window.innerWidth - document.body.clientWidth + FIT_MARGIN; | |
94 that.scale = (that.container.offsetWidth - scrollbarWidth) / page.getViewport({ scale: 1.0 }).width; | |
95 that.QueueRenderPage(that.currentPage); | |
96 }); | |
97 } | |
98 }, | |
99 FitHeight: function() { | |
100 if (this.pdfDoc !== null) { | |
101 var that = this; | |
102 this.pdfDoc.getPage(this.currentPage).then(function(page) { | |
103 // The computation below assumes that "line-height: 0px" CSS | |
104 // on the parent element of the canvas. | |
105 | |
106 // https://github.com/mozilla/pdf.js/issues/5628 | |
107 var scrollbarHeight = window.innerHeight - document.body.clientHeight + FIT_MARGIN; | |
108 that.scale = (that.container.offsetHeight - scrollbarHeight) / page.getViewport({ scale: 1.0 }).height; | |
109 //that.scale = that.container.clientHeight / page.getViewport({ scale: 1.0 }).height; | |
110 that.QueueRenderPage(that.currentPage); | |
111 }); | |
112 } | |
113 }, | |
114 ZoomIn: function() { | |
115 this.scale *= ZOOM_FACTOR; | |
116 this.QueueRenderPage(this.currentPage); | |
117 }, | |
118 ZoomOut: function() { | |
119 this.scale /= ZOOM_FACTOR; | |
120 this.QueueRenderPage(this.currentPage); | |
121 }, | |
122 LoadPdf: function(pdf) { | |
123 var that = this; | |
124 pdfjsLib.getDocument(new Uint8Array(this.pdf)).promise.then(function(pdfDoc_) { | |
125 that.pdfDoc = pdfDoc_; | |
126 that.currentPage = 0; | |
127 that.countPages = pdfDoc_.numPages; | |
128 that.scale = 1; | |
129 that.isRendering = false; | |
130 that.pageNumPending = null; | |
131 | |
132 // Initial/first page rendering | |
133 that.RenderPage(1); | |
134 }); | |
135 }, | |
136 RenderPage: function(pageNum) { | |
137 var that = this; | |
138 | |
139 if (this.pdfDoc !== null && | |
140 pageNum >= 1 && | |
141 pageNum <= this.countPages) { | |
142 this.isRendering = true; | |
143 this.pdfDoc.getPage(pageNum).then(function(page) { | |
144 var viewport = page.getViewport({scale: that.scale}); | |
145 | |
146 that.canvas.height = viewport.height; | |
147 that.canvas.width = viewport.width; | |
148 | |
149 // Horizontal centering of the canvas. This requires CSS | |
150 // "position: relative" on the canvas element. | |
151 if (that.canvas.width < that.container.clientWidth) { | |
152 that.canvas.style.left = Math.floor((that.container.clientWidth - viewport.width) / 2) + 'px'; | |
153 } else { | |
154 that.canvas.style.left = '0px'; | |
155 } | |
156 | |
157 // Render PDF page into canvas context | |
158 var renderContext = { | |
159 canvasContext: that.ctx, | |
160 viewport: viewport | |
161 }; | |
162 | |
163 var renderTask = page.render(renderContext); | |
164 | |
165 // Wait for rendering to finish | |
166 renderTask.promise.then(function() { | |
167 that.isRendering = false; | |
168 that.currentPage = pageNum; | |
169 if (that.pageNumPending !== null) { | |
170 // New page rendering is pending | |
171 that.currentPage = that.pageNumPending; | |
172 that.pageNumPending = null; | |
173 that.RenderPage(); | |
174 } | |
175 }); | |
176 }); | |
177 } | |
178 }, | |
179 QueueRenderPage: function(pageNum) { | |
180 if (this.isRendering) { | |
181 this.pageNumPending = pageNum; | |
182 } else { | |
183 this.RenderPage(pageNum); | |
184 } | |
185 }, | |
186 MouseWheel: function(event) { | |
187 if (event.ctrlKey) { | |
188 if (event.deltaY < 0) { | |
189 this.ZoomIn(); | |
190 } else if (event.deltaY > 0) { | |
191 this.ZoomOut(); | |
192 } | |
193 | |
194 event.preventDefault(); | |
195 } | |
196 } | |
197 } | |
198 }); |