@leafer-in/export 1.7.0 → 1.9.0
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/dist/export.cjs +214 -165
- package/dist/export.esm.js +212 -163
- package/dist/export.esm.min.js +1 -1
- package/dist/export.esm.min.js.map +1 -1
- package/dist/export.js +199 -169
- package/dist/export.min.cjs +1 -1
- package/dist/export.min.cjs.map +1 -1
- package/dist/export.min.js +1 -1
- package/dist/export.min.js.map +1 -1
- package/package.json +4 -4
- package/src/export.ts +108 -99
- package/src/trim.ts +5 -2
- package/types/index.d.ts +1 -1
package/src/export.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IExportModule, IExportOptions, IExportResult, IExportResultFunction, IUI, IExportFileType, IFunction, IRenderOptions, IBoundsData, IBounds, ILocationType, ILeaf } from '@leafer-ui/interface'
|
|
2
|
-
import { Creator, Matrix, TaskProcessor, FileHelper, Bounds, Platform, MathHelper, Resource } from '@leafer-ui/draw'
|
|
2
|
+
import { Creator, Matrix, TaskProcessor, FileHelper, Bounds, Platform, MathHelper, Resource, Export, isUndefined } from '@leafer-ui/draw'
|
|
3
3
|
|
|
4
4
|
import { getTrimBounds } from './trim'
|
|
5
5
|
|
|
@@ -8,146 +8,155 @@ export const ExportModule: IExportModule = {
|
|
|
8
8
|
|
|
9
9
|
syncExport(leaf: IUI, filename: string, options?: IExportOptions | number | boolean): IExportResult {
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Export.running = true
|
|
12
12
|
|
|
13
13
|
let result: IExportResult
|
|
14
|
-
const fileType = FileHelper.fileType(filename)
|
|
15
|
-
const isDownload = filename.includes('.')
|
|
16
|
-
options = FileHelper.getExportOptions(options)
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
const { download } = Platform.origin
|
|
15
|
+
try {
|
|
20
16
|
|
|
17
|
+
const fileType = FileHelper.fileType(filename)
|
|
18
|
+
const isDownload = filename.includes('.')
|
|
19
|
+
options = FileHelper.getExportOptions(options)
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
const { toURL } = Platform
|
|
22
|
+
const { download } = Platform.origin
|
|
23
23
|
|
|
24
|
-
isDownload && download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename)
|
|
25
|
-
result = { data: isDownload ? true : leaf.toJSON(options.json) }
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
if (fileType === 'json') {
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
isDownload && download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename)
|
|
28
|
+
result = { data: isDownload ? true : leaf.toJSON(options.json) }
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
} else if (fileType === 'svg') {
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const { slice, clip, trim, screenshot, padding, onCanvas } = options
|
|
37
|
-
const smooth = options.smooth === undefined ? (leafer ? leafer.config.smooth : true) : options.smooth
|
|
38
|
-
const contextSettings = options.contextSettings || (leafer ? leafer.config.contextSettings : undefined)
|
|
32
|
+
isDownload && download(toURL(leaf.toSVG(), 'svg'), filename)
|
|
33
|
+
result = { data: isDownload ? true : leaf.toSVG() }
|
|
39
34
|
|
|
40
|
-
const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill // leafer use
|
|
41
|
-
const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix()
|
|
42
|
-
|
|
43
|
-
// 获取元素大小
|
|
44
|
-
if (screenshot) {
|
|
45
|
-
renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot
|
|
46
35
|
} else {
|
|
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
|
-
|
|
36
|
+
|
|
37
|
+
let renderBounds: IBoundsData, trimBounds: IBounds, scaleX = 1, scaleY = 1
|
|
38
|
+
const { worldTransform, isLeafer, leafer, isFrame } = leaf
|
|
39
|
+
const { slice, clip, trim, screenshot, padding, onCanvas } = options
|
|
40
|
+
const smooth = isUndefined(options.smooth) ? (leafer ? leafer.config.smooth : true) : options.smooth
|
|
41
|
+
const contextSettings = options.contextSettings || (leafer ? leafer.config.contextSettings : undefined)
|
|
42
|
+
|
|
43
|
+
const fill = (isLeafer && screenshot) ? (isUndefined(options.fill) ? leaf.fill : options.fill) : options.fill // leafer use
|
|
44
|
+
const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix()
|
|
45
|
+
|
|
46
|
+
// 获取元素大小
|
|
47
|
+
if (screenshot) {
|
|
48
|
+
renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot
|
|
49
|
+
} else {
|
|
50
|
+
let relative: ILocationType | ILeaf = options.relative || (isLeafer ? 'inner' : 'local')
|
|
51
|
+
|
|
52
|
+
scaleX = worldTransform.scaleX
|
|
53
|
+
scaleY = worldTransform.scaleY
|
|
54
|
+
|
|
55
|
+
switch (relative) {
|
|
56
|
+
case 'inner':
|
|
57
|
+
matrix.set(worldTransform)
|
|
58
|
+
break
|
|
59
|
+
case 'local':
|
|
60
|
+
matrix.set(worldTransform).divide(leaf.localTransform)
|
|
61
|
+
scaleX /= leaf.scaleX
|
|
62
|
+
scaleY /= leaf.scaleY
|
|
63
|
+
break
|
|
64
|
+
case 'world':
|
|
65
|
+
scaleX = 1
|
|
66
|
+
scaleY = 1
|
|
67
|
+
break
|
|
68
|
+
case 'page':
|
|
69
|
+
relative = leafer || leaf
|
|
70
|
+
default:
|
|
71
|
+
matrix.set(worldTransform).divide(leaf.getTransform(relative))
|
|
72
|
+
const l = relative.worldTransform
|
|
73
|
+
scaleX /= scaleX / l.scaleX
|
|
74
|
+
scaleY /= scaleY / l.scaleY
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
renderBounds = leaf.getBounds('render', relative)
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
renderBounds = leaf.getBounds('render', relative)
|
|
75
|
-
}
|
|
76
80
|
|
|
81
|
+
// 缩放元素
|
|
82
|
+
const scaleData = { scaleX: 1, scaleY: 1 }
|
|
83
|
+
MathHelper.getScaleData(options.scale, options.size, renderBounds, scaleData)
|
|
77
84
|
|
|
78
|
-
|
|
79
|
-
const scaleData = { scaleX: 1, scaleY: 1 }
|
|
80
|
-
MathHelper.getScaleData(options.scale, options.size, renderBounds, scaleData)
|
|
85
|
+
let pixelRatio = options.pixelRatio || 1
|
|
81
86
|
|
|
82
|
-
let pixelRatio = options.pixelRatio || 1
|
|
83
87
|
|
|
88
|
+
// 导出元素
|
|
89
|
+
let { x, y, width, height } = new Bounds(renderBounds).scale(scaleData.scaleX, scaleData.scaleY)
|
|
90
|
+
if (clip) x += clip.x, y += clip.y, width = clip.width, height = clip.height
|
|
84
91
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (clip) x += clip.x, y += clip.y, width = clip.width, height = clip.height
|
|
92
|
+
const renderOptions: IRenderOptions = { exporting: true, matrix: matrix.scale(1 / scaleData.scaleX, 1 / scaleData.scaleY).invert().translate(-x, -y).withScale(1 / scaleX * scaleData.scaleX, 1 / scaleY * scaleData.scaleY) }
|
|
93
|
+
let canvas = Creator.canvas({ width: Math.floor(width), height: Math.floor(height), pixelRatio, smooth, contextSettings })
|
|
88
94
|
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
let sliceLeaf: IUI
|
|
96
|
+
if (slice) {
|
|
97
|
+
sliceLeaf = leaf
|
|
98
|
+
sliceLeaf.__worldOpacity = 0 // hide slice
|
|
91
99
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
sliceLeaf.__worldOpacity = 0 // hide slice
|
|
100
|
+
leaf = leafer || leaf // render all in bounds
|
|
101
|
+
renderOptions.bounds = canvas.bounds
|
|
102
|
+
}
|
|
96
103
|
|
|
97
|
-
leaf = leafer || leaf // render all in bounds
|
|
98
|
-
renderOptions.bounds = canvas.bounds
|
|
99
|
-
}
|
|
100
104
|
|
|
105
|
+
canvas.save()
|
|
101
106
|
|
|
102
|
-
|
|
107
|
+
if (isFrame && !isUndefined(fill)) {
|
|
108
|
+
const oldFill = leaf.get('fill')
|
|
109
|
+
leaf.fill = ''
|
|
110
|
+
leaf.__render(canvas, renderOptions)
|
|
111
|
+
leaf.fill = oldFill as string
|
|
112
|
+
} else {
|
|
113
|
+
leaf.__render(canvas, renderOptions)
|
|
114
|
+
}
|
|
103
115
|
|
|
104
|
-
|
|
105
|
-
const oldFill = leaf.get('fill')
|
|
106
|
-
leaf.fill = ''
|
|
107
|
-
leaf.__render(canvas, renderOptions)
|
|
108
|
-
leaf.fill = oldFill as string
|
|
109
|
-
} else {
|
|
110
|
-
leaf.__render(canvas, renderOptions)
|
|
111
|
-
}
|
|
116
|
+
canvas.restore()
|
|
112
117
|
|
|
113
|
-
|
|
118
|
+
if (sliceLeaf) sliceLeaf.__updateWorldOpacity() // show slice
|
|
114
119
|
|
|
120
|
+
if (trim) {
|
|
121
|
+
trimBounds = getTrimBounds(canvas)
|
|
122
|
+
const old = canvas, { width, height } = trimBounds
|
|
123
|
+
const config = { x: 0, y: 0, width, height, pixelRatio }
|
|
115
124
|
|
|
116
|
-
|
|
125
|
+
canvas = Creator.canvas(config)
|
|
126
|
+
canvas.copyWorld(old, trimBounds, config)
|
|
127
|
+
old.destroy()
|
|
128
|
+
}
|
|
117
129
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const config = { x: 0, y: 0, width, height, pixelRatio }
|
|
130
|
+
if (padding) {
|
|
131
|
+
const [top, right, bottom, left] = MathHelper.fourNumber(padding)
|
|
132
|
+
const old = canvas, { width, height } = old
|
|
122
133
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
134
|
+
canvas = Creator.canvas({ width: width + left + right, height: height + top + bottom, pixelRatio })
|
|
135
|
+
canvas.copyWorld(old, old.bounds, { x: left, y: top, width, height })
|
|
136
|
+
old.destroy()
|
|
137
|
+
}
|
|
126
138
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const old = canvas, { width, height } = old
|
|
139
|
+
if (needFill) canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over')
|
|
140
|
+
if (onCanvas) onCanvas(canvas)
|
|
130
141
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
142
|
+
const data = filename === 'canvas' ? canvas : canvas.export(filename, options)
|
|
143
|
+
result = { data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds }
|
|
134
144
|
|
|
135
|
-
|
|
136
|
-
if (onCanvas) onCanvas(canvas)
|
|
145
|
+
}
|
|
137
146
|
|
|
138
|
-
|
|
139
|
-
result = { data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds }
|
|
147
|
+
} catch (error) {
|
|
140
148
|
|
|
149
|
+
result = { data: '', error }
|
|
141
150
|
}
|
|
142
151
|
|
|
143
|
-
|
|
152
|
+
Export.running = false
|
|
144
153
|
|
|
145
154
|
return result
|
|
146
155
|
},
|
|
147
156
|
|
|
148
157
|
export(leaf: IUI, filename: IExportFileType | string, options?: IExportOptions | number | boolean): Promise<IExportResult> {
|
|
149
158
|
|
|
150
|
-
|
|
159
|
+
Export.running = true
|
|
151
160
|
|
|
152
161
|
return addTask((success: IExportResultFunction) =>
|
|
153
162
|
|
|
@@ -155,7 +164,7 @@ export const ExportModule: IExportModule = {
|
|
|
155
164
|
|
|
156
165
|
const getResult = async () => {
|
|
157
166
|
if (!Resource.isComplete) return Platform.requestRender(getResult)
|
|
158
|
-
const result: IExportResult =
|
|
167
|
+
const result: IExportResult = Export.syncExport(leaf, filename, options)
|
|
159
168
|
if (result.data instanceof Promise) result.data = await result.data
|
|
160
169
|
success(result)
|
|
161
170
|
resolve()
|
package/src/trim.ts
CHANGED
|
@@ -19,6 +19,9 @@ export function getTrimBounds(canvas: ILeaferCanvas): IBounds {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
const bounds = new Bounds()
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
if (pointBounds) {
|
|
23
|
+
toBounds(pointBounds, bounds)
|
|
24
|
+
bounds.scale(1 / canvas.pixelRatio).ceil()
|
|
25
|
+
}
|
|
26
|
+
return bounds
|
|
24
27
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
export {
|
|
2
|
+
export { };
|