comparison Applications/StoneWebViewer/WebApplication/app.js @ 1672:570398585b5f

start support of cine sequences
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 23 Nov 2020 15:39:27 +0100
parents f62f685e0eb2
children dd50f8a1a2be
comparison
equal deleted inserted replaced
1671:2c2512918a0f 1672:570398585b5f
46 'quality', 'framesCount', 'currentFrame', 'showInfo' ], 46 'quality', 'framesCount', 'currentFrame', 'showInfo' ],
47 template: '#viewport-template', 47 template: '#viewport-template',
48 data: function () { 48 data: function () {
49 return { 49 return {
50 stone: stone, // To access global object "stone" from "index.html" 50 stone: stone, // To access global object "stone" from "index.html"
51 status: 'waiting' 51 status: 'waiting',
52 cineControls: false,
53 cineIncrement: 0,
54 cineFramesPerSecond: 30,
55 cineTimeoutId: null,
56 cineLoadingFrame: false
52 } 57 }
53 }, 58 },
54 watch: { 59 watch: {
60 currentFrame: function(newVal, oldVal) {
61 /**
62 * The "FrameUpdated" event has been received, which indicates
63 * that the schedule frame has been displayed: The cine loop can
64 * proceed to the next frame (check out "CineCallback()").
65 **/
66 this.cineLoadingFrame = false;
67 },
55 series: function(newVal, oldVal) { 68 series: function(newVal, oldVal) {
56 this.status = 'loading'; 69 this.status = 'loading';
70 this.cineControls = false;
71 this.cineMode = '';
72 this.cineLoadingFrame = false;
73 this.cineRate = 30; // Default value
74
75 if (this.cineTimeoutId !== null) {
76 clearTimeout(this.cineTimeoutId);
77 this.cineTimeoutId = null;
78 }
57 79
58 var studyInstanceUid = newVal.tags[STUDY_INSTANCE_UID]; 80 var studyInstanceUid = newVal.tags[STUDY_INSTANCE_UID];
59 var seriesInstanceUid = newVal.tags[SERIES_INSTANCE_UID]; 81 var seriesInstanceUid = newVal.tags[SERIES_INSTANCE_UID];
60 stone.SpeedUpFetchSeriesMetadata(studyInstanceUid, seriesInstanceUid); 82 stone.SpeedUpFetchSeriesMetadata(studyInstanceUid, seriesInstanceUid);
61 83
62 if ((newVal.type == stone.ThumbnailType.IMAGE || 84 if ((newVal.type == stone.ThumbnailType.IMAGE ||
63 newVal.type == stone.ThumbnailType.NO_PREVIEW) && 85 newVal.type == stone.ThumbnailType.NO_PREVIEW) &&
64 newVal.complete) { 86 newVal.complete) {
65 this.status = 'ready'; 87 this.status = 'ready';
66 88
94 } 116 }
95 } 117 }
96 }, 118 },
97 mounted: function() { 119 mounted: function() {
98 var that = this; 120 var that = this;
99 121
122 window.addEventListener('SeriesDetailsReady', function(args) {
123 var canvasId = args.detail.canvasId;
124 if (canvasId == that.canvasId) {
125 that.cineFramesPerSecond = stone.GetCineRate(canvasId);
126 }
127 });
128
100 window.addEventListener('PdfLoaded', function(args) { 129 window.addEventListener('PdfLoaded', function(args) {
101 var studyInstanceUid = args.detail.studyInstanceUid; 130 var studyInstanceUid = args.detail.studyInstanceUid;
102 var seriesInstanceUid = args.detail.seriesInstanceUid; 131 var seriesInstanceUid = args.detail.seriesInstanceUid;
103 var pdfPointer = args.detail.pdfPointer; 132 var pdfPointer = args.detail.pdfPointer;
104 var pdfSize = args.detail.pdfSize; 133 var pdfSize = args.detail.pdfSize;
135 this.$emit('updated-series', parseInt(event.dataTransfer.getData('seriesIndex'), 10)); 164 this.$emit('updated-series', parseInt(event.dataTransfer.getData('seriesIndex'), 10));
136 }, 165 },
137 MakeActive: function() { 166 MakeActive: function() {
138 this.$emit('selected-viewport'); 167 this.$emit('selected-viewport');
139 }, 168 },
140 DecrementFrame: function() { 169 DecrementFrame: function(isCircular) {
141 stone.DecrementFrame(this.canvasId); 170 return stone.DecrementFrame(this.canvasId, isCircular);
142 }, 171 },
143 IncrementFrame: function() { 172 IncrementFrame: function(isCircular) {
144 stone.IncrementFrame(this.canvasId); 173 return stone.IncrementFrame(this.canvasId, isCircular);
174 },
175 CinePlay: function() {
176 this.cineControls = true;
177 this.cineIncrement = 1;
178 this.UpdateCine();
179 },
180 CinePause: function() {
181 if (this.cineIncrement == 0) {
182 // Two clicks on the "pause" button will hide the playback control
183 this.cineControls = !this.cineControls;
184 } else {
185 this.cineIncrement = 0;
186 this.UpdateCine();
187 }
188 },
189 CineBackward: function() {
190 this.cineControls = true;
191 this.cineIncrement = -1;
192 this.UpdateCine();
193 },
194 UpdateCine: function() {
195 // Cancel the previous cine loop, if any
196 if (this.cineTimeoutId !== null) {
197 clearTimeout(this.cineTimeoutId);
198 this.cineTimeoutId = null;
199 }
200
201 this.cineLoadingFrame = false;
202
203 if (this.cineIncrement != 0) {
204 this.CineCallback();
205 }
206 },
207 CineCallback: function() {
208 var reschedule;
209
210 if (this.cineLoadingFrame) {
211 /**
212 * Wait until the frame scheduled by the previous call to
213 * "CineCallback()" is actually displayed (i.e. we monitor the
214 * "FrameUpdated" event). Otherwise, the background loading
215 * process of the DICOM frames in C++ might be behind the
216 * advancement of the current frame, which freezes the
217 * display.
218 **/
219 reschedule = true;
220 } else {
221 this.cineLoadingFrame = true;
222
223 if (this.cineIncrement == 1) {
224 reschedule = this.DecrementFrame(true /* circular */);
225 } else if (this.cineIncrement == -1) {
226 reschedule = this.IncrementFrame(true /* circular */);
227 } else {
228 reschedule = false; // Increment is zero, this test is just for safety
229 }
230 }
231
232 if (reschedule) {
233 this.cineTimeoutId = setTimeout(this.CineCallback, 1000.0 / this.cineFramesPerSecond);
234 }
145 } 235 }
146 } 236 }
147 }); 237 });
148 238
149 239