/
CanvasSnapshotPlugin.ts
123 lines (112 loc) · 5.1 KB
/
CanvasSnapshotPlugin.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import {serialize, timeout} from 'ts-browser-helpers'
import {AViewerPluginSync} from '../../viewer'
import {uiButton, uiConfig, uiFolderContainer, uiInput} from 'uiconfig.js'
import {CanvasSnapshot, CanvasSnapshotOptions} from '../../utils/canvas-snapshot'
import {ProgressivePlugin} from '../pipeline/ProgressivePlugin'
@uiFolderContainer('Canvas Snapshot (Image Export)')
export class CanvasSnapshotPlugin extends AViewerPluginSync<''> {
static readonly PluginType = 'CanvasSnapshotPlugin'
enabled = true
constructor() {
super()
this.downloadSnapshot = this.downloadSnapshot.bind(this)
this.getDataUrl({})
}
/**
* Returns a File object with screenshot of the viewer canvas
* @param filename default is {@link CanvasSnapshotPlugin.filename}
* @param options waitForProgressive: wait for progressive rendering to finish, default: true
*/
async getFile(filename?: string, options: CanvasSnapshotOptions&{waitForProgressive?: boolean} = {waitForProgressive: true}): Promise<File|undefined> {
options.getDataUrl = false
return await this._getFile(filename || this.filename, options) as File
}
/**
* Returns a data url of the screenshot of the viewer canvas
* @param options waitForProgressive: wait for progressive rendering to finish, default: true
*/
async getDataUrl(options: CanvasSnapshotOptions&{waitForProgressive?: boolean} = {}): Promise<string> {
options.getDataUrl = true
return await this._getFile('', options) as string ?? ''
}
private async _getFile(filename: string, options: CanvasSnapshotOptions&{waitForProgressive?: boolean} = {}): Promise<File|string|undefined> {
const viewer = this._viewer
const canvas = this._viewer?.canvas
if (!viewer || !canvas) return undefined
const dpr = viewer.renderManager.renderScale
if (options.displayPixelRatio !== undefined && options.displayPixelRatio !== dpr) {
viewer.renderManager.renderScale = options.displayPixelRatio
}
if (options.timeout) await timeout(options.timeout)
const progressive = viewer.getPlugin(ProgressivePlugin)
if (options.waitForProgressive !== false && progressive) {
// todo: disable interactions and all so that frameCount is not affected
await new Promise<void>((res)=>{
const listener = () => {
if (!progressive.isConverged(true)) return
viewer.removeEventListener('postFrame', listener)
res()
}
viewer.addEventListener('postFrame', listener)
})
} else await viewer.doOnce('postFrame')
options.displayPixelRatio = 1
const rect = options.rect
if (rect && viewer.renderManager.renderScale !== 1) {
options.rect = {
...rect,
x: rect.x * viewer.renderManager.renderScale,
y: rect.y * viewer.renderManager.renderScale,
width: rect.width * viewer.renderManager.renderScale,
height: rect.height * viewer.renderManager.renderScale,
}
}
const file = await CanvasSnapshot.GetFile(canvas, filename, options)
options.rect = rect
options.displayPixelRatio = viewer.renderManager.renderScale
viewer.renderManager.renderScale = dpr
return file
}
@uiInput('Filename')
@serialize()
filename = 'snapshot.png'
/**
* Only for {@link downloadSnapshot} and functions using that
*/
@uiConfig()
@serialize()
defaultOptions: CanvasSnapshotOptions&{waitForProgressive?: boolean} = {
waitForProgressive: true,
displayPixelRatio: window.devicePixelRatio,
scale: 1,
timeout: 0,
quality: 0.9,
}
@uiButton('Download .png')
async downloadSnapshot(filename?: string, options: CanvasSnapshotOptions&{waitForProgressive?: boolean} = {waitForProgressive: true}): Promise<void> {
if (!this._viewer) return
if (!options.mimeType && !filename) this.filename = this.filename.split('.').slice(0, -1).join('.') + '.png'
const file = await this.getFile(filename, {...this.defaultOptions, ...options})
if (file) await this._viewer.exportBlob(file, file.name)
}
@uiButton('Download .jpeg')
protected async _downloadJpeg(): Promise<void> {
this.filename = this.filename.split('.').slice(0, -1).join('.') + '.jpeg'
return this.downloadSnapshot(undefined, {mimeType: 'image/jpeg'})
}
@uiButton('Download .webp')
protected async _downloadWebp(): Promise<void> {
this.filename = this.filename.split('.').slice(0, -1).join('.') + '.webp'
return this.downloadSnapshot(undefined, {mimeType: 'image/webp'})
}
}
/**
* @deprecated - use {@link CanvasSnapshotPlugin}
*/
export class CanvasSnipperPlugin extends CanvasSnapshotPlugin {
static readonly PluginType: any = 'CanvasSnipper'
constructor() {
super()
console.warn('CanvasSnipperPlugin is deprecated, use CanvasSnapshotPlugin')
}
}