@tsparticles/shape-image 3.1.0 → 3.2.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/21.min.js +2 -0
- package/21.min.js.LICENSE.txt +1 -0
- package/618.min.js +2 -0
- package/618.min.js.LICENSE.txt +1 -0
- package/623.min.js +2 -0
- package/623.min.js.LICENSE.txt +1 -0
- package/browser/GifUtils/ByteStream.js +2 -1
- package/browser/GifUtils/Utils.js +96 -0
- package/browser/ImageDrawer.js +42 -113
- package/browser/ImagePreloader.js +2 -1
- package/browser/Utils.js +1 -20
- package/browser/index.js +3 -3
- package/cjs/GifUtils/ByteStream.js +2 -1
- package/cjs/GifUtils/Utils.js +122 -1
- package/cjs/ImageDrawer.js +64 -112
- package/cjs/ImagePreloader.js +2 -1
- package/cjs/Utils.js +2 -22
- package/cjs/index.js +28 -5
- package/dist_browser_GifUtils_Utils_js.js +50 -0
- package/dist_browser_ImageDrawer_js.js +30 -0
- package/dist_browser_ImagePreloader_js.js +40 -0
- package/esm/GifUtils/ByteStream.js +2 -1
- package/esm/GifUtils/Utils.js +96 -0
- package/esm/ImageDrawer.js +42 -113
- package/esm/ImagePreloader.js +2 -1
- package/esm/Utils.js +1 -20
- package/esm/index.js +3 -3
- package/package.json +2 -2
- package/report.html +3 -3
- package/tsparticles.shape.image.js +251 -910
- package/tsparticles.shape.image.min.js +1 -1
- package/tsparticles.shape.image.min.js.LICENSE.txt +1 -1
- package/types/GifUtils/Utils.d.ts +4 -0
- package/types/ImageDrawer.d.ts +4 -4
- package/types/ImagePreloader.d.ts +1 -1
- package/types/Utils.d.ts +0 -1
- package/umd/GifUtils/ByteStream.js +2 -1
- package/umd/GifUtils/Utils.js +123 -1
- package/umd/ImageDrawer.js +66 -113
- package/umd/ImagePreloader.js +2 -1
- package/umd/Utils.js +3 -23
- package/umd/index.js +30 -6
package/cjs/ImageDrawer.js
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.ImageDrawer = void 0;
|
|
4
27
|
const engine_1 = require("@tsparticles/engine");
|
|
5
|
-
const
|
|
6
|
-
const origin = {
|
|
7
|
-
x: 0,
|
|
8
|
-
y: 0,
|
|
9
|
-
}, defaultLoopCount = 0, defaultFrame = 0, half = 0.5, initialTime = 0, firstIndex = 0, double = 2, defaultAlpha = 1, sides = 12, defaultRatio = 1;
|
|
28
|
+
const double = 2, defaultAlpha = 1, sides = 12, defaultRatio = 1;
|
|
10
29
|
class ImageDrawer {
|
|
11
30
|
constructor(engine) {
|
|
12
31
|
this.loadImageShape = async (imageShape) => {
|
|
@@ -28,80 +47,15 @@ class ImageDrawer {
|
|
|
28
47
|
}
|
|
29
48
|
this._engine.images.push(image);
|
|
30
49
|
}
|
|
31
|
-
draw(data) {
|
|
32
|
-
const { context, radius, particle, opacity
|
|
50
|
+
async draw(data) {
|
|
51
|
+
const { context, radius, particle, opacity } = data, image = particle.image, element = image?.element;
|
|
33
52
|
if (!image) {
|
|
34
53
|
return;
|
|
35
54
|
}
|
|
36
55
|
context.globalAlpha = opacity;
|
|
37
56
|
if (image.gif && image.gifData) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
throw new Error("could not create offscreen canvas context");
|
|
41
|
-
}
|
|
42
|
-
offscreenContext.imageSmoothingQuality = "low";
|
|
43
|
-
offscreenContext.imageSmoothingEnabled = false;
|
|
44
|
-
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
45
|
-
if (particle.gifLoopCount === undefined) {
|
|
46
|
-
particle.gifLoopCount = image.gifLoopCount ?? defaultLoopCount;
|
|
47
|
-
}
|
|
48
|
-
let frameIndex = particle.gifFrame ?? defaultFrame;
|
|
49
|
-
const pos = { x: -image.gifData.width * half, y: -image.gifData.height * half }, frame = image.gifData.frames[frameIndex];
|
|
50
|
-
if (particle.gifTime === undefined) {
|
|
51
|
-
particle.gifTime = initialTime;
|
|
52
|
-
}
|
|
53
|
-
if (!frame.bitmap) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
context.scale(radius / image.gifData.width, radius / image.gifData.height);
|
|
57
|
-
switch (frame.disposalMethod) {
|
|
58
|
-
case 4:
|
|
59
|
-
case 5:
|
|
60
|
-
case 6:
|
|
61
|
-
case 7:
|
|
62
|
-
case 0:
|
|
63
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
64
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
65
|
-
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
66
|
-
break;
|
|
67
|
-
case 1:
|
|
68
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
69
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
70
|
-
break;
|
|
71
|
-
case 2:
|
|
72
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
73
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
74
|
-
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
75
|
-
if (!image.gifData.globalColorTable.length) {
|
|
76
|
-
offscreenContext.putImageData(image.gifData.frames[firstIndex].image, pos.x + frame.left, pos.y + frame.top);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
|
|
80
|
-
}
|
|
81
|
-
break;
|
|
82
|
-
case 3:
|
|
83
|
-
{
|
|
84
|
-
const previousImageData = offscreenContext.getImageData(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
85
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
86
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
87
|
-
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
88
|
-
offscreenContext.putImageData(previousImageData, origin.x, origin.y);
|
|
89
|
-
}
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
particle.gifTime += delta.value;
|
|
93
|
-
if (particle.gifTime > frame.delayTime) {
|
|
94
|
-
particle.gifTime -= frame.delayTime;
|
|
95
|
-
if (++frameIndex >= image.gifData.frames.length) {
|
|
96
|
-
if (--particle.gifLoopCount <= defaultLoopCount) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
frameIndex = firstIndex;
|
|
100
|
-
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
101
|
-
}
|
|
102
|
-
particle.gifFrame = frameIndex;
|
|
103
|
-
}
|
|
104
|
-
context.scale(image.gifData.width / radius, image.gifData.height / radius);
|
|
57
|
+
const { drawGif } = await Promise.resolve().then(() => __importStar(require("./GifUtils/Utils.js")));
|
|
58
|
+
drawGif(data);
|
|
105
59
|
}
|
|
106
60
|
else if (element) {
|
|
107
61
|
const ratio = image.ratio, pos = {
|
|
@@ -124,7 +78,7 @@ class ImageDrawer {
|
|
|
124
78
|
await this._engine.loadImage(imageData);
|
|
125
79
|
}
|
|
126
80
|
}
|
|
127
|
-
loadShape(particle) {
|
|
81
|
+
async loadShape(particle) {
|
|
128
82
|
if (particle.shape !== "image" && particle.shape !== "images") {
|
|
129
83
|
return;
|
|
130
84
|
}
|
|
@@ -137,12 +91,11 @@ class ImageDrawer {
|
|
|
137
91
|
}
|
|
138
92
|
const image = this._engine.images.find((t) => t.name === imageData.name || t.source === imageData.src);
|
|
139
93
|
if (!image) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
});
|
|
94
|
+
await this.loadImageShape(imageData);
|
|
95
|
+
await this.loadShape(particle);
|
|
143
96
|
}
|
|
144
97
|
}
|
|
145
|
-
particleInit(container, particle) {
|
|
98
|
+
async particleInit(container, particle) {
|
|
146
99
|
if (particle.shape !== "image" && particle.shape !== "images") {
|
|
147
100
|
return;
|
|
148
101
|
}
|
|
@@ -160,43 +113,42 @@ class ImageDrawer {
|
|
|
160
113
|
const replaceColor = imageData.replaceColor ?? image.replaceColor;
|
|
161
114
|
if (image.loading) {
|
|
162
115
|
setTimeout(() => {
|
|
163
|
-
this.particleInit(container, particle);
|
|
116
|
+
void this.particleInit(container, particle);
|
|
164
117
|
});
|
|
165
118
|
return;
|
|
166
119
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
if (!imageRes.ratio) {
|
|
189
|
-
imageRes.ratio = 1;
|
|
190
|
-
}
|
|
191
|
-
const fill = imageData.fill ?? particle.shapeFill, close = imageData.close ?? particle.shapeClose, imageShape = {
|
|
192
|
-
image: imageRes,
|
|
193
|
-
fill,
|
|
194
|
-
close,
|
|
120
|
+
let imageRes;
|
|
121
|
+
if (image.svgData && color) {
|
|
122
|
+
const { replaceImageColor } = await Promise.resolve().then(() => __importStar(require("./Utils.js")));
|
|
123
|
+
imageRes = await replaceImageColor(image, imageData, color, particle);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
imageRes = {
|
|
127
|
+
color,
|
|
128
|
+
data: image,
|
|
129
|
+
element: image.element,
|
|
130
|
+
gif: image.gif,
|
|
131
|
+
gifData: image.gifData,
|
|
132
|
+
gifLoopCount: image.gifLoopCount,
|
|
133
|
+
loaded: true,
|
|
134
|
+
ratio: imageData.width && imageData.height
|
|
135
|
+
? imageData.width / imageData.height
|
|
136
|
+
: image.ratio ?? defaultRatio,
|
|
137
|
+
replaceColor: replaceColor,
|
|
138
|
+
source: imageData.src,
|
|
195
139
|
};
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
140
|
+
}
|
|
141
|
+
if (!imageRes.ratio) {
|
|
142
|
+
imageRes.ratio = 1;
|
|
143
|
+
}
|
|
144
|
+
const fill = imageData.fill ?? particle.shapeFill, close = imageData.close ?? particle.shapeClose, imageShape = {
|
|
145
|
+
image: imageRes,
|
|
146
|
+
fill,
|
|
147
|
+
close,
|
|
148
|
+
};
|
|
149
|
+
particle.image = imageShape.image;
|
|
150
|
+
particle.shapeFill = imageShape.fill;
|
|
151
|
+
particle.shapeClose = imageShape.close;
|
|
200
152
|
}
|
|
201
153
|
}
|
|
202
154
|
exports.ImageDrawer = ImageDrawer;
|
package/cjs/ImagePreloader.js
CHANGED
package/cjs/Utils.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.replaceImageColor = exports.downloadSvgImage = exports.
|
|
3
|
+
exports.replaceImageColor = exports.downloadSvgImage = exports.loadImage = void 0;
|
|
4
4
|
const engine_1 = require("@tsparticles/engine");
|
|
5
|
-
const
|
|
6
|
-
const stringStart = 0, defaultLoopCount = 0, defaultOpacity = 1;
|
|
5
|
+
const stringStart = 0, defaultOpacity = 1;
|
|
7
6
|
const currentColorRegex = /(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;
|
|
8
7
|
function replaceColorSvg(imageShape, color, opacity) {
|
|
9
8
|
const { svgData } = imageShape;
|
|
@@ -37,25 +36,6 @@ async function loadImage(image) {
|
|
|
37
36
|
});
|
|
38
37
|
}
|
|
39
38
|
exports.loadImage = loadImage;
|
|
40
|
-
async function loadGifImage(image) {
|
|
41
|
-
if (image.type !== "gif") {
|
|
42
|
-
await loadImage(image);
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
image.loading = true;
|
|
46
|
-
try {
|
|
47
|
-
image.gifData = await (0, Utils_js_1.decodeGIF)(image.source);
|
|
48
|
-
image.gifLoopCount = (0, Utils_js_1.getGIFLoopAmount)(image.gifData) ?? defaultLoopCount;
|
|
49
|
-
if (!image.gifLoopCount) {
|
|
50
|
-
image.gifLoopCount = Infinity;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
image.error = true;
|
|
55
|
-
}
|
|
56
|
-
image.loading = false;
|
|
57
|
-
}
|
|
58
|
-
exports.loadGifImage = loadGifImage;
|
|
59
39
|
async function downloadSvgImage(image) {
|
|
60
40
|
if (image.type !== "svg") {
|
|
61
41
|
await loadImage(image);
|
package/cjs/index.js
CHANGED
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.loadImageShape = void 0;
|
|
4
27
|
const Utils_js_1 = require("./Utils.js");
|
|
5
|
-
const ImageDrawer_js_1 = require("./ImageDrawer.js");
|
|
6
|
-
const ImagePreloader_js_1 = require("./ImagePreloader.js");
|
|
7
28
|
const engine_1 = require("@tsparticles/engine");
|
|
8
29
|
const extLength = 3;
|
|
9
30
|
function addLoadImageToEngine(engine) {
|
|
@@ -34,7 +55,8 @@ function addLoadImageToEngine(engine) {
|
|
|
34
55
|
engine.images.push(image);
|
|
35
56
|
let imageFunc;
|
|
36
57
|
if (data.gif) {
|
|
37
|
-
|
|
58
|
+
const { loadGifImage } = await Promise.resolve().then(() => __importStar(require("./GifUtils/Utils.js")));
|
|
59
|
+
imageFunc = loadGifImage;
|
|
38
60
|
}
|
|
39
61
|
else {
|
|
40
62
|
imageFunc = data.replaceColor ? Utils_js_1.downloadSvgImage : Utils_js_1.loadImage;
|
|
@@ -48,8 +70,9 @@ function addLoadImageToEngine(engine) {
|
|
|
48
70
|
}
|
|
49
71
|
async function loadImageShape(engine, refresh = true) {
|
|
50
72
|
addLoadImageToEngine(engine);
|
|
51
|
-
const
|
|
73
|
+
const { ImagePreloaderPlugin } = await Promise.resolve().then(() => __importStar(require("./ImagePreloader.js"))), { ImageDrawer } = await Promise.resolve().then(() => __importStar(require("./ImageDrawer.js")));
|
|
74
|
+
const preloader = new ImagePreloaderPlugin(engine);
|
|
52
75
|
await engine.addPlugin(preloader, refresh);
|
|
53
|
-
await engine.addShape(["image", "images"], new
|
|
76
|
+
await engine.addShape(["image", "images"], new ImageDrawer(engine), refresh);
|
|
54
77
|
}
|
|
55
78
|
exports.loadImageShape = loadImageShape;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Author : Matteo Bruni
|
|
3
|
+
* MIT license: https://opensource.org/licenses/MIT
|
|
4
|
+
* Demo / Generator : https://particles.js.org/
|
|
5
|
+
* GitHub : https://www.github.com/matteobruni/tsparticles
|
|
6
|
+
* How to use? : Check the GitHub README
|
|
7
|
+
* v3.2.0
|
|
8
|
+
*/
|
|
9
|
+
"use strict";
|
|
10
|
+
/*
|
|
11
|
+
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
|
12
|
+
* This devtool is neither made for production nor for readable output files.
|
|
13
|
+
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
|
14
|
+
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
15
|
+
* or disable the default devtool with "devtool: false".
|
|
16
|
+
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
17
|
+
*/
|
|
18
|
+
(this["webpackChunk_tsparticles_shape_image"] = this["webpackChunk_tsparticles_shape_image"] || []).push([["dist_browser_GifUtils_Utils_js"],{
|
|
19
|
+
|
|
20
|
+
/***/ "./dist/browser/GifUtils/ByteStream.js":
|
|
21
|
+
/*!*********************************************!*\
|
|
22
|
+
!*** ./dist/browser/GifUtils/ByteStream.js ***!
|
|
23
|
+
\*********************************************/
|
|
24
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
25
|
+
|
|
26
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ByteStream: () => (/* binding */ ByteStream)\n/* harmony export */ });\nclass ByteStream {\n constructor(bytes) {\n this.pos = 0;\n this.data = new Uint8ClampedArray(bytes);\n }\n getString(count) {\n const slice = this.data.slice(this.pos, this.pos + count);\n this.pos += slice.length;\n return slice.reduce((acc, curr) => acc + String.fromCharCode(curr), \"\");\n }\n nextByte() {\n return this.data[this.pos++];\n }\n nextTwoBytes() {\n const increment = 2,\n previous = 1,\n shift = 8;\n this.pos += increment;\n return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);\n }\n readSubBlocks() {\n let blockString = \"\",\n size = 0;\n const minCount = 0,\n emptySize = 0;\n do {\n size = this.data[this.pos++];\n for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {}\n } while (size !== emptySize);\n return blockString;\n }\n readSubBlocksBin() {\n let size = this.data[this.pos],\n len = 0;\n const emptySize = 0,\n increment = 1;\n for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {\n len += size;\n }\n const blockData = new Uint8Array(len);\n size = this.data[this.pos++];\n for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {\n for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {}\n }\n return blockData;\n }\n skipSubBlocks() {\n for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {}\n this.pos++;\n }\n}\n\n//# sourceURL=webpack://@tsparticles/shape-image/./dist/browser/GifUtils/ByteStream.js?");
|
|
27
|
+
|
|
28
|
+
/***/ }),
|
|
29
|
+
|
|
30
|
+
/***/ "./dist/browser/GifUtils/Constants.js":
|
|
31
|
+
/*!********************************************!*\
|
|
32
|
+
!*** ./dist/browser/GifUtils/Constants.js ***!
|
|
33
|
+
\********************************************/
|
|
34
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
35
|
+
|
|
36
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ InterlaceOffsets: () => (/* binding */ InterlaceOffsets),\n/* harmony export */ InterlaceSteps: () => (/* binding */ InterlaceSteps)\n/* harmony export */ });\nconst InterlaceOffsets = [0, 4, 2, 1];\nconst InterlaceSteps = [8, 8, 4, 2];\n\n//# sourceURL=webpack://@tsparticles/shape-image/./dist/browser/GifUtils/Constants.js?");
|
|
37
|
+
|
|
38
|
+
/***/ }),
|
|
39
|
+
|
|
40
|
+
/***/ "./dist/browser/GifUtils/Utils.js":
|
|
41
|
+
/*!****************************************!*\
|
|
42
|
+
!*** ./dist/browser/GifUtils/Utils.js ***!
|
|
43
|
+
\****************************************/
|
|
44
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
45
|
+
|
|
46
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ decodeGIF: () => (/* binding */ decodeGIF),\n/* harmony export */ drawGif: () => (/* binding */ drawGif),\n/* harmony export */ getGIFLoopAmount: () => (/* binding */ getGIFLoopAmount),\n/* harmony export */ loadGifImage: () => (/* binding */ loadGifImage)\n/* harmony export */ });\n/* harmony import */ var _Constants_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Constants.js */ \"./dist/browser/GifUtils/Constants.js\");\n/* harmony import */ var _ByteStream_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ByteStream.js */ \"./dist/browser/GifUtils/ByteStream.js\");\n\n\nconst origin = {\n x: 0,\n y: 0\n },\n defaultFrame = 0,\n half = 0.5,\n initialTime = 0,\n firstIndex = 0,\n defaultLoopCount = 0;\nfunction parseColorTable(byteStream, count) {\n const colors = [];\n for (let i = 0; i < count; i++) {\n colors.push({\n r: byteStream.data[byteStream.pos],\n g: byteStream.data[byteStream.pos + 1],\n b: byteStream.data[byteStream.pos + 2]\n });\n byteStream.pos += 3;\n }\n return colors;\n}\nfunction parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {\n switch (byteStream.nextByte()) {\n case 249:\n {\n const frame = gif.frames[getFrameIndex(false)];\n byteStream.pos++;\n const packedByte = byteStream.nextByte();\n frame.GCreserved = (packedByte & 0xe0) >>> 5;\n frame.disposalMethod = (packedByte & 0x1c) >>> 2;\n frame.userInputDelayFlag = (packedByte & 2) === 2;\n const transparencyFlag = (packedByte & 1) === 1;\n frame.delayTime = byteStream.nextTwoBytes() * 0xa;\n const transparencyIndex = byteStream.nextByte();\n if (transparencyFlag) {\n getTransparencyIndex(transparencyIndex);\n }\n byteStream.pos++;\n break;\n }\n case 255:\n {\n byteStream.pos++;\n const applicationExtension = {\n identifier: byteStream.getString(8),\n authenticationCode: byteStream.getString(3),\n data: byteStream.readSubBlocksBin()\n };\n gif.applicationExtensions.push(applicationExtension);\n break;\n }\n case 254:\n {\n gif.comments.push([getFrameIndex(false), byteStream.readSubBlocks()]);\n break;\n }\n case 1:\n {\n if (gif.globalColorTable.length === 0) {\n throw new EvalError(\"plain text extension without global color table\");\n }\n byteStream.pos++;\n gif.frames[getFrameIndex(false)].plainTextData = {\n left: byteStream.nextTwoBytes(),\n top: byteStream.nextTwoBytes(),\n width: byteStream.nextTwoBytes(),\n height: byteStream.nextTwoBytes(),\n charSize: {\n width: byteStream.nextTwoBytes(),\n height: byteStream.nextTwoBytes()\n },\n foregroundColor: byteStream.nextByte(),\n backgroundColor: byteStream.nextByte(),\n text: byteStream.readSubBlocks()\n };\n break;\n }\n default:\n byteStream.skipSubBlocks();\n break;\n }\n}\nasync function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback) {\n const frame = gif.frames[getFrameIndex(true)];\n frame.left = byteStream.nextTwoBytes();\n frame.top = byteStream.nextTwoBytes();\n frame.width = byteStream.nextTwoBytes();\n frame.height = byteStream.nextTwoBytes();\n const packedByte = byteStream.nextByte(),\n localColorTableFlag = (packedByte & 0x80) === 0x80,\n interlacedFlag = (packedByte & 0x40) === 0x40;\n frame.sortFlag = (packedByte & 0x20) === 0x20;\n frame.reserved = (packedByte & 0x18) >>> 3;\n const localColorCount = 1 << (packedByte & 7) + 1;\n if (localColorTableFlag) {\n frame.localColorTable = parseColorTable(byteStream, localColorCount);\n }\n const getColor = index => {\n const {\n r,\n g,\n b\n } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];\n if (index !== getTransparencyIndex(null)) {\n return {\n r,\n g,\n b,\n a: 255\n };\n }\n return {\n r,\n g,\n b,\n a: avgAlpha ? ~~((r + g + b) / 3) : 0\n };\n };\n const image = (() => {\n try {\n return new ImageData(frame.width, frame.height, {\n colorSpace: \"srgb\"\n });\n } catch (error) {\n if (error instanceof DOMException && error.name === \"IndexSizeError\") {\n return null;\n }\n throw error;\n }\n })();\n if (image == null) {\n throw new EvalError(\"GIF frame size is to large\");\n }\n const minCodeSize = byteStream.nextByte(),\n imageData = byteStream.readSubBlocksBin(),\n clearCode = 1 << minCodeSize;\n const readBits = (pos, len) => {\n const bytePos = pos >>> 3,\n bitPos = pos & 7;\n return (imageData[bytePos] + (imageData[bytePos + 1] << 8) + (imageData[bytePos + 2] << 16) & (1 << len) - 1 << bitPos) >>> bitPos;\n };\n if (interlacedFlag) {\n for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {\n if (_Constants_js__WEBPACK_IMPORTED_MODULE_0__.InterlaceOffsets[pass] < frame.height) {\n let pixelPos = 0,\n lineIndex = 0,\n exit = false;\n while (!exit) {\n const last = code;\n code = readBits(pos, size);\n pos += size + 1;\n if (code === clearCode) {\n size = minCodeSize + 1;\n dic.length = clearCode + 2;\n for (let i = 0; i < dic.length; i++) {\n dic[i] = i < clearCode ? [i] : [];\n }\n } else {\n if (code >= dic.length) {\n dic.push(dic[last].concat(dic[last][0]));\n } else if (last !== clearCode) {\n dic.push(dic[last].concat(dic[code][0]));\n }\n for (const item of dic[code]) {\n const {\n r,\n g,\n b,\n a\n } = getColor(item);\n image.data.set([r, g, b, a], _Constants_js__WEBPACK_IMPORTED_MODULE_0__.InterlaceOffsets[pass] * frame.width + _Constants_js__WEBPACK_IMPORTED_MODULE_0__.InterlaceSteps[pass] * lineIndex + pixelPos % (frame.width * 4));\n pixelPos += 4;\n }\n if (dic.length === 1 << size && size < 0xc) {\n size++;\n }\n }\n if (pixelPos === frame.width * 4 * (lineIndex + 1)) {\n lineIndex++;\n if (_Constants_js__WEBPACK_IMPORTED_MODULE_0__.InterlaceOffsets[pass] + _Constants_js__WEBPACK_IMPORTED_MODULE_0__.InterlaceSteps[pass] * lineIndex >= frame.height) {\n exit = true;\n }\n }\n }\n }\n progressCallback?.(byteStream.pos / (byteStream.data.length - 1), getFrameIndex(false) + 1, image, {\n x: frame.left,\n y: frame.top\n }, {\n width: gif.width,\n height: gif.height\n });\n }\n frame.image = image;\n frame.bitmap = await createImageBitmap(image);\n } else {\n let code = 0,\n size = minCodeSize + 1,\n pos = 0,\n pixelPos = -4,\n exit = false;\n const dic = [[0]];\n while (!exit) {\n const last = code;\n code = readBits(pos, size);\n pos += size;\n if (code === clearCode) {\n size = minCodeSize + 1;\n dic.length = clearCode + 2;\n for (let i = 0; i < dic.length; i++) {\n dic[i] = i < clearCode ? [i] : [];\n }\n } else {\n if (code === clearCode + 1) {\n exit = true;\n break;\n }\n if (code >= dic.length) {\n dic.push(dic[last].concat(dic[last][0]));\n } else if (last !== clearCode) {\n dic.push(dic[last].concat(dic[code][0]));\n }\n for (const item of dic[code]) {\n const {\n r,\n g,\n b,\n a\n } = getColor(item);\n image.data.set([r, g, b, a], pixelPos += 4);\n }\n if (dic.length >= 1 << size && size < 0xc) {\n size++;\n }\n }\n }\n frame.image = image;\n frame.bitmap = await createImageBitmap(image);\n progressCallback?.((byteStream.pos + 1) / byteStream.data.length, getFrameIndex(false) + 1, frame.image, {\n x: frame.left,\n y: frame.top\n }, {\n width: gif.width,\n height: gif.height\n });\n }\n}\nasync function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback) {\n switch (byteStream.nextByte()) {\n case 59:\n return true;\n case 44:\n await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback);\n break;\n case 33:\n parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);\n break;\n default:\n throw new EvalError(\"undefined block found\");\n }\n return false;\n}\nfunction getGIFLoopAmount(gif) {\n for (const extension of gif.applicationExtensions) {\n if (extension.identifier + extension.authenticationCode !== \"NETSCAPE2.0\") {\n continue;\n }\n return extension.data[1] + (extension.data[2] << 8);\n }\n return NaN;\n}\nasync function decodeGIF(gifURL, progressCallback, avgAlpha) {\n if (!avgAlpha) avgAlpha = false;\n const res = await fetch(gifURL);\n if (!res.ok && res.status === 404) {\n throw new EvalError(\"file not found\");\n }\n const buffer = await res.arrayBuffer();\n const gif = {\n width: 0,\n height: 0,\n totalTime: 0,\n colorRes: 0,\n pixelAspectRatio: 0,\n frames: [],\n sortFlag: false,\n globalColorTable: [],\n backgroundImage: new ImageData(1, 1, {\n colorSpace: \"srgb\"\n }),\n comments: [],\n applicationExtensions: []\n },\n byteStream = new _ByteStream_js__WEBPACK_IMPORTED_MODULE_1__.ByteStream(new Uint8ClampedArray(buffer));\n if (byteStream.getString(6) !== \"GIF89a\") {\n throw new Error(\"not a supported GIF file\");\n }\n gif.width = byteStream.nextTwoBytes();\n gif.height = byteStream.nextTwoBytes();\n const packedByte = byteStream.nextByte(),\n globalColorTableFlag = (packedByte & 0x80) === 0x80;\n gif.colorRes = (packedByte & 0x70) >>> 4;\n gif.sortFlag = (packedByte & 8) === 8;\n const globalColorCount = 1 << (packedByte & 7) + 1,\n backgroundColorIndex = byteStream.nextByte();\n gif.pixelAspectRatio = byteStream.nextByte();\n if (gif.pixelAspectRatio !== 0) {\n gif.pixelAspectRatio = (gif.pixelAspectRatio + 0xf) / 0x40;\n }\n if (globalColorTableFlag) {\n gif.globalColorTable = parseColorTable(byteStream, globalColorCount);\n }\n const backgroundImage = (() => {\n try {\n return new ImageData(gif.width, gif.height, {\n colorSpace: \"srgb\"\n });\n } catch (error) {\n if (error instanceof DOMException && error.name === \"IndexSizeError\") {\n return null;\n }\n throw error;\n }\n })();\n if (backgroundImage == null) {\n throw new Error(\"GIF frame size is to large\");\n }\n const {\n r,\n g,\n b\n } = gif.globalColorTable[backgroundColorIndex];\n backgroundImage.data.set(globalColorTableFlag ? [r, g, b, 255] : [0, 0, 0, 0]);\n for (let i = 4; i < backgroundImage.data.length; i *= 2) {\n backgroundImage.data.copyWithin(i, 0, i);\n }\n gif.backgroundImage = backgroundImage;\n let frameIndex = -1,\n incrementFrameIndex = true,\n transparencyIndex = -1;\n const getframeIndex = increment => {\n if (increment) {\n incrementFrameIndex = true;\n }\n return frameIndex;\n };\n const getTransparencyIndex = newValue => {\n if (newValue != null) {\n transparencyIndex = newValue;\n }\n return transparencyIndex;\n };\n try {\n do {\n if (incrementFrameIndex) {\n gif.frames.push({\n left: 0,\n top: 0,\n width: 0,\n height: 0,\n disposalMethod: 0,\n image: new ImageData(1, 1, {\n colorSpace: \"srgb\"\n }),\n plainTextData: null,\n userInputDelayFlag: false,\n delayTime: 0,\n sortFlag: false,\n localColorTable: [],\n reserved: 0,\n GCreserved: 0\n });\n frameIndex++;\n transparencyIndex = -1;\n incrementFrameIndex = false;\n }\n } while (!(await parseBlock(byteStream, gif, avgAlpha, getframeIndex, getTransparencyIndex, progressCallback)));\n gif.frames.length--;\n for (const frame of gif.frames) {\n if (frame.userInputDelayFlag && frame.delayTime === 0) {\n gif.totalTime = Infinity;\n break;\n }\n gif.totalTime += frame.delayTime;\n }\n return gif;\n } catch (error) {\n if (error instanceof EvalError) {\n throw new Error(`error while parsing frame ${frameIndex} \"${error.message}\"`);\n }\n throw error;\n }\n}\nfunction drawGif(data) {\n const {\n context,\n radius,\n particle,\n delta\n } = data,\n image = particle.image;\n if (!image?.gifData || !image.gif) {\n return;\n }\n const offscreenCanvas = new OffscreenCanvas(image.gifData.width, image.gifData.height),\n offscreenContext = offscreenCanvas.getContext(\"2d\");\n if (!offscreenContext) {\n throw new Error(\"could not create offscreen canvas context\");\n }\n offscreenContext.imageSmoothingQuality = \"low\";\n offscreenContext.imageSmoothingEnabled = false;\n offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);\n if (particle.gifLoopCount === undefined) {\n particle.gifLoopCount = image.gifLoopCount ?? defaultLoopCount;\n }\n let frameIndex = particle.gifFrame ?? defaultFrame;\n const pos = {\n x: -image.gifData.width * half,\n y: -image.gifData.height * half\n },\n frame = image.gifData.frames[frameIndex];\n if (particle.gifTime === undefined) {\n particle.gifTime = initialTime;\n }\n if (!frame.bitmap) {\n return;\n }\n context.scale(radius / image.gifData.width, radius / image.gifData.height);\n switch (frame.disposalMethod) {\n case 4:\n case 5:\n case 6:\n case 7:\n case 0:\n offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);\n context.drawImage(offscreenCanvas, pos.x, pos.y);\n offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);\n break;\n case 1:\n offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);\n context.drawImage(offscreenCanvas, pos.x, pos.y);\n break;\n case 2:\n offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);\n context.drawImage(offscreenCanvas, pos.x, pos.y);\n offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);\n if (!image.gifData.globalColorTable.length) {\n offscreenContext.putImageData(image.gifData.frames[firstIndex].image, pos.x + frame.left, pos.y + frame.top);\n } else {\n offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);\n }\n break;\n case 3:\n {\n const previousImageData = offscreenContext.getImageData(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);\n offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);\n context.drawImage(offscreenCanvas, pos.x, pos.y);\n offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);\n offscreenContext.putImageData(previousImageData, origin.x, origin.y);\n }\n break;\n }\n particle.gifTime += delta.value;\n if (particle.gifTime > frame.delayTime) {\n particle.gifTime -= frame.delayTime;\n if (++frameIndex >= image.gifData.frames.length) {\n if (--particle.gifLoopCount <= defaultLoopCount) {\n return;\n }\n frameIndex = firstIndex;\n offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);\n }\n particle.gifFrame = frameIndex;\n }\n context.scale(image.gifData.width / radius, image.gifData.height / radius);\n}\nasync function loadGifImage(image) {\n if (image.type !== \"gif\") {\n const {\n loadImage\n } = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ../Utils.js */ \"./dist/browser/Utils.js\"));\n await loadImage(image);\n return;\n }\n image.loading = true;\n try {\n image.gifData = await decodeGIF(image.source);\n image.gifLoopCount = getGIFLoopAmount(image.gifData) ?? defaultLoopCount;\n if (!image.gifLoopCount) {\n image.gifLoopCount = Infinity;\n }\n } catch {\n image.error = true;\n }\n image.loading = false;\n}\n\n//# sourceURL=webpack://@tsparticles/shape-image/./dist/browser/GifUtils/Utils.js?");
|
|
47
|
+
|
|
48
|
+
/***/ })
|
|
49
|
+
|
|
50
|
+
}]);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Author : Matteo Bruni
|
|
3
|
+
* MIT license: https://opensource.org/licenses/MIT
|
|
4
|
+
* Demo / Generator : https://particles.js.org/
|
|
5
|
+
* GitHub : https://www.github.com/matteobruni/tsparticles
|
|
6
|
+
* How to use? : Check the GitHub README
|
|
7
|
+
* v3.2.0
|
|
8
|
+
*/
|
|
9
|
+
"use strict";
|
|
10
|
+
/*
|
|
11
|
+
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
|
12
|
+
* This devtool is neither made for production nor for readable output files.
|
|
13
|
+
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
|
14
|
+
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
15
|
+
* or disable the default devtool with "devtool: false".
|
|
16
|
+
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
17
|
+
*/
|
|
18
|
+
(this["webpackChunk_tsparticles_shape_image"] = this["webpackChunk_tsparticles_shape_image"] || []).push([["dist_browser_ImageDrawer_js"],{
|
|
19
|
+
|
|
20
|
+
/***/ "./dist/browser/ImageDrawer.js":
|
|
21
|
+
/*!*************************************!*\
|
|
22
|
+
!*** ./dist/browser/ImageDrawer.js ***!
|
|
23
|
+
\*************************************/
|
|
24
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
25
|
+
|
|
26
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ImageDrawer: () => (/* binding */ ImageDrawer)\n/* harmony export */ });\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tsparticles/engine */ \"@tsparticles/engine\");\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__);\n\nconst double = 2,\n defaultAlpha = 1,\n sides = 12,\n defaultRatio = 1;\nclass ImageDrawer {\n constructor(engine) {\n this.loadImageShape = async imageShape => {\n if (!this._engine.loadImage) {\n throw new Error(`${_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.errorPrefix} image shape not initialized`);\n }\n await this._engine.loadImage({\n gif: imageShape.gif,\n name: imageShape.name,\n replaceColor: imageShape.replaceColor ?? false,\n src: imageShape.src\n });\n };\n this._engine = engine;\n }\n addImage(image) {\n if (!this._engine.images) {\n this._engine.images = [];\n }\n this._engine.images.push(image);\n }\n async draw(data) {\n const {\n context,\n radius,\n particle,\n opacity\n } = data,\n image = particle.image,\n element = image?.element;\n if (!image) {\n return;\n }\n context.globalAlpha = opacity;\n if (image.gif && image.gifData) {\n const {\n drawGif\n } = await __webpack_require__.e(/*! import() */ \"dist_browser_GifUtils_Utils_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./GifUtils/Utils.js */ \"./dist/browser/GifUtils/Utils.js\"));\n drawGif(data);\n } else if (element) {\n const ratio = image.ratio,\n pos = {\n x: -radius,\n y: -radius\n },\n diameter = radius * double;\n context.drawImage(element, pos.x, pos.y, diameter, diameter / ratio);\n }\n context.globalAlpha = defaultAlpha;\n }\n getSidesCount() {\n return sides;\n }\n async init(container) {\n const options = container.actualOptions;\n if (!options.preload || !this._engine.loadImage) {\n return;\n }\n for (const imageData of options.preload) {\n await this._engine.loadImage(imageData);\n }\n }\n async loadShape(particle) {\n if (particle.shape !== \"image\" && particle.shape !== \"images\") {\n return;\n }\n if (!this._engine.images) {\n this._engine.images = [];\n }\n const imageData = particle.shapeData;\n if (!imageData) {\n return;\n }\n const image = this._engine.images.find(t => t.name === imageData.name || t.source === imageData.src);\n if (!image) {\n await this.loadImageShape(imageData);\n await this.loadShape(particle);\n }\n }\n async particleInit(container, particle) {\n if (particle.shape !== \"image\" && particle.shape !== \"images\") {\n return;\n }\n if (!this._engine.images) {\n this._engine.images = [];\n }\n const images = this._engine.images,\n imageData = particle.shapeData;\n if (!imageData) {\n return;\n }\n const color = particle.getFillColor(),\n image = images.find(t => t.name === imageData.name || t.source === imageData.src);\n if (!image) {\n return;\n }\n const replaceColor = imageData.replaceColor ?? image.replaceColor;\n if (image.loading) {\n setTimeout(() => {\n void this.particleInit(container, particle);\n });\n return;\n }\n let imageRes;\n if (image.svgData && color) {\n const {\n replaceImageColor\n } = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ./Utils.js */ \"./dist/browser/Utils.js\"));\n imageRes = await replaceImageColor(image, imageData, color, particle);\n } else {\n imageRes = {\n color,\n data: image,\n element: image.element,\n gif: image.gif,\n gifData: image.gifData,\n gifLoopCount: image.gifLoopCount,\n loaded: true,\n ratio: imageData.width && imageData.height ? imageData.width / imageData.height : image.ratio ?? defaultRatio,\n replaceColor: replaceColor,\n source: imageData.src\n };\n }\n if (!imageRes.ratio) {\n imageRes.ratio = 1;\n }\n const fill = imageData.fill ?? particle.shapeFill,\n close = imageData.close ?? particle.shapeClose,\n imageShape = {\n image: imageRes,\n fill,\n close\n };\n particle.image = imageShape.image;\n particle.shapeFill = imageShape.fill;\n particle.shapeClose = imageShape.close;\n }\n}\n\n//# sourceURL=webpack://@tsparticles/shape-image/./dist/browser/ImageDrawer.js?");
|
|
27
|
+
|
|
28
|
+
/***/ })
|
|
29
|
+
|
|
30
|
+
}]);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Author : Matteo Bruni
|
|
3
|
+
* MIT license: https://opensource.org/licenses/MIT
|
|
4
|
+
* Demo / Generator : https://particles.js.org/
|
|
5
|
+
* GitHub : https://www.github.com/matteobruni/tsparticles
|
|
6
|
+
* How to use? : Check the GitHub README
|
|
7
|
+
* v3.2.0
|
|
8
|
+
*/
|
|
9
|
+
"use strict";
|
|
10
|
+
/*
|
|
11
|
+
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
|
12
|
+
* This devtool is neither made for production nor for readable output files.
|
|
13
|
+
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
|
14
|
+
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
15
|
+
* or disable the default devtool with "devtool: false".
|
|
16
|
+
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
17
|
+
*/
|
|
18
|
+
(this["webpackChunk_tsparticles_shape_image"] = this["webpackChunk_tsparticles_shape_image"] || []).push([["dist_browser_ImagePreloader_js"],{
|
|
19
|
+
|
|
20
|
+
/***/ "./dist/browser/ImagePreloader.js":
|
|
21
|
+
/*!****************************************!*\
|
|
22
|
+
!*** ./dist/browser/ImagePreloader.js ***!
|
|
23
|
+
\****************************************/
|
|
24
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
25
|
+
|
|
26
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ImagePreloaderPlugin: () => (/* binding */ ImagePreloaderPlugin)\n/* harmony export */ });\n/* harmony import */ var _Options_Classes_Preload_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Options/Classes/Preload.js */ \"./dist/browser/Options/Classes/Preload.js\");\n\nclass ImagePreloaderPlugin {\n constructor(engine) {\n this.id = \"imagePreloader\";\n this._engine = engine;\n }\n async getPlugin() {\n await Promise.resolve();\n return {};\n }\n loadOptions(options, source) {\n if (!source?.preload) {\n return;\n }\n if (!options.preload) {\n options.preload = [];\n }\n const preloadOptions = options.preload;\n for (const item of source.preload) {\n const existing = preloadOptions.find(t => t.name === item.name || t.src === item.src);\n if (existing) {\n existing.load(item);\n } else {\n const preload = new _Options_Classes_Preload_js__WEBPACK_IMPORTED_MODULE_0__.Preload();\n preload.load(item);\n preloadOptions.push(preload);\n }\n }\n }\n needsPlugin() {\n return true;\n }\n}\n\n//# sourceURL=webpack://@tsparticles/shape-image/./dist/browser/ImagePreloader.js?");
|
|
27
|
+
|
|
28
|
+
/***/ }),
|
|
29
|
+
|
|
30
|
+
/***/ "./dist/browser/Options/Classes/Preload.js":
|
|
31
|
+
/*!*************************************************!*\
|
|
32
|
+
!*** ./dist/browser/Options/Classes/Preload.js ***!
|
|
33
|
+
\*************************************************/
|
|
34
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
35
|
+
|
|
36
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Preload: () => (/* binding */ Preload)\n/* harmony export */ });\nclass Preload {\n constructor() {\n this.src = \"\";\n this.gif = false;\n }\n load(data) {\n if (!data) {\n return;\n }\n if (data.gif !== undefined) {\n this.gif = data.gif;\n }\n if (data.height !== undefined) {\n this.height = data.height;\n }\n if (data.name !== undefined) {\n this.name = data.name;\n }\n if (data.replaceColor !== undefined) {\n this.replaceColor = data.replaceColor;\n }\n if (data.src !== undefined) {\n this.src = data.src;\n }\n if (data.width !== undefined) {\n this.width = data.width;\n }\n }\n}\n\n//# sourceURL=webpack://@tsparticles/shape-image/./dist/browser/Options/Classes/Preload.js?");
|
|
37
|
+
|
|
38
|
+
/***/ })
|
|
39
|
+
|
|
40
|
+
}]);
|
|
@@ -27,12 +27,13 @@ export class ByteStream {
|
|
|
27
27
|
return blockString;
|
|
28
28
|
}
|
|
29
29
|
readSubBlocksBin() {
|
|
30
|
-
let size =
|
|
30
|
+
let size = this.data[this.pos], len = 0;
|
|
31
31
|
const emptySize = 0, increment = 1;
|
|
32
32
|
for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
|
|
33
33
|
len += size;
|
|
34
34
|
}
|
|
35
35
|
const blockData = new Uint8Array(len);
|
|
36
|
+
size = this.data[this.pos++];
|
|
36
37
|
for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
|
|
37
38
|
for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
|
|
38
39
|
}
|
package/esm/GifUtils/Utils.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { InterlaceOffsets, InterlaceSteps } from "./Constants.js";
|
|
2
2
|
import { ByteStream } from "./ByteStream.js";
|
|
3
|
+
const origin = {
|
|
4
|
+
x: 0,
|
|
5
|
+
y: 0,
|
|
6
|
+
}, defaultFrame = 0, half = 0.5, initialTime = 0, firstIndex = 0, defaultLoopCount = 0;
|
|
3
7
|
function parseColorTable(byteStream, count) {
|
|
4
8
|
const colors = [];
|
|
5
9
|
for (let i = 0; i < count; i++) {
|
|
@@ -329,3 +333,95 @@ export async function decodeGIF(gifURL, progressCallback, avgAlpha) {
|
|
|
329
333
|
throw error;
|
|
330
334
|
}
|
|
331
335
|
}
|
|
336
|
+
export function drawGif(data) {
|
|
337
|
+
const { context, radius, particle, delta } = data, image = particle.image;
|
|
338
|
+
if (!image?.gifData || !image.gif) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const offscreenCanvas = new OffscreenCanvas(image.gifData.width, image.gifData.height), offscreenContext = offscreenCanvas.getContext("2d");
|
|
342
|
+
if (!offscreenContext) {
|
|
343
|
+
throw new Error("could not create offscreen canvas context");
|
|
344
|
+
}
|
|
345
|
+
offscreenContext.imageSmoothingQuality = "low";
|
|
346
|
+
offscreenContext.imageSmoothingEnabled = false;
|
|
347
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
348
|
+
if (particle.gifLoopCount === undefined) {
|
|
349
|
+
particle.gifLoopCount = image.gifLoopCount ?? defaultLoopCount;
|
|
350
|
+
}
|
|
351
|
+
let frameIndex = particle.gifFrame ?? defaultFrame;
|
|
352
|
+
const pos = { x: -image.gifData.width * half, y: -image.gifData.height * half }, frame = image.gifData.frames[frameIndex];
|
|
353
|
+
if (particle.gifTime === undefined) {
|
|
354
|
+
particle.gifTime = initialTime;
|
|
355
|
+
}
|
|
356
|
+
if (!frame.bitmap) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
context.scale(radius / image.gifData.width, radius / image.gifData.height);
|
|
360
|
+
switch (frame.disposalMethod) {
|
|
361
|
+
case 4:
|
|
362
|
+
case 5:
|
|
363
|
+
case 6:
|
|
364
|
+
case 7:
|
|
365
|
+
case 0:
|
|
366
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
367
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
368
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
369
|
+
break;
|
|
370
|
+
case 1:
|
|
371
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
372
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
373
|
+
break;
|
|
374
|
+
case 2:
|
|
375
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
376
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
377
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
378
|
+
if (!image.gifData.globalColorTable.length) {
|
|
379
|
+
offscreenContext.putImageData(image.gifData.frames[firstIndex].image, pos.x + frame.left, pos.y + frame.top);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
|
|
383
|
+
}
|
|
384
|
+
break;
|
|
385
|
+
case 3:
|
|
386
|
+
{
|
|
387
|
+
const previousImageData = offscreenContext.getImageData(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
388
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
389
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
390
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
391
|
+
offscreenContext.putImageData(previousImageData, origin.x, origin.y);
|
|
392
|
+
}
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
particle.gifTime += delta.value;
|
|
396
|
+
if (particle.gifTime > frame.delayTime) {
|
|
397
|
+
particle.gifTime -= frame.delayTime;
|
|
398
|
+
if (++frameIndex >= image.gifData.frames.length) {
|
|
399
|
+
if (--particle.gifLoopCount <= defaultLoopCount) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
frameIndex = firstIndex;
|
|
403
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
404
|
+
}
|
|
405
|
+
particle.gifFrame = frameIndex;
|
|
406
|
+
}
|
|
407
|
+
context.scale(image.gifData.width / radius, image.gifData.height / radius);
|
|
408
|
+
}
|
|
409
|
+
export async function loadGifImage(image) {
|
|
410
|
+
if (image.type !== "gif") {
|
|
411
|
+
const { loadImage } = await import("../Utils.js");
|
|
412
|
+
await loadImage(image);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
image.loading = true;
|
|
416
|
+
try {
|
|
417
|
+
image.gifData = await decodeGIF(image.source);
|
|
418
|
+
image.gifLoopCount = getGIFLoopAmount(image.gifData) ?? defaultLoopCount;
|
|
419
|
+
if (!image.gifLoopCount) {
|
|
420
|
+
image.gifLoopCount = Infinity;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
catch {
|
|
424
|
+
image.error = true;
|
|
425
|
+
}
|
|
426
|
+
image.loading = false;
|
|
427
|
+
}
|