@tsparticles/shape-image 3.9.1 → 4.0.0-alpha.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/324.min.js +2 -0
- package/324.min.js.LICENSE.txt +1 -0
- package/554.min.js +2 -0
- package/554.min.js.LICENSE.txt +1 -0
- package/937.min.js +2 -0
- package/937.min.js.LICENSE.txt +1 -0
- package/968.min.js +2 -0
- package/968.min.js.LICENSE.txt +1 -0
- package/browser/GifUtils/Utils.js +10 -15
- package/browser/ImageDrawer.js +7 -14
- package/browser/ImagePreloader.js +2 -5
- package/browser/Utils.js +10 -10
- package/browser/index.js +21 -19
- package/cjs/GifUtils/ByteStream.js +1 -5
- package/cjs/GifUtils/Constants.js +2 -5
- package/cjs/GifUtils/Enums/DisposalMethod.js +2 -5
- package/cjs/GifUtils/Types/ApplicationExtension.js +1 -2
- package/cjs/GifUtils/Types/Frame.js +1 -2
- package/cjs/GifUtils/Types/GIF.js +1 -2
- package/cjs/GifUtils/Types/GIFDataHeaders.js +2 -5
- package/cjs/GifUtils/Types/GIFProgressCallbackFunction.js +1 -2
- package/cjs/GifUtils/Types/PlainTextData.js +1 -2
- package/cjs/GifUtils/Utils.js +41 -52
- package/cjs/IImageShape.js +1 -2
- package/cjs/ImageDrawer.js +11 -22
- package/cjs/ImagePreloader.js +5 -12
- package/cjs/Options/Classes/Preload.js +3 -7
- package/cjs/Options/Interfaces/IPreload.js +1 -2
- package/cjs/Utils.js +12 -17
- package/cjs/index.js +22 -23
- package/cjs/types.js +1 -2
- package/dist_browser_GifUtils_Utils_js.js +80 -0
- package/dist_browser_ImageDrawer_js.js +30 -0
- package/dist_browser_ImagePreloader_js.js +40 -0
- package/dist_browser_Utils_js.js +30 -0
- package/esm/GifUtils/Utils.js +10 -15
- package/esm/ImageDrawer.js +7 -14
- package/esm/ImagePreloader.js +2 -5
- package/esm/Utils.js +10 -10
- package/esm/index.js +21 -19
- package/package.json +4 -3
- package/report.html +5 -4
- package/tsparticles.shape.image.js +209 -110
- package/tsparticles.shape.image.min.js +1 -1
- package/tsparticles.shape.image.min.js.LICENSE.txt +1 -1
- package/types/ImagePreloader.d.ts +2 -3
- package/types/Options/Classes/Preload.d.ts +2 -2
- package/types/Utils.d.ts +1 -1
- package/types/index.d.ts +1 -1
- package/umd/GifUtils/Utils.js +10 -15
- package/umd/ImageDrawer.js +8 -15
- package/umd/ImagePreloader.js +2 -5
- package/umd/Utils.js +9 -9
- package/umd/index.js +57 -21
package/cjs/GifUtils/Utils.js
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports.loadGifImage = loadGifImage;
|
|
7
|
-
const Utils_js_1 = require("../Utils.js");
|
|
8
|
-
const Constants_js_1 = require("./Constants.js");
|
|
9
|
-
const ByteStream_js_1 = require("./ByteStream.js");
|
|
10
|
-
const DisposalMethod_js_1 = require("./Enums/DisposalMethod.js");
|
|
11
|
-
const GIFDataHeaders_js_1 = require("./Types/GIFDataHeaders.js");
|
|
1
|
+
import { loadImage } from "../Utils.js";
|
|
2
|
+
import { InterlaceOffsets, InterlaceSteps } from "./Constants.js";
|
|
3
|
+
import { ByteStream } from "./ByteStream.js";
|
|
4
|
+
import { DisposalMethod } from "./Enums/DisposalMethod.js";
|
|
5
|
+
import { GIFDataHeaders } from "./Types/GIFDataHeaders.js";
|
|
12
6
|
const origin = {
|
|
13
7
|
x: 0,
|
|
14
8
|
y: 0,
|
|
@@ -27,7 +21,7 @@ function parseColorTable(byteStream, count) {
|
|
|
27
21
|
}
|
|
28
22
|
function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
|
|
29
23
|
switch (byteStream.nextByte()) {
|
|
30
|
-
case
|
|
24
|
+
case GIFDataHeaders.GraphicsControlExtension: {
|
|
31
25
|
const frame = gif.frames[getFrameIndex(false)];
|
|
32
26
|
byteStream.pos++;
|
|
33
27
|
const packedByte = byteStream.nextByte();
|
|
@@ -43,7 +37,7 @@ function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyInde
|
|
|
43
37
|
byteStream.pos++;
|
|
44
38
|
break;
|
|
45
39
|
}
|
|
46
|
-
case
|
|
40
|
+
case GIFDataHeaders.ApplicationExtension: {
|
|
47
41
|
byteStream.pos++;
|
|
48
42
|
const applicationExtension = {
|
|
49
43
|
identifier: byteStream.getString(8),
|
|
@@ -53,11 +47,11 @@ function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyInde
|
|
|
53
47
|
gif.applicationExtensions.push(applicationExtension);
|
|
54
48
|
break;
|
|
55
49
|
}
|
|
56
|
-
case
|
|
50
|
+
case GIFDataHeaders.CommentExtension: {
|
|
57
51
|
gif.comments.push([getFrameIndex(false), byteStream.readSubBlocks()]);
|
|
58
52
|
break;
|
|
59
53
|
}
|
|
60
|
-
case
|
|
54
|
+
case GIFDataHeaders.PlainTextExtension: {
|
|
61
55
|
if (gif.globalColorTable.length === 0) {
|
|
62
56
|
throw new EvalError("plain text extension without global color table");
|
|
63
57
|
}
|
|
@@ -100,7 +94,7 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
100
94
|
if (index !== getTransparencyIndex(null)) {
|
|
101
95
|
return { r, g, b, a: 255 };
|
|
102
96
|
}
|
|
103
|
-
return { r, g, b, a: avgAlpha ?
|
|
97
|
+
return { r, g, b, a: avgAlpha ? Math.trunc((r + g + b) / 3) : 0 };
|
|
104
98
|
};
|
|
105
99
|
const image = (() => {
|
|
106
100
|
try {
|
|
@@ -125,7 +119,7 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
125
119
|
};
|
|
126
120
|
if (interlacedFlag) {
|
|
127
121
|
for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
|
|
128
|
-
if (
|
|
122
|
+
if (InterlaceOffsets[pass] < frame.height) {
|
|
129
123
|
let pixelPos = 0, lineIndex = 0, exit = false;
|
|
130
124
|
while (!exit) {
|
|
131
125
|
const last = code;
|
|
@@ -147,8 +141,8 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
147
141
|
}
|
|
148
142
|
for (const item of dic[code]) {
|
|
149
143
|
const { r, g, b, a } = getColor(item);
|
|
150
|
-
image.data.set([r, g, b, a],
|
|
151
|
-
|
|
144
|
+
image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width +
|
|
145
|
+
InterlaceSteps[pass] * lineIndex +
|
|
152
146
|
(pixelPos % (frame.width * 4)));
|
|
153
147
|
pixelPos += 4;
|
|
154
148
|
}
|
|
@@ -158,7 +152,7 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
158
152
|
}
|
|
159
153
|
if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
|
|
160
154
|
lineIndex++;
|
|
161
|
-
if (
|
|
155
|
+
if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
|
|
162
156
|
exit = true;
|
|
163
157
|
}
|
|
164
158
|
}
|
|
@@ -170,9 +164,9 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
170
164
|
frame.bitmap = await createImageBitmap(image);
|
|
171
165
|
}
|
|
172
166
|
else {
|
|
173
|
-
let code = 0, size = minCodeSize + 1, pos = 0, pixelPos = -4
|
|
167
|
+
let code = 0, size = minCodeSize + 1, pos = 0, pixelPos = -4;
|
|
174
168
|
const dic = [[0]];
|
|
175
|
-
|
|
169
|
+
for (;;) {
|
|
176
170
|
const last = code;
|
|
177
171
|
code = readBits(pos, size);
|
|
178
172
|
pos += size;
|
|
@@ -185,7 +179,6 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
185
179
|
}
|
|
186
180
|
else {
|
|
187
181
|
if (code === clearCode + 1) {
|
|
188
|
-
exit = true;
|
|
189
182
|
break;
|
|
190
183
|
}
|
|
191
184
|
if (code >= dic.length) {
|
|
@@ -196,7 +189,8 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
196
189
|
}
|
|
197
190
|
for (const item of dic[code]) {
|
|
198
191
|
const { r, g, b, a } = getColor(item);
|
|
199
|
-
image.data.set([r, g, b, a],
|
|
192
|
+
image.data.set([r, g, b, a], pixelPos);
|
|
193
|
+
pixelPos += 4;
|
|
200
194
|
}
|
|
201
195
|
if (dic.length >= 1 << size && size < 0xc) {
|
|
202
196
|
size++;
|
|
@@ -210,12 +204,12 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
210
204
|
}
|
|
211
205
|
async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback) {
|
|
212
206
|
switch (byteStream.nextByte()) {
|
|
213
|
-
case
|
|
207
|
+
case GIFDataHeaders.EndOfFile:
|
|
214
208
|
return true;
|
|
215
|
-
case
|
|
209
|
+
case GIFDataHeaders.Image:
|
|
216
210
|
await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback);
|
|
217
211
|
break;
|
|
218
|
-
case
|
|
212
|
+
case GIFDataHeaders.Extension:
|
|
219
213
|
parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
|
|
220
214
|
break;
|
|
221
215
|
default:
|
|
@@ -223,7 +217,7 @@ async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTranspare
|
|
|
223
217
|
}
|
|
224
218
|
return false;
|
|
225
219
|
}
|
|
226
|
-
function getGIFLoopAmount(gif) {
|
|
220
|
+
export function getGIFLoopAmount(gif) {
|
|
227
221
|
for (const extension of gif.applicationExtensions) {
|
|
228
222
|
if (extension.identifier + extension.authenticationCode !== "NETSCAPE2.0") {
|
|
229
223
|
continue;
|
|
@@ -232,9 +226,8 @@ function getGIFLoopAmount(gif) {
|
|
|
232
226
|
}
|
|
233
227
|
return NaN;
|
|
234
228
|
}
|
|
235
|
-
async function decodeGIF(gifURL, progressCallback, avgAlpha) {
|
|
236
|
-
|
|
237
|
-
avgAlpha = false;
|
|
229
|
+
export async function decodeGIF(gifURL, progressCallback, avgAlpha) {
|
|
230
|
+
avgAlpha ??= false;
|
|
238
231
|
const res = await fetch(gifURL);
|
|
239
232
|
if (!res.ok && res.status === 404) {
|
|
240
233
|
throw new EvalError("file not found");
|
|
@@ -252,7 +245,7 @@ async function decodeGIF(gifURL, progressCallback, avgAlpha) {
|
|
|
252
245
|
backgroundImage: new ImageData(1, 1, { colorSpace: "srgb" }),
|
|
253
246
|
comments: [],
|
|
254
247
|
applicationExtensions: [],
|
|
255
|
-
}, byteStream = new
|
|
248
|
+
}, byteStream = new ByteStream(new Uint8ClampedArray(buffer));
|
|
256
249
|
if (byteStream.getString(6) !== "GIF89a") {
|
|
257
250
|
throw new Error("not a supported GIF file");
|
|
258
251
|
}
|
|
@@ -310,7 +303,7 @@ async function decodeGIF(gifURL, progressCallback, avgAlpha) {
|
|
|
310
303
|
top: 0,
|
|
311
304
|
width: 0,
|
|
312
305
|
height: 0,
|
|
313
|
-
disposalMethod:
|
|
306
|
+
disposalMethod: DisposalMethod.Replace,
|
|
314
307
|
image: new ImageData(1, 1, { colorSpace: "srgb" }),
|
|
315
308
|
plainTextData: null,
|
|
316
309
|
userInputDelayFlag: false,
|
|
@@ -337,12 +330,12 @@ async function decodeGIF(gifURL, progressCallback, avgAlpha) {
|
|
|
337
330
|
}
|
|
338
331
|
catch (error) {
|
|
339
332
|
if (error instanceof EvalError) {
|
|
340
|
-
throw new Error(`error while parsing frame ${frameIndex} "${error.message}"`);
|
|
333
|
+
throw new Error(`error while parsing frame ${frameIndex.toString()} "${error.message}"`);
|
|
341
334
|
}
|
|
342
335
|
throw error;
|
|
343
336
|
}
|
|
344
337
|
}
|
|
345
|
-
function drawGif(data) {
|
|
338
|
+
export function drawGif(data) {
|
|
346
339
|
const { context, radius, particle, delta } = data, image = particle.image;
|
|
347
340
|
if (!image?.gifData || !image.gif) {
|
|
348
341
|
return;
|
|
@@ -354,33 +347,29 @@ function drawGif(data) {
|
|
|
354
347
|
offscreenContext.imageSmoothingQuality = "low";
|
|
355
348
|
offscreenContext.imageSmoothingEnabled = false;
|
|
356
349
|
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
357
|
-
|
|
358
|
-
particle.gifLoopCount = image.gifLoopCount ?? defaultLoopCount;
|
|
359
|
-
}
|
|
350
|
+
particle.gifLoopCount ??= image.gifLoopCount ?? defaultLoopCount;
|
|
360
351
|
let frameIndex = particle.gifFrame ?? defaultFrame;
|
|
361
352
|
const pos = { x: -image.gifData.width * half, y: -image.gifData.height * half }, frame = image.gifData.frames[frameIndex];
|
|
362
|
-
|
|
363
|
-
particle.gifTime = initialTime;
|
|
364
|
-
}
|
|
353
|
+
particle.gifTime ??= initialTime;
|
|
365
354
|
if (!frame.bitmap) {
|
|
366
355
|
return;
|
|
367
356
|
}
|
|
368
357
|
context.scale(radius / image.gifData.width, radius / image.gifData.height);
|
|
369
358
|
switch (frame.disposalMethod) {
|
|
370
|
-
case
|
|
371
|
-
case
|
|
372
|
-
case
|
|
373
|
-
case
|
|
374
|
-
case
|
|
359
|
+
case DisposalMethod.UndefinedA:
|
|
360
|
+
case DisposalMethod.UndefinedB:
|
|
361
|
+
case DisposalMethod.UndefinedC:
|
|
362
|
+
case DisposalMethod.UndefinedD:
|
|
363
|
+
case DisposalMethod.Replace:
|
|
375
364
|
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
376
365
|
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
377
366
|
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
378
367
|
break;
|
|
379
|
-
case
|
|
368
|
+
case DisposalMethod.Combine:
|
|
380
369
|
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
381
370
|
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
382
371
|
break;
|
|
383
|
-
case
|
|
372
|
+
case DisposalMethod.RestoreBackground:
|
|
384
373
|
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
385
374
|
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
386
375
|
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
@@ -391,7 +380,7 @@ function drawGif(data) {
|
|
|
391
380
|
offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
|
|
392
381
|
}
|
|
393
382
|
break;
|
|
394
|
-
case
|
|
383
|
+
case DisposalMethod.RestorePrevious:
|
|
395
384
|
{
|
|
396
385
|
const previousImageData = offscreenContext.getImageData(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
397
386
|
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
@@ -415,15 +404,15 @@ function drawGif(data) {
|
|
|
415
404
|
}
|
|
416
405
|
context.scale(image.gifData.width / radius, image.gifData.height / radius);
|
|
417
406
|
}
|
|
418
|
-
async function loadGifImage(image) {
|
|
407
|
+
export async function loadGifImage(image) {
|
|
419
408
|
if (image.type !== "gif") {
|
|
420
|
-
await
|
|
409
|
+
await loadImage(image);
|
|
421
410
|
return;
|
|
422
411
|
}
|
|
423
412
|
image.loading = true;
|
|
424
413
|
try {
|
|
425
414
|
image.gifData = await decodeGIF(image.source);
|
|
426
|
-
image.gifLoopCount = getGIFLoopAmount(image.gifData)
|
|
415
|
+
image.gifLoopCount = getGIFLoopAmount(image.gifData);
|
|
427
416
|
if (!image.gifLoopCount) {
|
|
428
417
|
image.gifLoopCount = Infinity;
|
|
429
418
|
}
|
package/cjs/IImageShape.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/cjs/ImageDrawer.js
CHANGED
|
@@ -1,30 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.ImageDrawer = void 0;
|
|
4
|
-
const engine_1 = require("@tsparticles/engine");
|
|
5
|
-
const Utils_js_1 = require("./Utils.js");
|
|
6
|
-
const Utils_js_2 = require("./GifUtils/Utils.js");
|
|
1
|
+
import { replaceImageColor } from "./Utils.js";
|
|
2
|
+
import { drawGif } from "./GifUtils/Utils.js";
|
|
7
3
|
const double = 2, defaultAlpha = 1, sides = 12, defaultRatio = 1;
|
|
8
|
-
class ImageDrawer {
|
|
4
|
+
export class ImageDrawer {
|
|
9
5
|
constructor(engine) {
|
|
10
6
|
this.validTypes = ["image", "images"];
|
|
11
7
|
this.loadImageShape = async (imageShape) => {
|
|
12
8
|
if (!this._engine.loadImage) {
|
|
13
|
-
throw new Error(
|
|
9
|
+
throw new Error(`Image shape not initialized`);
|
|
14
10
|
}
|
|
15
11
|
await this._engine.loadImage({
|
|
16
12
|
gif: imageShape.gif,
|
|
17
13
|
name: imageShape.name,
|
|
18
|
-
replaceColor: imageShape.replaceColor
|
|
14
|
+
replaceColor: imageShape.replaceColor,
|
|
19
15
|
src: imageShape.src,
|
|
20
16
|
});
|
|
21
17
|
};
|
|
22
18
|
this._engine = engine;
|
|
23
19
|
}
|
|
24
20
|
addImage(image) {
|
|
25
|
-
|
|
26
|
-
this._engine.images = [];
|
|
27
|
-
}
|
|
21
|
+
this._engine.images ??= [];
|
|
28
22
|
this._engine.images.push(image);
|
|
29
23
|
}
|
|
30
24
|
draw(data) {
|
|
@@ -34,7 +28,7 @@ class ImageDrawer {
|
|
|
34
28
|
}
|
|
35
29
|
context.globalAlpha = opacity;
|
|
36
30
|
if (image.gif && image.gifData) {
|
|
37
|
-
|
|
31
|
+
drawGif(data);
|
|
38
32
|
}
|
|
39
33
|
else if (element) {
|
|
40
34
|
const ratio = image.ratio, pos = {
|
|
@@ -61,9 +55,7 @@ class ImageDrawer {
|
|
|
61
55
|
if (particle.shape !== "image" && particle.shape !== "images") {
|
|
62
56
|
return;
|
|
63
57
|
}
|
|
64
|
-
|
|
65
|
-
this._engine.images = [];
|
|
66
|
-
}
|
|
58
|
+
this._engine.images ??= [];
|
|
67
59
|
const imageData = particle.shapeData;
|
|
68
60
|
if (!imageData) {
|
|
69
61
|
return;
|
|
@@ -79,9 +71,7 @@ class ImageDrawer {
|
|
|
79
71
|
if (particle.shape !== "image" && particle.shape !== "images") {
|
|
80
72
|
return;
|
|
81
73
|
}
|
|
82
|
-
|
|
83
|
-
this._engine.images = [];
|
|
84
|
-
}
|
|
74
|
+
this._engine.images ??= [];
|
|
85
75
|
const images = this._engine.images, imageData = particle.shapeData;
|
|
86
76
|
if (!imageData) {
|
|
87
77
|
return;
|
|
@@ -90,7 +80,7 @@ class ImageDrawer {
|
|
|
90
80
|
if (!image) {
|
|
91
81
|
return;
|
|
92
82
|
}
|
|
93
|
-
const replaceColor = imageData.replaceColor
|
|
83
|
+
const replaceColor = imageData.replaceColor;
|
|
94
84
|
if (image.loading) {
|
|
95
85
|
setTimeout(() => {
|
|
96
86
|
this.particleInit(container, particle);
|
|
@@ -100,7 +90,7 @@ class ImageDrawer {
|
|
|
100
90
|
void (async () => {
|
|
101
91
|
let imageRes;
|
|
102
92
|
if (image.svgData && color) {
|
|
103
|
-
imageRes = await
|
|
93
|
+
imageRes = await replaceImageColor(image, imageData, color, particle, container.hdr);
|
|
104
94
|
}
|
|
105
95
|
else {
|
|
106
96
|
imageRes = {
|
|
@@ -132,4 +122,3 @@ class ImageDrawer {
|
|
|
132
122
|
})();
|
|
133
123
|
}
|
|
134
124
|
}
|
|
135
|
-
exports.ImageDrawer = ImageDrawer;
|
package/cjs/ImagePreloader.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const Preload_js_1 = require("./Options/Classes/Preload.js");
|
|
5
|
-
class ImagePreloaderPlugin {
|
|
6
|
-
constructor(engine) {
|
|
1
|
+
import { Preload } from "./Options/Classes/Preload.js";
|
|
2
|
+
export class ImagePreloaderPlugin {
|
|
3
|
+
constructor() {
|
|
7
4
|
this.id = "imagePreloader";
|
|
8
|
-
this._engine = engine;
|
|
9
5
|
}
|
|
10
6
|
async getPlugin() {
|
|
11
7
|
await Promise.resolve();
|
|
@@ -15,9 +11,7 @@ class ImagePreloaderPlugin {
|
|
|
15
11
|
if (!source?.preload) {
|
|
16
12
|
return;
|
|
17
13
|
}
|
|
18
|
-
|
|
19
|
-
options.preload = [];
|
|
20
|
-
}
|
|
14
|
+
options.preload ??= [];
|
|
21
15
|
const preloadOptions = options.preload;
|
|
22
16
|
for (const item of source.preload) {
|
|
23
17
|
const existing = preloadOptions.find(t => t.name === item.name || t.src === item.src);
|
|
@@ -25,7 +19,7 @@ class ImagePreloaderPlugin {
|
|
|
25
19
|
existing.load(item);
|
|
26
20
|
}
|
|
27
21
|
else {
|
|
28
|
-
const preload = new
|
|
22
|
+
const preload = new Preload();
|
|
29
23
|
preload.load(item);
|
|
30
24
|
preloadOptions.push(preload);
|
|
31
25
|
}
|
|
@@ -35,4 +29,3 @@ class ImagePreloaderPlugin {
|
|
|
35
29
|
return true;
|
|
36
30
|
}
|
|
37
31
|
}
|
|
38
|
-
exports.ImagePreloaderPlugin = ImagePreloaderPlugin;
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.Preload = void 0;
|
|
4
|
-
const engine_1 = require("@tsparticles/engine");
|
|
5
|
-
class Preload {
|
|
1
|
+
import { isNull } from "@tsparticles/engine";
|
|
2
|
+
export class Preload {
|
|
6
3
|
constructor() {
|
|
7
4
|
this.src = "";
|
|
8
5
|
this.gif = false;
|
|
9
6
|
}
|
|
10
7
|
load(data) {
|
|
11
|
-
if (
|
|
8
|
+
if (isNull(data)) {
|
|
12
9
|
return;
|
|
13
10
|
}
|
|
14
11
|
if (data.gif !== undefined) {
|
|
@@ -31,4 +28,3 @@ class Preload {
|
|
|
31
28
|
}
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
|
-
exports.Preload = Preload;
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/cjs/Utils.js
CHANGED
|
@@ -1,24 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadImage = loadImage;
|
|
4
|
-
exports.downloadSvgImage = downloadSvgImage;
|
|
5
|
-
exports.replaceImageColor = replaceImageColor;
|
|
6
|
-
const engine_1 = require("@tsparticles/engine");
|
|
1
|
+
import { getLogger, getStyleFromHsl } from "@tsparticles/engine";
|
|
7
2
|
const stringStart = 0, defaultOpacity = 1;
|
|
8
3
|
const currentColorRegex = /(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;
|
|
9
|
-
function replaceColorSvg(imageShape, color, opacity) {
|
|
4
|
+
function replaceColorSvg(imageShape, color, opacity, hdr = false) {
|
|
10
5
|
const { svgData } = imageShape;
|
|
11
6
|
if (!svgData) {
|
|
12
7
|
return "";
|
|
13
8
|
}
|
|
14
|
-
const colorStyle =
|
|
9
|
+
const colorStyle = getStyleFromHsl(color, hdr, opacity);
|
|
15
10
|
if (svgData.includes("fill")) {
|
|
16
11
|
return svgData.replace(currentColorRegex, () => colorStyle);
|
|
17
12
|
}
|
|
18
13
|
const preFillIndex = svgData.indexOf(">");
|
|
19
14
|
return `${svgData.substring(stringStart, preFillIndex)} fill="${colorStyle}"${svgData.substring(preFillIndex)}`;
|
|
20
15
|
}
|
|
21
|
-
async function loadImage(image) {
|
|
16
|
+
export async function loadImage(image) {
|
|
22
17
|
return new Promise((resolve) => {
|
|
23
18
|
image.loading = true;
|
|
24
19
|
const img = new Image();
|
|
@@ -31,13 +26,13 @@ async function loadImage(image) {
|
|
|
31
26
|
image.element = undefined;
|
|
32
27
|
image.error = true;
|
|
33
28
|
image.loading = false;
|
|
34
|
-
|
|
29
|
+
getLogger().error(`Error loading image: ${image.source}`);
|
|
35
30
|
resolve();
|
|
36
31
|
});
|
|
37
32
|
img.src = image.source;
|
|
38
33
|
});
|
|
39
34
|
}
|
|
40
|
-
async function downloadSvgImage(image) {
|
|
35
|
+
export async function downloadSvgImage(image) {
|
|
41
36
|
if (image.type !== "svg") {
|
|
42
37
|
await loadImage(image);
|
|
43
38
|
return;
|
|
@@ -45,7 +40,7 @@ async function downloadSvgImage(image) {
|
|
|
45
40
|
image.loading = true;
|
|
46
41
|
const response = await fetch(image.source);
|
|
47
42
|
if (!response.ok) {
|
|
48
|
-
|
|
43
|
+
getLogger().error("Image not found");
|
|
49
44
|
image.error = true;
|
|
50
45
|
}
|
|
51
46
|
else {
|
|
@@ -53,8 +48,8 @@ async function downloadSvgImage(image) {
|
|
|
53
48
|
}
|
|
54
49
|
image.loading = false;
|
|
55
50
|
}
|
|
56
|
-
function replaceImageColor(image, imageData, color, particle) {
|
|
57
|
-
const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? defaultOpacity), imageRes = {
|
|
51
|
+
export function replaceImageColor(image, imageData, color, particle, hdr = false) {
|
|
52
|
+
const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? defaultOpacity, hdr), imageRes = {
|
|
58
53
|
color,
|
|
59
54
|
gif: imageData.gif,
|
|
60
55
|
data: {
|
|
@@ -67,15 +62,15 @@ function replaceImageColor(image, imageData, color, particle) {
|
|
|
67
62
|
source: imageData.src,
|
|
68
63
|
};
|
|
69
64
|
return new Promise(resolve => {
|
|
70
|
-
const svg = new Blob([svgColoredData], { type: "image/svg+xml" }),
|
|
65
|
+
const svg = new Blob([svgColoredData], { type: "image/svg+xml" }), url = URL.createObjectURL(svg), img = new Image();
|
|
71
66
|
img.addEventListener("load", () => {
|
|
72
67
|
imageRes.loaded = true;
|
|
73
68
|
imageRes.element = img;
|
|
74
69
|
resolve(imageRes);
|
|
75
|
-
|
|
70
|
+
URL.revokeObjectURL(url);
|
|
76
71
|
});
|
|
77
72
|
const errorHandler = async () => {
|
|
78
|
-
|
|
73
|
+
URL.revokeObjectURL(url);
|
|
79
74
|
const img2 = {
|
|
80
75
|
...image,
|
|
81
76
|
error: false,
|
package/cjs/index.js
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadImageShape = loadImageShape;
|
|
4
|
-
const Utils_js_1 = require("./Utils.js");
|
|
5
|
-
const ImageDrawer_js_1 = require("./ImageDrawer.js");
|
|
6
|
-
const ImagePreloader_js_1 = require("./ImagePreloader.js");
|
|
7
|
-
const engine_1 = require("@tsparticles/engine");
|
|
8
|
-
const Utils_js_2 = require("./GifUtils/Utils.js");
|
|
9
1
|
const extLength = 3;
|
|
10
2
|
function addLoadImageToEngine(engine) {
|
|
11
3
|
if (engine.loadImage) {
|
|
@@ -13,17 +5,15 @@ function addLoadImageToEngine(engine) {
|
|
|
13
5
|
}
|
|
14
6
|
engine.loadImage = async (data) => {
|
|
15
7
|
if (!data.name && !data.src) {
|
|
16
|
-
throw new Error(
|
|
8
|
+
throw new Error("No image source provided");
|
|
17
9
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
if (engine.images.find((t) => t.name === data.name || t.source === data.src)) {
|
|
10
|
+
engine.images ??= [];
|
|
11
|
+
if (engine.images.some((t) => t.name === data.name || t.source === data.src)) {
|
|
22
12
|
return;
|
|
23
13
|
}
|
|
24
14
|
try {
|
|
25
15
|
const image = {
|
|
26
|
-
gif: data.gif
|
|
16
|
+
gif: data.gif,
|
|
27
17
|
name: data.name ?? data.src,
|
|
28
18
|
source: data.src,
|
|
29
19
|
type: data.src.substring(data.src.length - extLength),
|
|
@@ -35,22 +25,31 @@ function addLoadImageToEngine(engine) {
|
|
|
35
25
|
engine.images.push(image);
|
|
36
26
|
let imageFunc;
|
|
37
27
|
if (data.gif) {
|
|
38
|
-
|
|
28
|
+
const { loadGifImage } = await import("./GifUtils/Utils.js");
|
|
29
|
+
imageFunc = loadGifImage;
|
|
30
|
+
}
|
|
31
|
+
else if (data.replaceColor) {
|
|
32
|
+
const { downloadSvgImage } = await import("./Utils.js");
|
|
33
|
+
imageFunc = downloadSvgImage;
|
|
39
34
|
}
|
|
40
35
|
else {
|
|
41
|
-
|
|
36
|
+
const { loadImage } = await import("./Utils.js");
|
|
37
|
+
imageFunc = loadImage;
|
|
42
38
|
}
|
|
43
39
|
await imageFunc(image);
|
|
44
40
|
}
|
|
45
41
|
catch {
|
|
46
|
-
throw new Error(`${
|
|
42
|
+
throw new Error(`${data.name ?? data.src} not found`);
|
|
47
43
|
}
|
|
48
44
|
};
|
|
49
45
|
}
|
|
50
|
-
|
|
51
|
-
engine.checkVersion("
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
export function loadImageShape(engine) {
|
|
47
|
+
engine.checkVersion("4.0.0-alpha.1");
|
|
48
|
+
engine.register(async (e) => {
|
|
49
|
+
const { ImageDrawer } = await import("./ImageDrawer.js"), { ImagePreloaderPlugin } = await import("./ImagePreloader.js");
|
|
50
|
+
addLoadImageToEngine(e);
|
|
51
|
+
const preloader = new ImagePreloaderPlugin();
|
|
52
|
+
e.addPlugin(preloader);
|
|
53
|
+
e.addShape(new ImageDrawer(e));
|
|
54
|
+
});
|
|
56
55
|
}
|
package/cjs/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|