@leafer/image 1.0.0-beta.8 → 1.0.0-rc.1

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.8",
3
+ "version": "1.0.0-rc.1",
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.8",
23
- "@leafer/platform": "1.0.0-beta.8"
25
+ "@leafer/task": "1.0.0-rc.1",
26
+ "@leafer/platform": "1.0.0-rc.1"
24
27
  },
25
28
  "devDependencies": {
26
- "@leafer/interface": "1.0.0-beta.8"
29
+ "@leafer/interface": "1.0.0-rc.1"
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 destory(): 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,47 +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
-
14
- public options: ILeaferImageConfig
15
-
16
- constructor(_options: ILeaferImageConfig) {
17
- this.options = _options
18
- }
19
-
20
- public async load(onSuccess: IFunction, onError: IFunction): Promise<void> {
21
- return Platform.origin.loadImage(this.options.url).then((img) => {
22
- this.ready = true
23
- this.width = img.naturalWidth || img.width
24
- this.height = img.naturalHeight || img.height
25
- this.view = img
26
- if (onSuccess) onSuccess(this)
27
- }).catch((e) => {
28
- if (onError) onError(e)
29
- })
30
- }
31
-
32
- public getCanvas(width: number, height: number, opacity?: number, _filters?: IObject): any {
33
- width || (width = this.width)
34
- height || (height = this.height)
35
- const canvas = Platform.origin.createCanvas(width, height)
36
- const ctx = canvas.getContext('2d')
37
- if (opacity) ctx.globalAlpha = opacity
38
- ctx.drawImage(this.view, 0, 0, width, height)
39
- return canvas
40
- }
41
-
42
- public destory(): void {
43
- this.view = null
44
- this.options = null
45
- }
46
-
47
- }