cc-gram 0.2.1 → 1.0.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/README.md +47 -26
- package/dist/core.d.ts +60 -0
- package/dist/{types/filters.d.ts → filters.d.ts} +2 -3
- package/dist/index.d.ts +10 -0
- package/dist/index.esm.js +1 -0
- package/dist/index.umd.js +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/utils.d.ts +20 -0
- package/package.json +37 -36
- package/src/core.ts +188 -0
- package/src/filters.ts +219 -0
- package/src/index.ts +12 -0
- package/src/types.ts +15 -0
- package/src/utils.ts +85 -0
- package/dist/index.js +0 -1
- package/dist/types/index.d.ts +0 -79
- package/dist/types/utils.d.ts +0 -12
package/README.md
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
# CCgram
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/cc-gram)
|
|
4
|
+
[](https://www.npmjs.com/package/cc-gram)
|
|
5
|
+
[](https://github.com/EastSun5566/cc-gram/actions?query=workflow%3ATest)
|
|
6
|
+
[](https://github.com/EastSun5566/cc-gram/blob/master/LICENSE)
|
|
4
7
|
|
|
5
8
|
> 🖼 A CSS & Canvas Instagram filters based on CSSgram
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
🔗 <https://eastsun5566.github.io/cc-gram/>
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
## 🤔 The Why
|
|
15
|
+
|
|
16
|
+
> [CSSgram](https://github.com/una/CSSgram) is a great CSS filters library, but sometimes you want to access/download the filter image. Then CCgram comes into the play. It uses pure CSS to preview filters and draw it with Canvas when you need it.
|
|
17
|
+
|
|
18
|
+
- On-Demand: Uses CSS to preview & draw with Canvas API on demand.
|
|
19
|
+
- Non-Blocking: Draw an image on Web Worker with `OffscreenCanvas` & `ImageBitmap`.
|
|
20
|
+
|
|
21
|
+
## ✨ Installation
|
|
8
22
|
|
|
9
23
|
```sh
|
|
10
24
|
npm i cc-gram
|
|
11
|
-
|
|
12
|
-
# or yarn add cc-gram
|
|
13
25
|
```
|
|
14
26
|
|
|
15
27
|
## 🚀 Usage
|
|
@@ -29,9 +41,18 @@ npm i cc-gram
|
|
|
29
41
|
> Initialize to apply CSS filter to All targets has `data-filter` attribute
|
|
30
42
|
|
|
31
43
|
```js
|
|
32
|
-
import
|
|
44
|
+
import { createFilter } from "cc-gram";
|
|
45
|
+
|
|
46
|
+
const filter = createFilter();
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
// or you can turn off init apply
|
|
51
|
+
const filter = createFilter({ init: false });
|
|
33
52
|
|
|
34
|
-
|
|
53
|
+
// you can also specify data attribute
|
|
54
|
+
// i.e., <img data-my-attr="1977">
|
|
55
|
+
const filter = createFilter({ dataAttribute: "my-attr" });
|
|
35
56
|
```
|
|
36
57
|
|
|
37
58
|
---
|
|
@@ -42,10 +63,10 @@ const cg = new CCGram();
|
|
|
42
63
|
|
|
43
64
|
```js
|
|
44
65
|
// apply to All targets has `data-filter` attribute
|
|
45
|
-
|
|
66
|
+
filter.applyFilter();
|
|
46
67
|
|
|
47
|
-
// or you can just use selector
|
|
48
|
-
|
|
68
|
+
// or you can just use selector for performance
|
|
69
|
+
filter.applyFilter("#my-image");
|
|
49
70
|
```
|
|
50
71
|
|
|
51
72
|
##### All available filter name list
|
|
@@ -53,7 +74,7 @@ cg.applyFilter("#my-image");
|
|
|
53
74
|
> `filterNames`
|
|
54
75
|
|
|
55
76
|
```js
|
|
56
|
-
const
|
|
77
|
+
const filterNames = filter.filterNames;
|
|
57
78
|
```
|
|
58
79
|
|
|
59
80
|
- Default filter Name list:
|
|
@@ -84,7 +105,7 @@ const { filterNames } = cg;
|
|
|
84
105
|
- `stinson`
|
|
85
106
|
- `amaro`
|
|
86
107
|
|
|
87
|
-
##### Add / Set filter to filter list
|
|
108
|
+
##### Add / Set filter to the filter list
|
|
88
109
|
|
|
89
110
|
> `setFilter(name, setting)`
|
|
90
111
|
|
|
@@ -92,7 +113,7 @@ const { filterNames } = cg;
|
|
|
92
113
|
- setting: `object` - The filter setting
|
|
93
114
|
|
|
94
115
|
```js
|
|
95
|
-
|
|
116
|
+
filter.setFilter("my-filter", {
|
|
96
117
|
saturate: 0.8,
|
|
97
118
|
contrast: 1.2,
|
|
98
119
|
});
|
|
@@ -109,14 +130,14 @@ cg.setFilter("my-filter", {
|
|
|
109
130
|
- `saturate`
|
|
110
131
|
- `sepia`
|
|
111
132
|
|
|
112
|
-
##### Remove filter from filter list
|
|
133
|
+
##### Remove the filter from the filter list
|
|
113
134
|
|
|
114
135
|
> `removeFilter(name)`
|
|
115
136
|
|
|
116
137
|
- name: `string` - The filter name
|
|
117
138
|
|
|
118
139
|
```js
|
|
119
|
-
|
|
140
|
+
filter.removeFilter("my-filter");
|
|
120
141
|
```
|
|
121
142
|
|
|
122
143
|
---
|
|
@@ -124,7 +145,7 @@ cg.removeFilter("my-filter");
|
|
|
124
145
|
### Access Filter image
|
|
125
146
|
|
|
126
147
|
```js
|
|
127
|
-
const
|
|
148
|
+
const image = document.querySelector('img[data-filter="1977"]');
|
|
128
149
|
```
|
|
129
150
|
|
|
130
151
|
#### Data URL
|
|
@@ -132,7 +153,7 @@ const target = document.querySelector('img[data-filter="1977"]');
|
|
|
132
153
|
> `getDataURL(image[, options = {}])`
|
|
133
154
|
|
|
134
155
|
```js
|
|
135
|
-
const dataUrl = await
|
|
156
|
+
const dataUrl = await filter.getDataURL(image);
|
|
136
157
|
```
|
|
137
158
|
|
|
138
159
|
#### Blob
|
|
@@ -140,7 +161,7 @@ const dataUrl = await ccGram.getDataURL(target);
|
|
|
140
161
|
> `getBlob(image[, options = {}])`
|
|
141
162
|
|
|
142
163
|
```js
|
|
143
|
-
const blob = await
|
|
164
|
+
const blob = await filter.getBlob(image, {
|
|
144
165
|
type: "image/jpeg",
|
|
145
166
|
quality: 0.8,
|
|
146
167
|
});
|
|
@@ -148,21 +169,21 @@ const blob = await cg.getBlob(target, {
|
|
|
148
169
|
|
|
149
170
|
- Options
|
|
150
171
|
|
|
151
|
-
- type: `string` - MIME types,
|
|
152
|
-
- quality: `number`- [0 - 1],
|
|
172
|
+
- type: `string` - MIME types, defaults to `image/png`,
|
|
173
|
+
- quality: `number`- [0 - 1], defaults to `0.92`
|
|
153
174
|
|
|
154
|
-
## 🔧
|
|
175
|
+
## 🔧 Development
|
|
155
176
|
|
|
156
177
|
```sh
|
|
157
|
-
# install
|
|
158
|
-
|
|
178
|
+
# install deps
|
|
179
|
+
pnpm i
|
|
159
180
|
|
|
160
181
|
# fix style
|
|
161
|
-
|
|
182
|
+
pnpm run lint
|
|
162
183
|
|
|
163
184
|
# run test
|
|
164
|
-
|
|
185
|
+
pnpm test
|
|
165
186
|
|
|
166
|
-
# build for
|
|
167
|
-
|
|
187
|
+
# build for prod
|
|
188
|
+
pnpm run build
|
|
168
189
|
```
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { FilterName, FilterSetting } from './filters';
|
|
2
|
+
import { Options, ParseOptions } from './types';
|
|
3
|
+
export declare const DEFAULT_DATA_ATTRIBUTE = "filter";
|
|
4
|
+
/** 🖼 A CSS & Canvas Instagram filters based on CSSgram */
|
|
5
|
+
export declare class CCgram {
|
|
6
|
+
static readonly DEFAULT_DATA_ATTRIBUTE = "filter";
|
|
7
|
+
static readonly DEFAULT_FILTERS: Map<string, FilterSetting>;
|
|
8
|
+
/** filter list */
|
|
9
|
+
protected readonly _filters: Map<string, FilterSetting>;
|
|
10
|
+
/** data attribute */
|
|
11
|
+
protected _dataAttribute: string;
|
|
12
|
+
/** Initialize CSS filter to all targets */
|
|
13
|
+
constructor({ dataAttribute, init, }?: Options);
|
|
14
|
+
/** The filter name list */
|
|
15
|
+
get filterNames(): FilterName[];
|
|
16
|
+
/**
|
|
17
|
+
* Add/Set filter
|
|
18
|
+
* @param name - the Filter name
|
|
19
|
+
* @param setting - the Filter setting
|
|
20
|
+
*/
|
|
21
|
+
setFilter(name: FilterName, setting: FilterSetting): void;
|
|
22
|
+
/**
|
|
23
|
+
* Remove filter
|
|
24
|
+
* @param name - the Filter name
|
|
25
|
+
*/
|
|
26
|
+
removeFilter(name: FilterName): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Get setting object of filter
|
|
29
|
+
* @param [name=''] - The filter name
|
|
30
|
+
*/
|
|
31
|
+
getFilterSetting(name?: FilterName): FilterSetting | void;
|
|
32
|
+
/**
|
|
33
|
+
* Get the CSS inline style string of filter
|
|
34
|
+
* @param [name=''] - The filter name
|
|
35
|
+
*/
|
|
36
|
+
getFilterStyle(name?: FilterName): string;
|
|
37
|
+
/**
|
|
38
|
+
* Apply CSS filter to all targets
|
|
39
|
+
* @param [selectors='img[data-${this._dataAttribute}]'] - selectors
|
|
40
|
+
*/
|
|
41
|
+
applyFilter(selectors?: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Get the data URL of image element
|
|
44
|
+
* @param image - image element
|
|
45
|
+
* @param [options] - options
|
|
46
|
+
*/
|
|
47
|
+
getDataURL(image: HTMLImageElement, options?: ParseOptions): Promise<string | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Get the blob of image element
|
|
50
|
+
* @param image - image element
|
|
51
|
+
* @param [options={}] - parse options
|
|
52
|
+
*/
|
|
53
|
+
getBlob(image: HTMLImageElement, options?: ParseOptions): Promise<Blob | null>;
|
|
54
|
+
}
|
|
55
|
+
/** old Name, alias for `CCgram` */
|
|
56
|
+
export declare const CCGram: typeof CCgram;
|
|
57
|
+
/** alias for `CCgram` */
|
|
58
|
+
export declare const Filter: typeof CCgram;
|
|
59
|
+
export declare type FilterInstance = InstanceType<typeof CCgram>;
|
|
60
|
+
export declare function createFilter(options: Options): FilterInstance;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Base on CSSgram by Una Kravets
|
|
3
|
-
* @see CSSgram
|
|
3
|
+
* @see CSSgram {@link https://github.com/una/CSSgram}
|
|
4
4
|
*/
|
|
5
5
|
/** The Name of Filter */
|
|
6
6
|
export declare type FilterName = string;
|
|
7
|
-
/** The Setting of Filter */
|
|
7
|
+
/** The Setting object of Filter */
|
|
8
8
|
export interface FilterSetting {
|
|
9
9
|
blur?: number;
|
|
10
10
|
brightness?: number;
|
|
@@ -18,4 +18,3 @@ export interface FilterSetting {
|
|
|
18
18
|
}
|
|
19
19
|
/** The default Filter List */
|
|
20
20
|
export declare const DEFAULT_FILTERS: Map<FilterName, FilterSetting>;
|
|
21
|
-
export default DEFAULT_FILTERS;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package cc-gram <https://github.com/EastSun5566/cc-gram>
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright (c) 2019 - present
|
|
6
|
+
* @author 汪東陽 EastSun5566 <https://github.com/EastSun5566>
|
|
7
|
+
*/
|
|
8
|
+
export { Filter as default } from './core';
|
|
9
|
+
export * from './filters';
|
|
10
|
+
export * from './core';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function t(t,e,r,n){return new(r||(r=Promise))((function(a,s){function i(t){try{c(n.next(t))}catch(t){s(t)}}function o(t){try{c(n.throw(t))}catch(t){s(t)}}function c(t){var e;t.done?a(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(i,o)}c((n=n.apply(t,e||[])).next())}))}const e=new Map([["aden",{"hue-rotate":-20,contrast:.9,brightness:1.2,saturate:.85}],["inkwell",{sepia:.3,contrast:1.1,brightness:1.1,grayscale:1}],["reyes",{sepia:.22,contrast:.85,brightness:1.1,saturate:.75}],["gingham",{"hue-rotate":-10,brightness:1.05}],["toaster",{contrast:1.5,brightness:.9}],["walden",{"hue-rotate":-10,brightness:1.1,sepia:.3,saturate:1.6}],["hudson",{brightness:1.2,contrast:.9,saturate:1.1}],["earlybird",{contrast:.9,sepia:.2}],["mayfair",{contrast:1.1,saturate:1.1}],["lofi",{contrast:1.5,saturate:1.1}],["1977",{contrast:1.1,brightness:1.1,saturate:1.3}],["brooklyn",{contrast:.9,brightness:1.1}],["xpro2",{sepia:.3}],["nashville",{contrast:1.2,brightness:1.05,saturate:1.2,sepia:.2}],["lark",{contrast:.9}],["moon",{brightness:1.1,contrast:1.1,grayscale:1}],["clarendon",{contrast:1.2,saturate:1.35}],["willow",{contrast:.95,brightness:.9,grayscale:.5}],["rise",{contrast:.9,brightness:1.05,sepia:.2,saturate:.9}],["slumber",{brightness:1.05,saturate:.66}],["brannan",{contrast:1.4,sepia:.5}],["valencia",{contrast:1.08,brightness:1.08,sepia:.08}],["maven",{contrast:.95,brightness:1.95,saturate:1.5,sepia:.25}],["stinson",{contrast:.75,brightness:1.15,saturate:.85}],["amaro",{"hue-rotate":-10,contrast:.9,brightness:1.1,saturate:1.5}]]),r="undefined"!=typeof OffscreenCanvas;function n(t,e="internal error."){if(!t)throw Error(`[CCgram] ${e}`)}function a(t){n(t&&"IMG"===t.tagName,"The first argument is required and must be an <img> element."),n(t.src,"The <img> element src attribute is empty.")}function s({data:t}){const{canvas:e,image:r,filterStyle:n,options:a}=t,s=e.getContext("2d",{alpha:!1});if(!s)throw new Error("The 2d context canvas is not supported.");return s.filter=n,s.drawImage(r,0,0),e.convertToBlob(a)}const i="filter";class o{constructor({dataAttribute:t="filter",init:r=!0}={}){if(this._filters=e,this._dataAttribute=t,!r)return;if("complete"===document.readyState)return void this.applyFilter();const n=()=>{this.applyFilter(),document.removeEventListener("DOMContentLoaded",n)};document.addEventListener("DOMContentLoaded",n)}get filterNames(){return[...this._filters.keys()]}setFilter(t,e){this._filters.set(t,e)}removeFilter(t){return this._filters.delete(t)}getFilterSetting(t=""){return this._filters.get(t)}getFilterStyle(t=""){return function(t){return t?Object.keys(t).map((e=>`${e}(${t[e]}${"hue-rotate"===e?"deg":"blur"===e?"px":""})`)).join(" "):"none"}(this._filters.get(t))}applyFilter(t=`img[data-${this._dataAttribute}]`){document.querySelectorAll(t).forEach((t=>{const{dataset:e}=t;t.style.setProperty("filter",this.getFilterStyle(e[this._dataAttribute]))}))}getDataURL(e,r={}){return t(this,void 0,void 0,(function*(){a(e);const t=yield this.getBlob(e,r);if(!t)return null;const n=new FileReader;return new Promise((e=>{n.addEventListener("load",(()=>{e(n.result)})),n.readAsDataURL(t)}))}))}getBlob(e,n={}){return t(this,void 0,void 0,(function*(){a(e);const{naturalWidth:t,naturalHeight:i}=e,o=this.getFilterStyle(e.dataset[this._dataAttribute]);if(r){const r=new OffscreenCanvas(t,i),a=yield createImageBitmap(e);return new Promise((t=>{const e=function(t){const e=`\n const work = ${t.toString()};\n\n addEventListener('message', async (...params) => {\n const res = await work(...params);\n postMessage(res);\n });\n `,r=URL.createObjectURL(new Blob([e],{type:"text/javascript"})),n=new Worker(r),{terminate:a}=n;return n.terminate=()=>{URL.revokeObjectURL(r),a.call(n)},n}(s);e.addEventListener("message",(({data:r})=>{t(r),e.terminate()})),e.postMessage({canvas:r,image:a,filterStyle:o,options:n},[r,a])}))}const c=document.createElement("canvas");c.width=t,c.height=i;const l=c.getContext("2d",{alpha:!1});if(!l)throw new Error("The 2d context canvas is not supported.");l.filter=o,l.drawImage(e,0,0);const{type:u,quality:h}=n;return new Promise((t=>c.toBlob((e=>t(e)),u,h)))}))}}o.DEFAULT_DATA_ATTRIBUTE="filter",o.DEFAULT_FILTERS=e;const c=o,l=o;function u(t){return new l(t)}export{c as CCGram,o as CCgram,i as DEFAULT_DATA_ATTRIBUTE,e as DEFAULT_FILTERS,l as Filter,u as createFilter,l as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).CCGram={})}(this,(function(t){"use strict";function e(t,e,r,n){return new(r||(r=Promise))((function(a,s){function i(t){try{c(n.next(t))}catch(t){s(t)}}function o(t){try{c(n.throw(t))}catch(t){s(t)}}function c(t){var e;t.done?a(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(i,o)}c((n=n.apply(t,e||[])).next())}))}const r=new Map([["aden",{"hue-rotate":-20,contrast:.9,brightness:1.2,saturate:.85}],["inkwell",{sepia:.3,contrast:1.1,brightness:1.1,grayscale:1}],["reyes",{sepia:.22,contrast:.85,brightness:1.1,saturate:.75}],["gingham",{"hue-rotate":-10,brightness:1.05}],["toaster",{contrast:1.5,brightness:.9}],["walden",{"hue-rotate":-10,brightness:1.1,sepia:.3,saturate:1.6}],["hudson",{brightness:1.2,contrast:.9,saturate:1.1}],["earlybird",{contrast:.9,sepia:.2}],["mayfair",{contrast:1.1,saturate:1.1}],["lofi",{contrast:1.5,saturate:1.1}],["1977",{contrast:1.1,brightness:1.1,saturate:1.3}],["brooklyn",{contrast:.9,brightness:1.1}],["xpro2",{sepia:.3}],["nashville",{contrast:1.2,brightness:1.05,saturate:1.2,sepia:.2}],["lark",{contrast:.9}],["moon",{brightness:1.1,contrast:1.1,grayscale:1}],["clarendon",{contrast:1.2,saturate:1.35}],["willow",{contrast:.95,brightness:.9,grayscale:.5}],["rise",{contrast:.9,brightness:1.05,sepia:.2,saturate:.9}],["slumber",{brightness:1.05,saturate:.66}],["brannan",{contrast:1.4,sepia:.5}],["valencia",{contrast:1.08,brightness:1.08,sepia:.08}],["maven",{contrast:.95,brightness:1.95,saturate:1.5,sepia:.25}],["stinson",{contrast:.75,brightness:1.15,saturate:.85}],["amaro",{"hue-rotate":-10,contrast:.9,brightness:1.1,saturate:1.5}]]),n="undefined"!=typeof OffscreenCanvas;function a(t,e="internal error."){if(!t)throw Error(`[CCgram] ${e}`)}function s(t){a(t&&"IMG"===t.tagName,"The first argument is required and must be an <img> element."),a(t.src,"The <img> element src attribute is empty.")}function i({data:t}){const{canvas:e,image:r,filterStyle:n,options:a}=t,s=e.getContext("2d",{alpha:!1});if(!s)throw new Error("The 2d context canvas is not supported.");return s.filter=n,s.drawImage(r,0,0),e.convertToBlob(a)}const o="filter";class c{constructor({dataAttribute:t="filter",init:e=!0}={}){if(this._filters=r,this._dataAttribute=t,!e)return;if("complete"===document.readyState)return void this.applyFilter();const n=()=>{this.applyFilter(),document.removeEventListener("DOMContentLoaded",n)};document.addEventListener("DOMContentLoaded",n)}get filterNames(){return[...this._filters.keys()]}setFilter(t,e){this._filters.set(t,e)}removeFilter(t){return this._filters.delete(t)}getFilterSetting(t=""){return this._filters.get(t)}getFilterStyle(t=""){return function(t){return t?Object.keys(t).map((e=>`${e}(${t[e]}${"hue-rotate"===e?"deg":"blur"===e?"px":""})`)).join(" "):"none"}(this._filters.get(t))}applyFilter(t=`img[data-${this._dataAttribute}]`){document.querySelectorAll(t).forEach((t=>{const{dataset:e}=t;t.style.setProperty("filter",this.getFilterStyle(e[this._dataAttribute]))}))}getDataURL(t,r={}){return e(this,void 0,void 0,(function*(){s(t);const e=yield this.getBlob(t,r);if(!e)return null;const n=new FileReader;return new Promise((t=>{n.addEventListener("load",(()=>{t(n.result)})),n.readAsDataURL(e)}))}))}getBlob(t,r={}){return e(this,void 0,void 0,(function*(){s(t);const{naturalWidth:e,naturalHeight:a}=t,o=this.getFilterStyle(t.dataset[this._dataAttribute]);if(n){const n=new OffscreenCanvas(e,a),s=yield createImageBitmap(t);return new Promise((t=>{const e=function(t){const e=`\n const work = ${t.toString()};\n\n addEventListener('message', async (...params) => {\n const res = await work(...params);\n postMessage(res);\n });\n `,r=URL.createObjectURL(new Blob([e],{type:"text/javascript"})),n=new Worker(r),{terminate:a}=n;return n.terminate=()=>{URL.revokeObjectURL(r),a.call(n)},n}(i);e.addEventListener("message",(({data:r})=>{t(r),e.terminate()})),e.postMessage({canvas:n,image:s,filterStyle:o,options:r},[n,s])}))}const c=document.createElement("canvas");c.width=e,c.height=a;const l=c.getContext("2d",{alpha:!1});if(!l)throw new Error("The 2d context canvas is not supported.");l.filter=o,l.drawImage(t,0,0);const{type:u,quality:d}=r;return new Promise((t=>c.toBlob((e=>t(e)),u,d)))}))}}c.DEFAULT_DATA_ATTRIBUTE=o,c.DEFAULT_FILTERS=r;const l=c,u=c;t.CCGram=l,t.CCgram=c,t.DEFAULT_DATA_ATTRIBUTE=o,t.DEFAULT_FILTERS=r,t.Filter=u,t.createFilter=function(t){return new u(t)},t.default=u,Object.defineProperty(t,"__esModule",{value:!0})}));
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** constructor Options */
|
|
2
|
+
export interface Options {
|
|
3
|
+
/** The default data attribute */
|
|
4
|
+
dataAttribute?: string;
|
|
5
|
+
/** is Init CSS filter to all targets */
|
|
6
|
+
init?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/** The parse options for canvas */
|
|
9
|
+
export interface ParseOptions {
|
|
10
|
+
/** MIME types, defaults to `image/png` */
|
|
11
|
+
type?: string;
|
|
12
|
+
/** [0 - 1], defaults to `0.92` */
|
|
13
|
+
quality?: number;
|
|
14
|
+
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference types="offscreencanvas" />
|
|
2
|
+
import { FilterSetting } from './filters';
|
|
3
|
+
import { ParseOptions } from './types';
|
|
4
|
+
export declare const hasOffscreenCanvas: boolean;
|
|
5
|
+
export declare function assert<TCond = unknown>(condition: TCond, message?: string): asserts condition;
|
|
6
|
+
export declare function assertIsImage(image: HTMLImageElement): asserts image is HTMLImageElement;
|
|
7
|
+
export declare function createWorker<TData = unknown, TMessage = unknown>(fn: (messageEvent: MessageEvent<TData>) => TMessage): Worker;
|
|
8
|
+
/**
|
|
9
|
+
* Parse setting to style string
|
|
10
|
+
* @param setting - The filter setting
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseSettingToStyle(setting?: FilterSetting): string;
|
|
13
|
+
interface CreateBlobOptions<TCanvas extends HTMLCanvasElement | OffscreenCanvas = HTMLCanvasElement> {
|
|
14
|
+
canvas: TCanvas;
|
|
15
|
+
image: CanvasImageSource;
|
|
16
|
+
filterStyle: string;
|
|
17
|
+
options: ParseOptions;
|
|
18
|
+
}
|
|
19
|
+
export declare function createBlobWorker({ data, }: MessageEvent<CreateBlobOptions<OffscreenCanvas>>): Promise<Blob | null>;
|
|
20
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-gram",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "🖼 A CSS & Canvas Instagram filters based on CSSgram",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.umd.js",
|
|
7
|
+
"module": "dist/index.esm.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
"import": "./dist/index.esm.js",
|
|
11
|
+
"require": "./dist/index.umd.js"
|
|
12
|
+
},
|
|
7
13
|
"files": [
|
|
8
|
-
"dist"
|
|
14
|
+
"dist",
|
|
15
|
+
"src"
|
|
9
16
|
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"type-check": "tsc --noEmit",
|
|
12
|
-
"build:types": "tsc --emitDeclarationOnly",
|
|
13
|
-
"build:js": "webpack -p",
|
|
14
|
-
"build:js:dev": "webpack -d",
|
|
15
|
-
"build": "yarn build:types && yarn build:js",
|
|
16
|
-
"test": "jest __tests__/",
|
|
17
|
-
"lint": "eslint --fix --ignore-path .gitignore --ext .js,.ts src/",
|
|
18
|
-
"release:patch": "sh bin/release.sh patch",
|
|
19
|
-
"release:minor": "sh bin/release.sh minor",
|
|
20
|
-
"release:major": "sh bin/release.sh major",
|
|
21
|
-
"deploy": "sh bin/deploy.sh"
|
|
22
|
-
},
|
|
23
17
|
"keywords": [
|
|
24
18
|
"image",
|
|
25
19
|
"filter",
|
|
@@ -37,36 +31,43 @@
|
|
|
37
31
|
"url": "https://github.com/EastSun5566/cc-gram"
|
|
38
32
|
},
|
|
39
33
|
"homepage": "https://eastsun5566.github.io/cc-gram/",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/EastSun5566/cc-gram/issues"
|
|
36
|
+
},
|
|
40
37
|
"husky": {
|
|
41
38
|
"hooks": {
|
|
42
|
-
"pre-commit": "
|
|
39
|
+
"pre-commit": "pnpm lint"
|
|
43
40
|
}
|
|
44
41
|
},
|
|
45
42
|
"devDependencies": {
|
|
46
|
-
"@
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
-
"@
|
|
50
|
-
"@babel/preset-env": "^7.4.3",
|
|
51
|
-
"@babel/preset-typescript": "^7.3.3",
|
|
52
|
-
"@types/jest": "^24.0.24",
|
|
43
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
44
|
+
"@rollup/plugin-terser": "^0.1.0",
|
|
45
|
+
"@rollup/plugin-typescript": "^9.0.2",
|
|
46
|
+
"@types/offscreencanvas": "^2019.7.0",
|
|
53
47
|
"@typescript-eslint/eslint-plugin": "^2.14.0",
|
|
54
48
|
"@typescript-eslint/parser": "^2.14.0",
|
|
49
|
+
"@vitest/coverage-c8": "^0.25.6",
|
|
55
50
|
"babel-eslint": "^10.0.1",
|
|
56
|
-
"babel-loader": "^8.0.5",
|
|
57
|
-
"canvas": "^2.4.1",
|
|
58
51
|
"eslint": "^6.8.0",
|
|
59
52
|
"eslint-config-airbnb-base": "^14.0.0",
|
|
60
53
|
"eslint-plugin-import": "^2.19.1",
|
|
61
|
-
"fork-ts-checker-webpack-plugin": "^3.1.1",
|
|
62
54
|
"husky": "^3.1.0",
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
55
|
+
"jsdom": "^20.0.3",
|
|
56
|
+
"rimraf": "^3.0.2",
|
|
57
|
+
"rollup": "^3.2.5",
|
|
58
|
+
"rollup-plugin-filesize": "^9.1.2",
|
|
59
|
+
"tslib": "^2.4.1",
|
|
60
|
+
"typescript": "^4.8.4",
|
|
61
|
+
"vitest": "^0.25.6"
|
|
68
62
|
},
|
|
69
|
-
"
|
|
70
|
-
"
|
|
63
|
+
"scripts": {
|
|
64
|
+
"preinstall": "npx only-allow pnpm",
|
|
65
|
+
"build": "rimraf dist && rollup -c rollup.config.ts --configPlugin typescript",
|
|
66
|
+
"type-check": "tsc --noEmit",
|
|
67
|
+
"test": "vitest __tests__",
|
|
68
|
+
"test:coverage": "vitest run __tests__ --coverage",
|
|
69
|
+
"lint": "eslint --fix --ignore-path .gitignore --ext .js,.ts src",
|
|
70
|
+
"release": "sh scripts/release.sh",
|
|
71
|
+
"demo:dev": "pnpm -C demo dev"
|
|
71
72
|
}
|
|
72
|
-
}
|
|
73
|
+
}
|
package/src/core.ts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_FILTERS,
|
|
3
|
+
FilterName,
|
|
4
|
+
FilterSetting,
|
|
5
|
+
} from './filters';
|
|
6
|
+
import {
|
|
7
|
+
parseSettingToStyle,
|
|
8
|
+
hasOffscreenCanvas,
|
|
9
|
+
assertIsImage,
|
|
10
|
+
createWorker,
|
|
11
|
+
createBlobWorker,
|
|
12
|
+
} from './utils';
|
|
13
|
+
|
|
14
|
+
import { Options, ParseOptions } from './types';
|
|
15
|
+
|
|
16
|
+
export const DEFAULT_DATA_ATTRIBUTE = 'filter';
|
|
17
|
+
|
|
18
|
+
/** 🖼 A CSS & Canvas Instagram filters based on CSSgram */
|
|
19
|
+
export class CCgram {
|
|
20
|
+
static readonly DEFAULT_DATA_ATTRIBUTE = DEFAULT_DATA_ATTRIBUTE;
|
|
21
|
+
|
|
22
|
+
static readonly DEFAULT_FILTERS = DEFAULT_FILTERS;
|
|
23
|
+
|
|
24
|
+
/** filter list */
|
|
25
|
+
protected readonly _filters = DEFAULT_FILTERS;
|
|
26
|
+
|
|
27
|
+
/** data attribute */
|
|
28
|
+
protected _dataAttribute: string;
|
|
29
|
+
|
|
30
|
+
/** Initialize CSS filter to all targets */
|
|
31
|
+
constructor({
|
|
32
|
+
dataAttribute = DEFAULT_DATA_ATTRIBUTE,
|
|
33
|
+
init = true,
|
|
34
|
+
}: Options = {}) {
|
|
35
|
+
this._dataAttribute = dataAttribute;
|
|
36
|
+
|
|
37
|
+
if (!init) return;
|
|
38
|
+
|
|
39
|
+
if (document.readyState === 'complete') {
|
|
40
|
+
this.applyFilter();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const handleLoaded = (): void => {
|
|
45
|
+
this.applyFilter();
|
|
46
|
+
document.removeEventListener('DOMContentLoaded', handleLoaded);
|
|
47
|
+
};
|
|
48
|
+
document.addEventListener('DOMContentLoaded', handleLoaded);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** The filter name list */
|
|
52
|
+
get filterNames(): FilterName[] {
|
|
53
|
+
return [...this._filters.keys()];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Add/Set filter
|
|
58
|
+
* @param name - the Filter name
|
|
59
|
+
* @param setting - the Filter setting
|
|
60
|
+
*/
|
|
61
|
+
setFilter(name: FilterName, setting: FilterSetting): void {
|
|
62
|
+
this._filters.set(name, setting);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Remove filter
|
|
67
|
+
* @param name - the Filter name
|
|
68
|
+
*/
|
|
69
|
+
removeFilter(name: FilterName): boolean {
|
|
70
|
+
return this._filters.delete(name);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get setting object of filter
|
|
75
|
+
* @param [name=''] - The filter name
|
|
76
|
+
*/
|
|
77
|
+
getFilterSetting(name: FilterName = ''): FilterSetting | void {
|
|
78
|
+
return this._filters.get(name);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get the CSS inline style string of filter
|
|
83
|
+
* @param [name=''] - The filter name
|
|
84
|
+
*/
|
|
85
|
+
getFilterStyle(name: FilterName = ''): string {
|
|
86
|
+
const setting = this._filters.get(name);
|
|
87
|
+
|
|
88
|
+
return parseSettingToStyle(setting);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Apply CSS filter to all targets
|
|
93
|
+
* @param [selectors='img[data-${this._dataAttribute}]'] - selectors
|
|
94
|
+
*/
|
|
95
|
+
applyFilter(selectors = `img[data-${this._dataAttribute}]`): void {
|
|
96
|
+
document
|
|
97
|
+
.querySelectorAll<HTMLImageElement>(selectors)
|
|
98
|
+
.forEach((target): void => {
|
|
99
|
+
const { dataset } = target;
|
|
100
|
+
target.style.setProperty('filter', this.getFilterStyle(dataset[this._dataAttribute]));
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the data URL of image element
|
|
106
|
+
* @param image - image element
|
|
107
|
+
* @param [options] - options
|
|
108
|
+
*/
|
|
109
|
+
async getDataURL(
|
|
110
|
+
image: HTMLImageElement,
|
|
111
|
+
options: ParseOptions = {},
|
|
112
|
+
): Promise<string | null> {
|
|
113
|
+
assertIsImage(image);
|
|
114
|
+
|
|
115
|
+
// don't use canvas.toDataURL, use blob to DataURL
|
|
116
|
+
const blob = await this.getBlob(image, options);
|
|
117
|
+
if (!blob) return null;
|
|
118
|
+
|
|
119
|
+
const reader = new FileReader();
|
|
120
|
+
|
|
121
|
+
return new Promise((resolve) => {
|
|
122
|
+
reader.addEventListener('load', () => {
|
|
123
|
+
resolve(reader.result as string);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
reader.readAsDataURL(blob);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get the blob of image element
|
|
132
|
+
* @param image - image element
|
|
133
|
+
* @param [options={}] - parse options
|
|
134
|
+
*/
|
|
135
|
+
async getBlob(
|
|
136
|
+
image: HTMLImageElement,
|
|
137
|
+
options: ParseOptions = {},
|
|
138
|
+
): Promise<Blob | null> {
|
|
139
|
+
assertIsImage(image);
|
|
140
|
+
|
|
141
|
+
const { naturalWidth, naturalHeight } = image;
|
|
142
|
+
const filterStyle = this.getFilterStyle(image.dataset[this._dataAttribute]);
|
|
143
|
+
|
|
144
|
+
if (hasOffscreenCanvas) {
|
|
145
|
+
const canvas = new OffscreenCanvas(naturalWidth, naturalHeight);
|
|
146
|
+
const bmp = await createImageBitmap(image);
|
|
147
|
+
|
|
148
|
+
return new Promise((resolve) => {
|
|
149
|
+
const worker = createWorker(createBlobWorker);
|
|
150
|
+
|
|
151
|
+
worker.addEventListener('message', ({ data }: MessageEvent<Blob>) => {
|
|
152
|
+
resolve(data);
|
|
153
|
+
worker.terminate();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
worker.postMessage({
|
|
157
|
+
canvas,
|
|
158
|
+
image: bmp,
|
|
159
|
+
filterStyle,
|
|
160
|
+
options,
|
|
161
|
+
}, [canvas, bmp]);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const canvas = document.createElement('canvas');
|
|
166
|
+
canvas.width = naturalWidth;
|
|
167
|
+
canvas.height = naturalHeight;
|
|
168
|
+
|
|
169
|
+
const ctx = canvas.getContext('2d', { alpha: false });
|
|
170
|
+
if (!ctx) throw new Error('The 2d context canvas is not supported.');
|
|
171
|
+
|
|
172
|
+
ctx.filter = filterStyle;
|
|
173
|
+
ctx.drawImage(image, 0, 0);
|
|
174
|
+
|
|
175
|
+
const { type, quality } = options;
|
|
176
|
+
return new Promise((resolve) => canvas.toBlob((blob): void => resolve(blob), type, quality));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** old Name, alias for `CCgram` */
|
|
181
|
+
export const CCGram = CCgram;
|
|
182
|
+
/** alias for `CCgram` */
|
|
183
|
+
export const Filter = CCgram;
|
|
184
|
+
|
|
185
|
+
export type FilterInstance = InstanceType<typeof CCgram>;
|
|
186
|
+
export function createFilter(options: Options): FilterInstance {
|
|
187
|
+
return new Filter(options);
|
|
188
|
+
}
|
package/src/filters.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base on CSSgram by Una Kravets
|
|
3
|
+
* @see CSSgram {@link https://github.com/una/CSSgram}
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** The Name of Filter */
|
|
7
|
+
export type FilterName = string;
|
|
8
|
+
|
|
9
|
+
/** The Setting object of Filter */
|
|
10
|
+
export interface FilterSetting {
|
|
11
|
+
blur?: number;
|
|
12
|
+
brightness?: number;
|
|
13
|
+
contrast?: number;
|
|
14
|
+
grayscale?: number;
|
|
15
|
+
'hue-rotate'?: number;
|
|
16
|
+
invert?: number;
|
|
17
|
+
saturate?: number;
|
|
18
|
+
sepia?: number;
|
|
19
|
+
[key: string]: number | undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The default Filter List */
|
|
23
|
+
export const DEFAULT_FILTERS: Map<FilterName, FilterSetting> = new Map([
|
|
24
|
+
[
|
|
25
|
+
'aden',
|
|
26
|
+
{
|
|
27
|
+
'hue-rotate': -20,
|
|
28
|
+
contrast: 0.9,
|
|
29
|
+
brightness: 1.2,
|
|
30
|
+
saturate: 0.85,
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
'inkwell',
|
|
35
|
+
{
|
|
36
|
+
sepia: 0.3,
|
|
37
|
+
contrast: 1.1,
|
|
38
|
+
brightness: 1.1,
|
|
39
|
+
grayscale: 1,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
'reyes',
|
|
44
|
+
{
|
|
45
|
+
sepia: 0.22,
|
|
46
|
+
contrast: 0.85,
|
|
47
|
+
brightness: 1.1,
|
|
48
|
+
saturate: 0.75,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
[
|
|
52
|
+
'gingham',
|
|
53
|
+
{
|
|
54
|
+
'hue-rotate': -10,
|
|
55
|
+
brightness: 1.05,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
'toaster',
|
|
60
|
+
{
|
|
61
|
+
contrast: 1.5,
|
|
62
|
+
brightness: 0.9,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
[
|
|
66
|
+
'walden',
|
|
67
|
+
{
|
|
68
|
+
'hue-rotate': -10,
|
|
69
|
+
brightness: 1.1,
|
|
70
|
+
sepia: 0.3,
|
|
71
|
+
saturate: 1.6,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
[
|
|
75
|
+
'hudson',
|
|
76
|
+
{
|
|
77
|
+
brightness: 1.2,
|
|
78
|
+
contrast: 0.9,
|
|
79
|
+
saturate: 1.1,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
'earlybird',
|
|
84
|
+
{
|
|
85
|
+
contrast: 0.9,
|
|
86
|
+
sepia: 0.2,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
'mayfair',
|
|
91
|
+
{
|
|
92
|
+
contrast: 1.1,
|
|
93
|
+
saturate: 1.1,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
[
|
|
97
|
+
'lofi',
|
|
98
|
+
{
|
|
99
|
+
contrast: 1.5,
|
|
100
|
+
saturate: 1.1,
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
[
|
|
104
|
+
'1977',
|
|
105
|
+
{
|
|
106
|
+
contrast: 1.1,
|
|
107
|
+
brightness: 1.1,
|
|
108
|
+
saturate: 1.3,
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
[
|
|
112
|
+
'brooklyn',
|
|
113
|
+
{
|
|
114
|
+
contrast: 0.9,
|
|
115
|
+
brightness: 1.1,
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
[
|
|
119
|
+
'xpro2',
|
|
120
|
+
{
|
|
121
|
+
sepia: 0.3,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
[
|
|
125
|
+
'nashville',
|
|
126
|
+
{
|
|
127
|
+
contrast: 1.2,
|
|
128
|
+
brightness: 1.05,
|
|
129
|
+
saturate: 1.2,
|
|
130
|
+
sepia: 0.2,
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
[
|
|
134
|
+
'lark',
|
|
135
|
+
{
|
|
136
|
+
contrast: 0.9,
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
[
|
|
140
|
+
'moon',
|
|
141
|
+
{
|
|
142
|
+
brightness: 1.1,
|
|
143
|
+
contrast: 1.1,
|
|
144
|
+
grayscale: 1,
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
[
|
|
148
|
+
'clarendon',
|
|
149
|
+
{
|
|
150
|
+
contrast: 1.2,
|
|
151
|
+
saturate: 1.35,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
[
|
|
155
|
+
'willow',
|
|
156
|
+
{
|
|
157
|
+
contrast: 0.95,
|
|
158
|
+
brightness: 0.9,
|
|
159
|
+
grayscale: 0.5,
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
[
|
|
163
|
+
'rise',
|
|
164
|
+
{
|
|
165
|
+
contrast: 0.9,
|
|
166
|
+
brightness: 1.05,
|
|
167
|
+
sepia: 0.2,
|
|
168
|
+
saturate: 0.9,
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
[
|
|
172
|
+
'slumber',
|
|
173
|
+
{
|
|
174
|
+
brightness: 1.05,
|
|
175
|
+
saturate: 0.66,
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
[
|
|
179
|
+
'brannan',
|
|
180
|
+
{
|
|
181
|
+
contrast: 1.4,
|
|
182
|
+
sepia: 0.5,
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
[
|
|
186
|
+
'valencia',
|
|
187
|
+
{
|
|
188
|
+
contrast: 1.08,
|
|
189
|
+
brightness: 1.08,
|
|
190
|
+
sepia: 0.08,
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
[
|
|
194
|
+
'maven',
|
|
195
|
+
{
|
|
196
|
+
contrast: 0.95,
|
|
197
|
+
brightness: 1.95,
|
|
198
|
+
saturate: 1.5,
|
|
199
|
+
sepia: 0.25,
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
[
|
|
203
|
+
'stinson',
|
|
204
|
+
{
|
|
205
|
+
contrast: 0.75,
|
|
206
|
+
brightness: 1.15,
|
|
207
|
+
saturate: 0.85,
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
[
|
|
211
|
+
'amaro',
|
|
212
|
+
{
|
|
213
|
+
'hue-rotate': -10,
|
|
214
|
+
contrast: 0.9,
|
|
215
|
+
brightness: 1.1,
|
|
216
|
+
saturate: 1.5,
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
]);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package cc-gram <https://github.com/EastSun5566/cc-gram>
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright (c) 2019 - present
|
|
6
|
+
* @author 汪東陽 EastSun5566 <https://github.com/EastSun5566>
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { Filter as default } from './core';
|
|
10
|
+
|
|
11
|
+
export * from './filters';
|
|
12
|
+
export * from './core';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** constructor Options */
|
|
2
|
+
export interface Options {
|
|
3
|
+
/** The default data attribute */
|
|
4
|
+
dataAttribute?: string;
|
|
5
|
+
/** is Init CSS filter to all targets */
|
|
6
|
+
init?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** The parse options for canvas */
|
|
10
|
+
export interface ParseOptions {
|
|
11
|
+
/** MIME types, defaults to `image/png` */
|
|
12
|
+
type?: string;
|
|
13
|
+
/** [0 - 1], defaults to `0.92` */
|
|
14
|
+
quality?: number;
|
|
15
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { FilterSetting } from './filters';
|
|
2
|
+
import { ParseOptions } from './types';
|
|
3
|
+
|
|
4
|
+
export const hasOffscreenCanvas = typeof OffscreenCanvas !== 'undefined';
|
|
5
|
+
|
|
6
|
+
export function assert<TCond = unknown>(condition: TCond, message = 'internal error.'): asserts condition {
|
|
7
|
+
if (!condition) throw Error(`[CCgram] ${message}`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function assertIsImage(image: HTMLImageElement): asserts image is HTMLImageElement {
|
|
11
|
+
assert(image && image.tagName === 'IMG', 'The first argument is required and must be an <img> element.');
|
|
12
|
+
assert(image.src, 'The <img> element src attribute is empty.');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function createWorker<
|
|
16
|
+
TData = unknown,
|
|
17
|
+
TMessage = unknown
|
|
18
|
+
>(fn: (messageEvent: MessageEvent<TData>) => TMessage): Worker {
|
|
19
|
+
const code = `
|
|
20
|
+
const work = ${fn.toString()};
|
|
21
|
+
|
|
22
|
+
addEventListener('message', async (...params) => {
|
|
23
|
+
const res = await work(...params);
|
|
24
|
+
postMessage(res);
|
|
25
|
+
});
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
const url = URL.createObjectURL(new Blob([code], { type: 'text/javascript' }));
|
|
29
|
+
const worker = new Worker(url);
|
|
30
|
+
|
|
31
|
+
const { terminate } = worker;
|
|
32
|
+
worker.terminate = (): void => {
|
|
33
|
+
URL.revokeObjectURL(url);
|
|
34
|
+
terminate.call(worker);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return worker;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Parse setting to style string
|
|
42
|
+
* @param setting - The filter setting
|
|
43
|
+
*/
|
|
44
|
+
export function parseSettingToStyle(setting?: FilterSetting): string {
|
|
45
|
+
if (!setting) return 'none';
|
|
46
|
+
|
|
47
|
+
return Object
|
|
48
|
+
.keys(setting)
|
|
49
|
+
.map((key): string => `${key}(${setting[key]}${
|
|
50
|
+
key === 'hue-rotate'
|
|
51
|
+
? 'deg'
|
|
52
|
+
: key === 'blur'
|
|
53
|
+
? 'px'
|
|
54
|
+
: ''
|
|
55
|
+
})`)
|
|
56
|
+
.join(' ');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface CreateBlobOptions<
|
|
60
|
+
TCanvas extends HTMLCanvasElement | OffscreenCanvas = HTMLCanvasElement
|
|
61
|
+
> {
|
|
62
|
+
canvas: TCanvas;
|
|
63
|
+
image: CanvasImageSource;
|
|
64
|
+
filterStyle: string;
|
|
65
|
+
options: ParseOptions;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function createBlobWorker({
|
|
69
|
+
data,
|
|
70
|
+
}: MessageEvent<CreateBlobOptions<OffscreenCanvas>>): Promise<Blob | null> {
|
|
71
|
+
const {
|
|
72
|
+
canvas,
|
|
73
|
+
image,
|
|
74
|
+
filterStyle,
|
|
75
|
+
options,
|
|
76
|
+
} = data;
|
|
77
|
+
|
|
78
|
+
const ctx = canvas.getContext('2d', { alpha: false });
|
|
79
|
+
if (!ctx) throw new Error('The 2d context canvas is not supported.');
|
|
80
|
+
|
|
81
|
+
ctx.filter = filterStyle;
|
|
82
|
+
ctx.drawImage(image, 0, 0);
|
|
83
|
+
|
|
84
|
+
return canvas.convertToBlob(options);
|
|
85
|
+
}
|
package/dist/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CCGram=e():t.CCGram=e()}("undefined"!=typeof self?self:this,(function(){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=12)}([function(t,e,r){t.exports=r(11)},function(t,e){t.exports=function(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}},function(t,e){function r(t,e,r,n,o,i,a){try{var u=t[i](a),c=u.value}catch(t){return void r(t)}u.done?e(c):Promise.resolve(c).then(n,o)}t.exports=function(t){return function(){var e=this,n=arguments;return new Promise((function(o,i){var a=t.apply(e,n);function u(t){r(a,o,i,u,c,"next",t)}function c(t){r(a,o,i,u,c,"throw",t)}u(void 0)}))}}},function(t,e){t.exports=function(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}},function(t,e,r){var n=r(7),o=r(8),i=r(9),a=r(10);t.exports=function(t){return n(t)||o(t)||i(t)||a()}},function(t,e){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},function(t,e){function r(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}t.exports=function(t,e,n){return e&&r(t.prototype,e),n&&r(t,n),t}},function(t,e,r){var n=r(3);t.exports=function(t){if(Array.isArray(t))return n(t)}},function(t,e){t.exports=function(t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(t))return Array.from(t)}},function(t,e,r){var n=r(3);t.exports=function(t,e){if(t){if("string"==typeof t)return n(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?n(t,e):void 0}}},function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}},function(t,e,r){var n=function(t){"use strict";var e=Object.prototype,r=e.hasOwnProperty,n="function"==typeof Symbol?Symbol:{},o=n.iterator||"@@iterator",i=n.asyncIterator||"@@asyncIterator",a=n.toStringTag||"@@toStringTag";function u(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{u({},"")}catch(t){u=function(t,e,r){return t[e]=r}}function c(t,e,r,n){var o=e&&e.prototype instanceof l?e:l,i=Object.create(o.prototype),a=new L(n||[]);return i._invoke=function(t,e,r){var n="suspendedStart";return function(o,i){if("executing"===n)throw new Error("Generator is already running");if("completed"===n){if("throw"===o)throw i;return j()}for(r.method=o,r.arg=i;;){var a=r.delegate;if(a){var u=w(a,r);if(u){if(u===f)continue;return u}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if("suspendedStart"===n)throw n="completed",r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);n="executing";var c=s(t,e,r);if("normal"===c.type){if(n=r.done?"completed":"suspendedYield",c.arg===f)continue;return{value:c.arg,done:r.done}}"throw"===c.type&&(n="completed",r.method="throw",r.arg=c.arg)}}}(t,r,a),i}function s(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}t.wrap=c;var f={};function l(){}function h(){}function p(){}var d={};d[o]=function(){return this};var y=Object.getPrototypeOf,v=y&&y(y(E([])));v&&v!==e&&r.call(v,o)&&(d=v);var g=p.prototype=l.prototype=Object.create(d);function m(t){["next","throw","return"].forEach((function(e){u(t,e,(function(t){return this._invoke(e,t)}))}))}function b(t,e){var n;this._invoke=function(o,i){function a(){return new e((function(n,a){!function n(o,i,a,u){var c=s(t[o],t,i);if("throw"!==c.type){var f=c.arg,l=f.value;return l&&"object"==typeof l&&r.call(l,"__await")?e.resolve(l.__await).then((function(t){n("next",t,a,u)}),(function(t){n("throw",t,a,u)})):e.resolve(l).then((function(t){f.value=t,a(f)}),(function(t){return n("throw",t,a,u)}))}u(c.arg)}(o,i,n,a)}))}return n=n?n.then(a,a):a()}}function w(t,e){var r=t.iterator[e.method];if(void 0===r){if(e.delegate=null,"throw"===e.method){if(t.iterator.return&&(e.method="return",e.arg=void 0,w(t,e),"throw"===e.method))return f;e.method="throw",e.arg=new TypeError("The iterator does not provide a 'throw' method")}return f}var n=s(r,t.iterator,e.arg);if("throw"===n.type)return e.method="throw",e.arg=n.arg,e.delegate=null,f;var o=n.arg;return o?o.done?(e[t.resultName]=o.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=void 0),e.delegate=null,f):o:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,f)}function x(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function _(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function L(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(x,this),this.reset(!0)}function E(t){if(t){var e=t[o];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,i=function e(){for(;++n<t.length;)if(r.call(t,n))return e.value=t[n],e.done=!1,e;return e.value=void 0,e.done=!0,e};return i.next=i}}return{next:j}}function j(){return{value:void 0,done:!0}}return h.prototype=g.constructor=p,p.constructor=h,h.displayName=u(p,a,"GeneratorFunction"),t.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===h||"GeneratorFunction"===(e.displayName||e.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,p):(t.__proto__=p,u(t,a,"GeneratorFunction")),t.prototype=Object.create(g),t},t.awrap=function(t){return{__await:t}},m(b.prototype),b.prototype[i]=function(){return this},t.AsyncIterator=b,t.async=function(e,r,n,o,i){void 0===i&&(i=Promise);var a=new b(c(e,r,n,o),i);return t.isGeneratorFunction(r)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},m(g),u(g,a,"Generator"),g[o]=function(){return this},g.toString=function(){return"[object Generator]"},t.keys=function(t){var e=[];for(var r in t)e.push(r);return e.reverse(),function r(){for(;e.length;){var n=e.pop();if(n in t)return r.value=n,r.done=!1,r}return r.done=!0,r}},t.values=E,L.prototype={constructor:L,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=void 0,this.done=!1,this.delegate=null,this.method="next",this.arg=void 0,this.tryEntries.forEach(_),!t)for(var e in this)"t"===e.charAt(0)&&r.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=void 0)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function n(r,n){return a.type="throw",a.arg=t,e.next=r,n&&(e.method="next",e.arg=void 0),!!n}for(var o=this.tryEntries.length-1;o>=0;--o){var i=this.tryEntries[o],a=i.completion;if("root"===i.tryLoc)return n("end");if(i.tryLoc<=this.prev){var u=r.call(i,"catchLoc"),c=r.call(i,"finallyLoc");if(u&&c){if(this.prev<i.catchLoc)return n(i.catchLoc,!0);if(this.prev<i.finallyLoc)return n(i.finallyLoc)}else if(u){if(this.prev<i.catchLoc)return n(i.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return n(i.finallyLoc)}}}},abrupt:function(t,e){for(var n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var i=o;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=e&&e<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=e,i?(this.method="next",this.next=i.finallyLoc,f):this.complete(a)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),f},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),_(r),f}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;_(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,r){return this.delegate={iterator:E(t),resultName:e,nextLoc:r},"next"===this.method&&(this.arg=void 0),f}},t}(t.exports);try{regeneratorRuntime=n}catch(t){Function("r","regeneratorRuntime = r")(n)}},function(t,e,r){"use strict";r.r(e),r.d(e,"CCGram",(function(){return g}));var n=r(4),o=r.n(n),i=r(0),a=r.n(i),u=r(2),c=r.n(u),s=r(5),f=r.n(s),l=r(6),h=r.n(l),p=r(1),d=r.n(p),y=new Map([["aden",{"hue-rotate":-20,contrast:.9,brightness:1.2,saturate:.85}],["inkwell",{sepia:.3,contrast:1.1,brightness:1.1,grayscale:1}],["reyes",{sepia:.22,contrast:.85,brightness:1.1,saturate:.75}],["gingham",{"hue-rotate":-10,brightness:1.05}],["toaster",{contrast:1.5,brightness:.9}],["walden",{"hue-rotate":-10,brightness:1.1,sepia:.3,saturate:1.6}],["hudson",{brightness:1.2,contrast:.9,saturate:1.1}],["earlybird",{contrast:.9,sepia:.2}],["mayfair",{contrast:1.1,saturate:1.1}],["lofi",{contrast:1.5,saturate:1.1}],["1977",{contrast:1.1,brightness:1.1,saturate:1.3}],["brooklyn",{contrast:.9,brightness:1.1}],["xpro2",{sepia:.3}],["nashville",{contrast:1.2,brightness:1.05,saturate:1.2,sepia:.2}],["lark",{contrast:.9}],["moon",{brightness:1.1,contrast:1.1,grayscale:1}],["clarendon",{contrast:1.2,saturate:1.35}],["willow",{contrast:.95,brightness:.9,grayscale:.5}],["rise",{contrast:.9,brightness:1.05,sepia:.2,saturate:.9}],["slumber",{brightness:1.05,saturate:.66}],["brannan",{contrast:1.4,sepia:.5}],["valencia",{contrast:1.08,brightness:1.08,sepia:.08}],["maven",{contrast:.95,brightness:1.95,saturate:1.5,sepia:.25}],["stinson",{contrast:.75,brightness:1.15,saturate:.85}],["amaro",{"hue-rotate":-10,contrast:.9,brightness:1.1,saturate:1.5}]]),v=function(t){return t?Object.keys(t).map((function(e){return"".concat(e,"(").concat(t[e]).concat("hue-rotate"===e?"deg":"blur"===e?"px":"",")")})).join(" "):"none"},g=function(){function t(){var e=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=r.dataAttribute,o=void 0===n?t.DEFAULT_DATA_ATTRIBUTE:n,i=r.init,a=void 0===i||i;if(f()(this,t),d()(this,"_filters",y),d()(this,"_dataAttribute",void 0),this._dataAttribute=o,a)if("complete"!==document.readyState){var u=function t(){e.applyFilter(),document.removeEventListener("DOMContentLoaded",t)};document.addEventListener("DOMContentLoaded",u)}else this.applyFilter()}var e,r;return h()(t,[{key:"setFilter",value:function(t,e){this._filters.set(t,e)}},{key:"removeFilter",value:function(t){return this._filters.delete(t)}},{key:"getFilterSetting",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return this._filters.get(t)}},{key:"getFilterStyle",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=this._filters.get(t);return v(e)}},{key:"applyFilter",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"img[data-".concat(this._dataAttribute,"]");document.querySelectorAll(e).forEach((function(e){var r=e.dataset;e.style.filter=t.getFilterStyle(r[t._dataAttribute])}))}},{key:"_getImageCanvas",value:function(t){if(!t||"IMG"!==t.tagName)throw new Error("The first argument is required and must be an <img> element.");if(!t.src)throw new Error("The <img> element src attribute is empty.");return function(t,e){return new Promise((function(r,n){var o=t.naturalWidth,i=t.naturalHeight,a=document.createElement("canvas");a.width=o,a.height=i;var u=a.getContext("2d",{alpha:!1});return u?(u.filter=e,u.drawImage(t,0,0),r(a)):n(new Error("The 2d context canvas is not supported."))}))}(t,this.getFilterStyle(t.dataset[this._dataAttribute]))}},{key:"getDataURL",value:(r=c()(a.a.mark((function t(e){var r,n,o,i,u=arguments;return a.a.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=u.length>1&&void 0!==u[1]?u[1]:{},n=r.type,o=r.quality,t.next=3,this._getImageCanvas(e);case 3:return i=t.sent,t.abrupt("return",i.toDataURL(n,o));case 5:case"end":return t.stop()}}),t,this)}))),function(t){return r.apply(this,arguments)})},{key:"getBlob",value:(e=c()(a.a.mark((function t(e){var r,n,o,i,u=arguments;return a.a.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=u.length>1&&void 0!==u[1]?u[1]:{},n=r.type,o=r.quality,t.next=3,this._getImageCanvas(e);case 3:return i=t.sent,t.abrupt("return",new Promise((function(t){i.toBlob((function(e){return t(e)}),n,o)})));case 5:case"end":return t.stop()}}),t,this)}))),function(t){return e.apply(this,arguments)})},{key:"filterNames",get:function(){return o()(this._filters.keys())}}]),t}();d()(g,"DEFAULT_DATA_ATTRIBUTE","filter");e.default=g}])}));
|
package/dist/types/index.d.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @package cc-gram <https://github.com/EastSun5566/cc-gram>
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
* @copyright (c) 2019 - present
|
|
6
|
-
* @author 汪東陽 EastSun5566 <https://github.com/EastSun5566>
|
|
7
|
-
*/
|
|
8
|
-
import { FilterName, FilterSetting } from './filters';
|
|
9
|
-
/** The options for canvas */
|
|
10
|
-
interface Options {
|
|
11
|
-
/** MIME types, default is `image/png` */
|
|
12
|
-
type?: string;
|
|
13
|
-
/** [0 - 1], default is `0.92` */
|
|
14
|
-
quality?: number;
|
|
15
|
-
}
|
|
16
|
-
/** Initial Config */
|
|
17
|
-
interface Config {
|
|
18
|
-
/** The default data attribute */
|
|
19
|
-
dataAttribute?: string;
|
|
20
|
-
/** is Init CSS filter to all targets */
|
|
21
|
-
init?: boolean;
|
|
22
|
-
}
|
|
23
|
-
/** 🖼 A CSS & Canvas Instagram filters based on CSSgram */
|
|
24
|
-
export declare class CCGram {
|
|
25
|
-
/** default option */
|
|
26
|
-
static readonly DEFAULT_DATA_ATTRIBUTE = "filter";
|
|
27
|
-
/** filter list */
|
|
28
|
-
protected readonly _filters: Map<string, FilterSetting>;
|
|
29
|
-
/** data attribute */
|
|
30
|
-
protected _dataAttribute: string;
|
|
31
|
-
/** Initialize CSS filter to all targets */
|
|
32
|
-
constructor({ dataAttribute, init, }?: Config);
|
|
33
|
-
/** The filter name list */
|
|
34
|
-
get filterNames(): FilterName[];
|
|
35
|
-
/**
|
|
36
|
-
* Add/Set filter
|
|
37
|
-
* @param {FilterName} name - the Filter name
|
|
38
|
-
* @param {FilterSetting} setting - the Filter setting
|
|
39
|
-
*/
|
|
40
|
-
setFilter(name: FilterName, setting: FilterSetting): void;
|
|
41
|
-
/**
|
|
42
|
-
* Remove filter
|
|
43
|
-
* @param {FilterName} name - the Filter name
|
|
44
|
-
*/
|
|
45
|
-
removeFilter(name: FilterName): boolean;
|
|
46
|
-
/**
|
|
47
|
-
* Get setting of filter
|
|
48
|
-
* @param {FilterName} [name=''] - The filter name
|
|
49
|
-
*/
|
|
50
|
-
getFilterSetting(name?: FilterName): FilterSetting | void;
|
|
51
|
-
/**
|
|
52
|
-
* Get the CSS inline style of filter
|
|
53
|
-
* @param {FilterName} [name=''] - The filter name
|
|
54
|
-
*/
|
|
55
|
-
getFilterStyle(name?: FilterName): string;
|
|
56
|
-
/**
|
|
57
|
-
* Apply CSS filter to all targets
|
|
58
|
-
* @param {string} [selectors='img[data-${this._dataAttribute}]'] - selectors
|
|
59
|
-
*/
|
|
60
|
-
applyFilter(selectors?: string): void;
|
|
61
|
-
/**
|
|
62
|
-
* Create canvas of image element
|
|
63
|
-
* @param {HTMLImageElement} image
|
|
64
|
-
*/
|
|
65
|
-
protected _getImageCanvas(image: HTMLImageElement): Promise<HTMLCanvasElement>;
|
|
66
|
-
/**
|
|
67
|
-
* Get the data URL of image element
|
|
68
|
-
* @param {HTMLImageElement} image - image element
|
|
69
|
-
* @param {Options} [options={}] - options
|
|
70
|
-
*/
|
|
71
|
-
getDataURL(image: HTMLImageElement, { type, quality }?: Options): Promise<string>;
|
|
72
|
-
/**
|
|
73
|
-
* Get the blob of image element
|
|
74
|
-
* @param {HTMLImageElement} image - image element
|
|
75
|
-
* @param {Options} [options={}] - options
|
|
76
|
-
*/
|
|
77
|
-
getBlob(image: HTMLImageElement, { type, quality }?: Options): Promise<Blob | null>;
|
|
78
|
-
}
|
|
79
|
-
export default CCGram;
|
package/dist/types/utils.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { FilterSetting } from './filters';
|
|
2
|
-
/**
|
|
3
|
-
* Parse setting to style
|
|
4
|
-
* @param {FilterSetting} setting - The filter setting
|
|
5
|
-
*/
|
|
6
|
-
export declare const parseSettingToStyle: (setting?: FilterSetting | undefined) => string;
|
|
7
|
-
/**
|
|
8
|
-
* Create filter image canvas
|
|
9
|
-
* @param {HTMLImageElement} image - The image
|
|
10
|
-
* @param {string} filterStyle - The filter style
|
|
11
|
-
*/
|
|
12
|
-
export declare const createFilterImageCanvas: (image: HTMLImageElement, filterStyle: string) => Promise<HTMLCanvasElement>;
|