@leafer/image 1.0.0-beta.9 → 1.0.0-rc.2

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 CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@leafer/image",
3
- "version": "1.0.0-beta.9",
3
+ "version": "1.0.0-rc.2",
4
4
  "description": "@leafer/image",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
7
7
  "main": "src/index.ts",
8
+ "types": "types/index.d.ts",
8
9
  "files": [
9
- "src"
10
+ "src",
11
+ "types",
12
+ "dist"
10
13
  ],
11
14
  "repository": {
12
15
  "type": "git",
@@ -19,10 +22,10 @@
19
22
  "leaferjs"
20
23
  ],
21
24
  "dependencies": {
22
- "@leafer/task": "1.0.0-beta.9",
23
- "@leafer/platform": "1.0.0-beta.9"
25
+ "@leafer/task": "1.0.0-rc.2",
26
+ "@leafer/platform": "1.0.0-rc.2"
24
27
  },
25
28
  "devDependencies": {
26
- "@leafer/interface": "1.0.0-beta.9"
29
+ "@leafer/interface": "1.0.0-rc.2"
27
30
  }
28
31
  }
@@ -1,43 +1,51 @@
1
- import { ILeafer, ILeaferCanvasConfig, IImageManager, ILeaferImageConfig, ILeaferImage, ITaskProcessor, IFunction } from '@leafer/interface'
1
+ import { IImageManager, ILeaferImageConfig, ILeaferImage } from '@leafer/interface'
2
2
  import { Creator } from '@leafer/platform'
3
3
  import { TaskProcessor } from '@leafer/task'
4
4
 
5
+ export const ImageManager: IImageManager = {
5
6
 
6
- interface ILeaferImageMap {
7
- [name: string]: ILeaferImage
8
- }
9
-
7
+ map: {},
10
8
 
11
- export class ImageManager implements IImageManager {
9
+ recycledList: [],
12
10
 
13
- public leafer: ILeafer
11
+ tasker: new TaskProcessor(),
14
12
 
15
- public tasker: ITaskProcessor
13
+ patternTasker: new TaskProcessor(),
16
14
 
17
- public map: ILeaferImageMap = {}
18
-
19
- constructor(leafer: ILeafer, _config: ILeaferCanvasConfig) {
20
- this.leafer = leafer
21
- this.tasker = new TaskProcessor()
22
- }
15
+ get isComplete() { return I.tasker.isComplete && I.patternTasker.isComplete },
23
16
 
24
- public get(config: ILeaferImageConfig): ILeaferImage {
25
- let image = this.map[config.url]
17
+ get(config: ILeaferImageConfig): ILeaferImage {
18
+ let image = I.map[config.url]
26
19
  if (!image) {
27
20
  image = Creator.image(config)
28
- this.map[config.url] = image
21
+ I.map[config.url] = image
29
22
  }
23
+ image.use++
30
24
  return image
31
- }
25
+ },
26
+
27
+ recycle(image: ILeaferImage): void {
28
+ image.use--
29
+ setTimeout(() => { if (!image.use) I.recycledList.push(image) })
30
+ },
31
+
32
+ clearRecycled(): void {
33
+ const list = I.recycledList
34
+ if (list.length) {
35
+ list.forEach(image => {
36
+ if (!image.use && image.url) {
37
+ delete I.map[image.url]
38
+ image.destroy()
39
+ }
40
+ })
41
+ list.length = 0
42
+ }
43
+ },
32
44
 
33
- public load(image: ILeaferImage, onSuccess: IFunction, onError: IFunction): void {
34
- this.tasker.addParallel(async () => await image.load(onSuccess, onError))
35
- if (!this.tasker.running) this.tasker.start()
45
+ destroy(): void {
46
+ I.map = {}
36
47
  }
37
48
 
38
- public destroy(): void {
39
- this.leafer = null
40
- this.map = null
41
- }
49
+ }
42
50
 
43
- }
51
+ const I = ImageManager
@@ -0,0 +1,104 @@
1
+ import { ILeaferImage, ILeaferImageConfig, IFunction, IObject, InnerId } from '@leafer/interface'
2
+ import { Platform } from '@leafer/platform'
3
+ import { IncrementId } from '@leafer/math'
4
+
5
+ import { ImageManager } from './ImageManager'
6
+
7
+
8
+ const { IMAGE, create } = IncrementId
9
+
10
+ export class LeaferImage implements ILeaferImage {
11
+
12
+ public readonly innerId: InnerId
13
+ public get url() { return this.config.url }
14
+
15
+ public view: any
16
+
17
+ public width: number
18
+ public height: number
19
+
20
+ public isSVG: boolean
21
+
22
+ public get completed() { return this.ready || !!this.error }
23
+
24
+ public ready: boolean
25
+ public error: IObject
26
+ public loading: boolean
27
+
28
+ public use = 0
29
+
30
+ public config: ILeaferImageConfig
31
+
32
+ protected waitComplete: IFunction[] = []
33
+
34
+ constructor(config: ILeaferImageConfig) {
35
+ this.innerId = create(IMAGE)
36
+ this.config = config || { url: '' }
37
+ const { url } = config
38
+ if (url.startsWith('data:')) {
39
+ if (url.startsWith('data:image/svg')) this.isSVG = true
40
+ } else {
41
+ if (url.includes('.svg')) this.isSVG = true
42
+ }
43
+ if (this.config.format === 'svg') this.isSVG = true
44
+ }
45
+
46
+ public load(onSuccess: IFunction, onError: IFunction): number {
47
+ if (!this.loading) {
48
+ this.loading = true
49
+ ImageManager.tasker.add(async () => await Platform.origin.loadImage(this.url).then((img) => {
50
+ this.ready = true
51
+ this.width = img.naturalWidth || img.width
52
+ this.height = img.naturalHeight || img.height
53
+ this.view = img
54
+ this.onComplete(true)
55
+ }).catch((e) => {
56
+ this.error = e
57
+ this.onComplete(false)
58
+ }))
59
+ }
60
+ this.waitComplete.push(onSuccess, onError)
61
+ return this.waitComplete.length - 2
62
+ }
63
+
64
+ public unload(index: number, stopEvent?: boolean): void {
65
+ const l = this.waitComplete
66
+ if (stopEvent) {
67
+ const error = l[index + 1]
68
+ if (error) error({ type: 'stop' })
69
+ }
70
+ l[index] = l[index + 1] = undefined
71
+ }
72
+
73
+ protected onComplete(isSuccess: boolean): void {
74
+ let odd: number
75
+ this.waitComplete.forEach((item, index) => {
76
+ odd = index % 2
77
+ if (item) {
78
+ if (isSuccess) {
79
+ if (!odd) item(this)
80
+ } else {
81
+ if (odd) item(this.error)
82
+ }
83
+ }
84
+ })
85
+ this.waitComplete.length = 0
86
+ this.loading = false
87
+ }
88
+
89
+ public getCanvas(width: number, height: number, opacity?: number, _filters?: IObject): any {
90
+ width || (width = this.width)
91
+ height || (height = this.height)
92
+ const canvas = Platform.origin.createCanvas(width, height)
93
+ const ctx = canvas.getContext('2d')
94
+ if (opacity) ctx.globalAlpha = opacity
95
+ ctx.drawImage(this.view, 0, 0, width, height)
96
+ return canvas
97
+ }
98
+
99
+ public destroy(): void {
100
+ this.config = { url: '' }
101
+ this.waitComplete.length = 0
102
+ }
103
+
104
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { LeaferImageBase } from './LeaferImageBase'
1
+ export { LeaferImage } from './LeaferImage'
2
2
  export { ImageManager } from './ImageManager'
@@ -0,0 +1,27 @@
1
+ import { ILeaferImage, InnerId, IObject, ILeaferImageConfig, IFunction, IImageManager } from '@leafer/interface';
2
+
3
+ declare class LeaferImage implements ILeaferImage {
4
+ readonly innerId: InnerId;
5
+ get url(): string;
6
+ view: any;
7
+ width: number;
8
+ height: number;
9
+ isSVG: boolean;
10
+ get completed(): boolean;
11
+ ready: boolean;
12
+ error: IObject;
13
+ loading: boolean;
14
+ use: number;
15
+ config: ILeaferImageConfig;
16
+ protected waitComplete: IFunction[];
17
+ constructor(config: ILeaferImageConfig);
18
+ load(onSuccess: IFunction, onError: IFunction): number;
19
+ unload(index: number, stopEvent?: boolean): void;
20
+ protected onComplete(isSuccess: boolean): void;
21
+ getCanvas(width: number, height: number, opacity?: number, _filters?: IObject): any;
22
+ destroy(): void;
23
+ }
24
+
25
+ declare const ImageManager: IImageManager;
26
+
27
+ export { ImageManager, LeaferImage };
@@ -1,49 +0,0 @@
1
- import { ILeaferImage, ILeaferImageConfig, IFunction, IObject } from '@leafer/interface'
2
- import { Platform } from '@leafer/platform'
3
-
4
-
5
- export class LeaferImageBase implements ILeaferImage {
6
-
7
- public view: any
8
-
9
- public width: number
10
- public height: number
11
-
12
- public ready: boolean
13
- public error: IObject
14
-
15
- public options: ILeaferImageConfig
16
-
17
- constructor(_options: ILeaferImageConfig) {
18
- this.options = _options
19
- }
20
-
21
- public async load(onSuccess: IFunction, onError: IFunction): Promise<void> {
22
- return Platform.origin.loadImage(this.options.url).then((img) => {
23
- this.ready = true
24
- this.width = img.naturalWidth || img.width
25
- this.height = img.naturalHeight || img.height
26
- this.view = img
27
- if (onSuccess) onSuccess(this)
28
- }).catch((e) => {
29
- this.error = e
30
- if (onError) onError(e)
31
- })
32
- }
33
-
34
- public getCanvas(width: number, height: number, opacity?: number, _filters?: IObject): any {
35
- width || (width = this.width)
36
- height || (height = this.height)
37
- const canvas = Platform.origin.createCanvas(width, height)
38
- const ctx = canvas.getContext('2d')
39
- if (opacity) ctx.globalAlpha = opacity
40
- ctx.drawImage(this.view, 0, 0, width, height)
41
- return canvas
42
- }
43
-
44
- public destroy(): void {
45
- this.view = null
46
- this.options = null
47
- }
48
-
49
- }