canvas-img 0.0.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/README.md +101 -0
- package/READMME.md +101 -0
- package/canvas-img.js +197 -0
- package/demo.html +46 -0
- package/package.json +16 -0
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# canvas-img
|
|
2
|
+
Canvas draw image cross origin resource
|
|
3
|
+
|
|
4
|
+
## TODO
|
|
5
|
+
1. clear img
|
|
6
|
+
2. use Image
|
|
7
|
+
|
|
8
|
+
## Demo
|
|
9
|
+
```html
|
|
10
|
+
<!DOCTYPE html>
|
|
11
|
+
<html>
|
|
12
|
+
<head>
|
|
13
|
+
<meta charset="UTF-8">
|
|
14
|
+
<title>drawImageCORS demo</title>
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<canvas id="myCanvas" width="800" height="600"></canvas>
|
|
18
|
+
|
|
19
|
+
<script src="canvas-img.js"></script>
|
|
20
|
+
|
|
21
|
+
<script>
|
|
22
|
+
const canvas = document.getElementById('myCanvas');
|
|
23
|
+
const ctx = canvas.getContext('2d');
|
|
24
|
+
|
|
25
|
+
// drawImageCORS (src, x, y)
|
|
26
|
+
ctx.drawImageCORS('https://picsum.photos/400/300', 50, 50)
|
|
27
|
+
.then(() => console.log('done'))
|
|
28
|
+
.catch(err => console.error('error:', err));
|
|
29
|
+
|
|
30
|
+
// drawImageCORS (src, x, y, width, height)
|
|
31
|
+
ctx.drawImageCORS('https://picsum.photos/400/200', 500, 50, 200, 150)
|
|
32
|
+
.then(() => console.log('done'));
|
|
33
|
+
|
|
34
|
+
// drawImageCORS (src, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
|
35
|
+
ctx.drawImageCORS(
|
|
36
|
+
'https://picsum.photos/400/400',
|
|
37
|
+
50, 50, 200, 150, // clip
|
|
38
|
+
50, 300, 200, 150
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
async function loadMultiple() {
|
|
42
|
+
try {
|
|
43
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 0, 0);
|
|
44
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 200, 0);
|
|
45
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 400, 0);
|
|
46
|
+
console.log('all done');
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error('load error:', error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
loadMultiple();
|
|
53
|
+
</script>
|
|
54
|
+
</body>
|
|
55
|
+
</html><!DOCTYPE html>
|
|
56
|
+
<html>
|
|
57
|
+
<head>
|
|
58
|
+
<meta charset="UTF-8">
|
|
59
|
+
<title>drawImageCORS demo</title>
|
|
60
|
+
</head>
|
|
61
|
+
<body>
|
|
62
|
+
<canvas id="myCanvas" width="800" height="600"></canvas>
|
|
63
|
+
|
|
64
|
+
<script src="canvas-img.js"></script>
|
|
65
|
+
|
|
66
|
+
<script>
|
|
67
|
+
const canvas = document.getElementById('myCanvas');
|
|
68
|
+
const ctx = canvas.getContext('2d');
|
|
69
|
+
|
|
70
|
+
// drawImageCORS (src, x, y)
|
|
71
|
+
ctx.drawImageCORS('https://picsum.photos/400/300', 50, 50)
|
|
72
|
+
.then(() => console.log('done'))
|
|
73
|
+
.catch(err => console.error('error:', err));
|
|
74
|
+
|
|
75
|
+
// drawImageCORS (src, x, y, width, height)
|
|
76
|
+
ctx.drawImageCORS('https://picsum.photos/400/200', 500, 50, 200, 150)
|
|
77
|
+
.then(() => console.log('done'));
|
|
78
|
+
|
|
79
|
+
// drawImageCORS (src, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
|
80
|
+
ctx.drawImageCORS(
|
|
81
|
+
'https://picsum.photos/400/400',
|
|
82
|
+
50, 50, 200, 150, // clip
|
|
83
|
+
50, 300, 200, 150
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
async function loadMultiple() {
|
|
87
|
+
try {
|
|
88
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 0, 0);
|
|
89
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 200, 0);
|
|
90
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 400, 0);
|
|
91
|
+
console.log('all done');
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error('load error:', error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
loadMultiple();
|
|
98
|
+
</script>
|
|
99
|
+
</body>
|
|
100
|
+
</html>
|
|
101
|
+
```
|
package/READMME.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# canvas-img
|
|
2
|
+
Canvas draw image cross origin resource
|
|
3
|
+
|
|
4
|
+
## TODO
|
|
5
|
+
1. clear img
|
|
6
|
+
2. use Image
|
|
7
|
+
|
|
8
|
+
s## Demo
|
|
9
|
+
```html
|
|
10
|
+
<!DOCTYPE html>
|
|
11
|
+
<html>
|
|
12
|
+
<head>
|
|
13
|
+
<meta charset="UTF-8">
|
|
14
|
+
<title>drawImageCORS demo</title>
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<canvas id="myCanvas" width="800" height="600"></canvas>
|
|
18
|
+
|
|
19
|
+
<script src="canvas-img.js"></script>
|
|
20
|
+
|
|
21
|
+
<script>
|
|
22
|
+
const canvas = document.getElementById('myCanvas');
|
|
23
|
+
const ctx = canvas.getContext('2d');
|
|
24
|
+
|
|
25
|
+
// drawImageCORS (src, x, y)
|
|
26
|
+
ctx.drawImageCORS('https://picsum.photos/400/300', 50, 50)
|
|
27
|
+
.then(() => console.log('done'))
|
|
28
|
+
.catch(err => console.error('error:', err));
|
|
29
|
+
|
|
30
|
+
// drawImageCORS (src, x, y, width, height)
|
|
31
|
+
ctx.drawImageCORS('https://picsum.photos/400/200', 500, 50, 200, 150)
|
|
32
|
+
.then(() => console.log('done'));
|
|
33
|
+
|
|
34
|
+
// drawImageCORS (src, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
|
35
|
+
ctx.drawImageCORS(
|
|
36
|
+
'https://picsum.photos/400/400',
|
|
37
|
+
50, 50, 200, 150, // clip
|
|
38
|
+
50, 300, 200, 150
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
async function loadMultiple() {
|
|
42
|
+
try {
|
|
43
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 0, 0);
|
|
44
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 200, 0);
|
|
45
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 400, 0);
|
|
46
|
+
console.log('all done');
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error('load error:', error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
loadMultiple();
|
|
53
|
+
</script>
|
|
54
|
+
</body>
|
|
55
|
+
</html><!DOCTYPE html>
|
|
56
|
+
<html>
|
|
57
|
+
<head>
|
|
58
|
+
<meta charset="UTF-8">
|
|
59
|
+
<title>drawImageCORS demo</title>
|
|
60
|
+
</head>
|
|
61
|
+
<body>
|
|
62
|
+
<canvas id="myCanvas" width="800" height="600"></canvas>
|
|
63
|
+
|
|
64
|
+
<script src="canvas-img.js"></script>
|
|
65
|
+
|
|
66
|
+
<script>
|
|
67
|
+
const canvas = document.getElementById('myCanvas');
|
|
68
|
+
const ctx = canvas.getContext('2d');
|
|
69
|
+
|
|
70
|
+
// drawImageCORS (src, x, y)
|
|
71
|
+
ctx.drawImageCORS('https://picsum.photos/400/300', 50, 50)
|
|
72
|
+
.then(() => console.log('done'))
|
|
73
|
+
.catch(err => console.error('error:', err));
|
|
74
|
+
|
|
75
|
+
// drawImageCORS (src, x, y, width, height)
|
|
76
|
+
ctx.drawImageCORS('https://picsum.photos/400/200', 500, 50, 200, 150)
|
|
77
|
+
.then(() => console.log('done'));
|
|
78
|
+
|
|
79
|
+
// drawImageCORS (src, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
|
80
|
+
ctx.drawImageCORS(
|
|
81
|
+
'https://picsum.photos/400/400',
|
|
82
|
+
50, 50, 200, 150, // clip
|
|
83
|
+
50, 300, 200, 150
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
async function loadMultiple() {
|
|
87
|
+
try {
|
|
88
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 0, 0);
|
|
89
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 200, 0);
|
|
90
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 400, 0);
|
|
91
|
+
console.log('all done');
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error('load error:', error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
loadMultiple();
|
|
98
|
+
</script>
|
|
99
|
+
</body>
|
|
100
|
+
</html>
|
|
101
|
+
```
|
package/canvas-img.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* canvas.drawImageCORS - Cross-origin image drawing library
|
|
3
|
+
* Loads images by dynamically creating hidden <img> elements, then draws them to canvas after loading completes
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* canvas.drawImageCORS(src, x, y)
|
|
7
|
+
* canvas.drawImageCORS(src, x, y, width, height)
|
|
8
|
+
* canvas.drawImageCORS(src, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
|
9
|
+
*
|
|
10
|
+
* Returns: Promise that resolves when the image is loaded and drawn
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
(function () {
|
|
14
|
+
function injectHiddenStyle() {
|
|
15
|
+
// random id
|
|
16
|
+
if (document.getElementById("style-3bXfmO7c")) return;
|
|
17
|
+
|
|
18
|
+
const style = document.createElement("style");
|
|
19
|
+
style.id = "style-3bXfmO7c";
|
|
20
|
+
style.textContent = `
|
|
21
|
+
._3bXfmO7c {
|
|
22
|
+
width: 0px;
|
|
23
|
+
height: 0px;
|
|
24
|
+
display: none;
|
|
25
|
+
position: absolute;
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
opacity: 0;
|
|
28
|
+
visibility: hidden;
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
document.head.appendChild(style);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
injectHiddenStyle();
|
|
35
|
+
|
|
36
|
+
function createHiddenImg(src) {
|
|
37
|
+
const img = document.createElement("img");
|
|
38
|
+
img.className = "_3bXfmO7c";
|
|
39
|
+
document.body.appendChild(img);
|
|
40
|
+
return img;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function loadImage(src) {
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
const img = createHiddenImg(src);
|
|
46
|
+
|
|
47
|
+
const onLoad = function () {
|
|
48
|
+
img.removeEventListener("load", onLoad);
|
|
49
|
+
img.removeEventListener("error", onError);
|
|
50
|
+
resolve(img);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const onError = function () {
|
|
54
|
+
img.removeEventListener("load", onLoad);
|
|
55
|
+
img.removeEventListener("error", onError);
|
|
56
|
+
|
|
57
|
+
if (img.parentNode) {
|
|
58
|
+
img.parentNode.removeChild(img);
|
|
59
|
+
}
|
|
60
|
+
reject("Load image error " + src);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
img.addEventListener("load", onLoad);
|
|
64
|
+
img.addEventListener("error", onError);
|
|
65
|
+
|
|
66
|
+
img.src = src;
|
|
67
|
+
|
|
68
|
+
// If the image is already cached (browser cache), complete may be true
|
|
69
|
+
if (img.complete) {
|
|
70
|
+
// But onload may or may not have been triggered, handle it manually
|
|
71
|
+
if (img.naturalWidth > 0) {
|
|
72
|
+
// Manually trigger the load event
|
|
73
|
+
const loadEvent = new Event("load");
|
|
74
|
+
img.dispatchEvent(loadEvent);
|
|
75
|
+
} else {
|
|
76
|
+
// Manually trigger the error event
|
|
77
|
+
const errorEvent = new Event("error");
|
|
78
|
+
img.dispatchEvent(errorEvent);
|
|
79
|
+
}
|
|
80
|
+
resolve(img);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function parseArguments(args) {
|
|
86
|
+
if (args.length === 3) {
|
|
87
|
+
// drawImageCORS(src, x, y)
|
|
88
|
+
return {
|
|
89
|
+
type: "simple",
|
|
90
|
+
src: args[0],
|
|
91
|
+
x: args[1],
|
|
92
|
+
y: args[2],
|
|
93
|
+
};
|
|
94
|
+
} else if (args.length === 5) {
|
|
95
|
+
// drawImageCORS(src, x, y, width, height)
|
|
96
|
+
return {
|
|
97
|
+
type: "scaled",
|
|
98
|
+
src: args[0],
|
|
99
|
+
x: args[1],
|
|
100
|
+
y: args[2],
|
|
101
|
+
width: args[3],
|
|
102
|
+
height: args[4],
|
|
103
|
+
};
|
|
104
|
+
} else if (args.length === 9) {
|
|
105
|
+
// drawImageCORS(src, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
|
106
|
+
return {
|
|
107
|
+
type: "cropped",
|
|
108
|
+
src: args[0],
|
|
109
|
+
sx: args[1],
|
|
110
|
+
sy: args[2],
|
|
111
|
+
sWidth: args[3],
|
|
112
|
+
sHeight: args[4],
|
|
113
|
+
dx: args[5],
|
|
114
|
+
dy: args[6],
|
|
115
|
+
dWidth: args[7],
|
|
116
|
+
dHeight: args[8],
|
|
117
|
+
};
|
|
118
|
+
} else {
|
|
119
|
+
throw new Error("Invalid number of arguments: expected 3, 5, or 9 arguments, but got ${args.length}");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function isCanvasValid(ctx) {
|
|
124
|
+
return ctx instanceof CanvasRenderingContext2D;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function drawImageCORS(...args) {
|
|
128
|
+
const ctx = this;
|
|
129
|
+
|
|
130
|
+
if (!isCanvasValid(ctx)) {
|
|
131
|
+
return Promise.reject(new Error("Invalid canvas"));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let params;
|
|
135
|
+
try {
|
|
136
|
+
params = parseArguments(args);
|
|
137
|
+
} catch (e) {
|
|
138
|
+
return Promise.reject(e);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const src = params.src;
|
|
142
|
+
if (!src || typeof src !== "string") {
|
|
143
|
+
return Promise.reject(new Error("Invalid image address"));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return loadImage(src)
|
|
147
|
+
.then((img) => {
|
|
148
|
+
if (!isCanvasValid(ctx)) {
|
|
149
|
+
throw new Error("Invalid canvas");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
switch (params.type) {
|
|
153
|
+
case "simple":
|
|
154
|
+
ctx.drawImage(img, params.x, params.y);
|
|
155
|
+
break;
|
|
156
|
+
case "scaled":
|
|
157
|
+
ctx.drawImage(img, params.x, params.y, params.width, params.height);
|
|
158
|
+
break;
|
|
159
|
+
case "cropped":
|
|
160
|
+
ctx.drawImage(
|
|
161
|
+
img,
|
|
162
|
+
params.sx,
|
|
163
|
+
params.sy,
|
|
164
|
+
params.sWidth,
|
|
165
|
+
params.sHeight,
|
|
166
|
+
params.dx,
|
|
167
|
+
params.dy,
|
|
168
|
+
params.dWidth,
|
|
169
|
+
params.dHeight,
|
|
170
|
+
);
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return img;
|
|
175
|
+
})
|
|
176
|
+
.catch((error) => {
|
|
177
|
+
console.error("drawImageCORS faild:", error.message);
|
|
178
|
+
throw error;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (typeof CanvasRenderingContext2D !== "undefined") {
|
|
183
|
+
CanvasRenderingContext2D.prototype.drawImageCORS = drawImageCORS;
|
|
184
|
+
} else {
|
|
185
|
+
if (typeof HTMLCanvasElement !== "undefined") {
|
|
186
|
+
HTMLCanvasElement.prototype.drawImageCORS = drawImageCORS;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (typeof module !== "undefined" && module.exports) {
|
|
191
|
+
module.exports = {
|
|
192
|
+
drawImageCORS,
|
|
193
|
+
};
|
|
194
|
+
} else if (typeof window !== "undefined") {
|
|
195
|
+
window.drawImageCORS = drawImageCORS;
|
|
196
|
+
}
|
|
197
|
+
})();
|
package/demo.html
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>drawImageCORS demo</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<canvas id="myCanvas" width="800" height="600"></canvas>
|
|
9
|
+
|
|
10
|
+
<script src="canvas-img.js"></script>
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
const canvas = document.getElementById('myCanvas');
|
|
14
|
+
const ctx = canvas.getContext('2d');
|
|
15
|
+
|
|
16
|
+
// drawImageCORS (src, x, y)
|
|
17
|
+
ctx.drawImageCORS('https://picsum.photos/400/300', 50, 50)
|
|
18
|
+
.then(() => console.log('done'))
|
|
19
|
+
.catch(err => console.error('error:', err));
|
|
20
|
+
|
|
21
|
+
// drawImageCORS (src, x, y, width, height)
|
|
22
|
+
ctx.drawImageCORS('https://picsum.photos/400/200', 500, 50, 200, 150)
|
|
23
|
+
.then(() => console.log('done'));
|
|
24
|
+
|
|
25
|
+
// drawImageCORS (src, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
|
26
|
+
ctx.drawImageCORS(
|
|
27
|
+
'https://picsum.photos/400/400',
|
|
28
|
+
50, 50, 200, 150, // clip
|
|
29
|
+
50, 300, 200, 150
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
async function loadMultiple() {
|
|
33
|
+
try {
|
|
34
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 0, 0);
|
|
35
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 200, 0);
|
|
36
|
+
await ctx.drawImageCORS('https://picsum.photos/200/200', 400, 0);
|
|
37
|
+
console.log('all done');
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('load error:', error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
loadMultiple();
|
|
44
|
+
</script>
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "canvas-img",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "canvas-img.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"canvas",
|
|
10
|
+
"drawImageCORS",
|
|
11
|
+
"canvas-img"
|
|
12
|
+
],
|
|
13
|
+
"author": "molang",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"description": ""
|
|
16
|
+
}
|