@aarsteinmedia/dotlottie-player 4.0.14 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/custom-elements.json +2310 -187
- package/dist/index.d.ts +22 -7
- package/dist/index.js +1777 -2
- package/dist/unpkg/index.js +2 -0
- package/package.json +18 -17
- package/dist/cjs/index.js +0 -1804
- package/dist/esm/index.js +0 -1777
package/dist/esm/index.js
DELETED
|
@@ -1,1777 +0,0 @@
|
|
|
1
|
-
import { strToU8, strFromU8, zip, unzip as unzip$1 } from 'fflate';
|
|
2
|
-
import * as Lottie from 'lottie-web/build/player/lottie.js';
|
|
3
|
-
|
|
4
|
-
var ObjectFit = /*#__PURE__*/ function(ObjectFit) {
|
|
5
|
-
ObjectFit["Contain"] = "contain";
|
|
6
|
-
ObjectFit["Cover"] = "cover";
|
|
7
|
-
ObjectFit["Fill"] = "fill";
|
|
8
|
-
ObjectFit["ScaleDown"] = "scale-down";
|
|
9
|
-
ObjectFit["None"] = "none";
|
|
10
|
-
return ObjectFit;
|
|
11
|
-
}({});
|
|
12
|
-
var PlayerState = /*#__PURE__*/ function(PlayerState) {
|
|
13
|
-
PlayerState["Completed"] = "completed";
|
|
14
|
-
PlayerState["Destroyed"] = "destroyed";
|
|
15
|
-
PlayerState["Error"] = "error";
|
|
16
|
-
PlayerState["Frozen"] = "frozen";
|
|
17
|
-
PlayerState["Loading"] = "loading";
|
|
18
|
-
PlayerState["Paused"] = "paused";
|
|
19
|
-
PlayerState["Playing"] = "playing";
|
|
20
|
-
PlayerState["Stopped"] = "stopped";
|
|
21
|
-
return PlayerState;
|
|
22
|
-
}({});
|
|
23
|
-
var PlayMode = /*#__PURE__*/ function(PlayMode) {
|
|
24
|
-
PlayMode["Bounce"] = "bounce";
|
|
25
|
-
PlayMode["Normal"] = "normal";
|
|
26
|
-
return PlayMode;
|
|
27
|
-
}({});
|
|
28
|
-
var PlayerEvents = /*#__PURE__*/ function(PlayerEvents) {
|
|
29
|
-
PlayerEvents["Complete"] = "complete";
|
|
30
|
-
PlayerEvents["Destroyed"] = "destroyed";
|
|
31
|
-
PlayerEvents["Error"] = "error";
|
|
32
|
-
PlayerEvents["Frame"] = "frame";
|
|
33
|
-
PlayerEvents["Freeze"] = "freeze";
|
|
34
|
-
PlayerEvents["Load"] = "load";
|
|
35
|
-
PlayerEvents["Loop"] = "loop";
|
|
36
|
-
PlayerEvents["Next"] = "next";
|
|
37
|
-
PlayerEvents["Pause"] = "pause";
|
|
38
|
-
PlayerEvents["Play"] = "play";
|
|
39
|
-
PlayerEvents["Previous"] = "previous";
|
|
40
|
-
PlayerEvents["Ready"] = "ready";
|
|
41
|
-
PlayerEvents["Rendered"] = "rendered";
|
|
42
|
-
PlayerEvents["Stop"] = "stop";
|
|
43
|
-
return PlayerEvents;
|
|
44
|
-
}({});
|
|
45
|
-
var PreserveAspectRatio = /*#__PURE__*/ function(PreserveAspectRatio) {
|
|
46
|
-
PreserveAspectRatio["Contain"] = "xMidYMid meet";
|
|
47
|
-
PreserveAspectRatio["Cover"] = "xMidYMid slice";
|
|
48
|
-
PreserveAspectRatio["None"] = "xMinYMin slice";
|
|
49
|
-
PreserveAspectRatio["Initial"] = "none";
|
|
50
|
-
return PreserveAspectRatio;
|
|
51
|
-
}({});
|
|
52
|
-
|
|
53
|
-
class CustomError extends Error {
|
|
54
|
-
}
|
|
55
|
-
const addExt = (ext, str)=>{
|
|
56
|
-
if (!str) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
if (getExt(str)) {
|
|
60
|
-
if (getExt(str) === ext) {
|
|
61
|
-
return str;
|
|
62
|
-
}
|
|
63
|
-
return `${getFilename(str)}.${ext}`;
|
|
64
|
-
}
|
|
65
|
-
return `${str}.${ext}`;
|
|
66
|
-
}, aspectRatio = (objectFit)=>{
|
|
67
|
-
switch(objectFit){
|
|
68
|
-
case ObjectFit.Contain:
|
|
69
|
-
case ObjectFit.ScaleDown:
|
|
70
|
-
return 'xMidYMid meet';
|
|
71
|
-
case ObjectFit.Cover:
|
|
72
|
-
return 'xMidYMid slice';
|
|
73
|
-
case ObjectFit.Fill:
|
|
74
|
-
return 'none';
|
|
75
|
-
case ObjectFit.None:
|
|
76
|
-
return 'xMinYMin slice';
|
|
77
|
-
default:
|
|
78
|
-
return 'xMidYMid meet';
|
|
79
|
-
}
|
|
80
|
-
}, /**
|
|
81
|
-
* Convert Base64 encoded string to Uint8Array
|
|
82
|
-
* @param { string } str Base64 encoded string
|
|
83
|
-
* @returns { Uint8Array } UTF-8/Latin-1 binary
|
|
84
|
-
*/ base64ToU8 = (str)=>strToU8(isServer() ? Buffer.from(parseBase64(str), 'base64').toString('binary') : atob(parseBase64(str)), true), /**
|
|
85
|
-
* Convert a JSON Lottie to dotLottie or combine several animations and download new dotLottie file in your browser.
|
|
86
|
-
*/ createDotLottie = async ({ animations, fileName, manifest, shouldDownload = true })=>{
|
|
87
|
-
try {
|
|
88
|
-
// Input validation
|
|
89
|
-
if (!animations?.length || !manifest) {
|
|
90
|
-
throw new Error(`Missing or malformed required parameter(s):\n ${animations?.length ? '- manifest\n' : ''} ${manifest ? '- animations\n' : ''}`);
|
|
91
|
-
}
|
|
92
|
-
const manifestCompressionLevel = 0, animationCompressionLevel = 9, // Prepare the dotLottie file
|
|
93
|
-
name = addExt('lottie', fileName) || `${useId()}.lottie`, dotlottie = {
|
|
94
|
-
'manifest.json': [
|
|
95
|
-
strToU8(JSON.stringify(manifest), true),
|
|
96
|
-
{
|
|
97
|
-
level: manifestCompressionLevel
|
|
98
|
-
}
|
|
99
|
-
]
|
|
100
|
-
};
|
|
101
|
-
// Add animations and assets to the dotLottie file
|
|
102
|
-
for (const [i, animation] of animations.entries()){
|
|
103
|
-
for (const asset of animation.assets ?? []){
|
|
104
|
-
if (!asset.p || !isImage(asset) && !isAudio(asset)) {
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
const { p: file, u: path } = asset, // Original asset.id caused issues with multianimations
|
|
108
|
-
assetId = useId('asset'), isEncoded = file.startsWith('data:'), ext = isEncoded ? getExtFromB64(file) : getExt(file), // Check if the asset is already base64-encoded. If not, get path, fetch it, and encode it
|
|
109
|
-
dataURL = isEncoded ? file : await fileToBase64(path ? path.endsWith('/') && `${path}${file}` || `${path}/${file}` : file);
|
|
110
|
-
asset.p = `${assetId}.${ext}`;
|
|
111
|
-
// Asset is embedded, so path empty string
|
|
112
|
-
asset.u = '';
|
|
113
|
-
// Asset is encoded
|
|
114
|
-
asset.e = 1;
|
|
115
|
-
dotlottie[`${isAudio(asset) ? 'audio' : 'images'}/${assetId}.${ext}`] = [
|
|
116
|
-
base64ToU8(dataURL),
|
|
117
|
-
{
|
|
118
|
-
level: animationCompressionLevel
|
|
119
|
-
}
|
|
120
|
-
];
|
|
121
|
-
}
|
|
122
|
-
dotlottie[`animations/${manifest.animations[i].id}.json`] = [
|
|
123
|
-
strToU8(JSON.stringify(animation), true),
|
|
124
|
-
{
|
|
125
|
-
level: animationCompressionLevel
|
|
126
|
-
}
|
|
127
|
-
];
|
|
128
|
-
}
|
|
129
|
-
const buffer = await getArrayBuffer(dotlottie);
|
|
130
|
-
return shouldDownload ? download(buffer, {
|
|
131
|
-
mimeType: 'application/zip',
|
|
132
|
-
name
|
|
133
|
-
}) : buffer;
|
|
134
|
-
} catch (err) {
|
|
135
|
-
console.error(`❌ ${handleErrors(err).message}`);
|
|
136
|
-
}
|
|
137
|
-
}, createJSON = ({ animation, fileName, shouldDownload })=>{
|
|
138
|
-
try {
|
|
139
|
-
if (!animation) {
|
|
140
|
-
throw new Error("Missing or malformed required parameter(s):\n - animation\n'");
|
|
141
|
-
}
|
|
142
|
-
const name = addExt('json', fileName) || `${useId()}.json`, jsonString = JSON.stringify(animation);
|
|
143
|
-
return shouldDownload ? download(jsonString, {
|
|
144
|
-
mimeType: 'application/json',
|
|
145
|
-
name
|
|
146
|
-
}) : jsonString;
|
|
147
|
-
} catch (err) {
|
|
148
|
-
console.error(`❌ ${handleErrors(err).message}`);
|
|
149
|
-
}
|
|
150
|
-
}, /**
|
|
151
|
-
* Download file, either SVG or dotLottie.
|
|
152
|
-
* @param { string } data The data to be downloaded
|
|
153
|
-
* @param { string } name Don't include file extension in the filename
|
|
154
|
-
*/ download = (data, options)=>{
|
|
155
|
-
const blob = new Blob([
|
|
156
|
-
data
|
|
157
|
-
], {
|
|
158
|
-
type: options?.mimeType
|
|
159
|
-
}), fileName = options?.name || useId(), dataURL = URL.createObjectURL(blob), link = document.createElement('a');
|
|
160
|
-
link.href = dataURL;
|
|
161
|
-
link.download = fileName;
|
|
162
|
-
link.hidden = true;
|
|
163
|
-
document.body.appendChild(link);
|
|
164
|
-
link.click();
|
|
165
|
-
setTimeout(()=>{
|
|
166
|
-
link.remove();
|
|
167
|
-
URL.revokeObjectURL(dataURL);
|
|
168
|
-
}, 1000);
|
|
169
|
-
}, fileToBase64 = async (url)=>{
|
|
170
|
-
const response = await fetch(url), blob = await response.blob();
|
|
171
|
-
return new Promise((resolve, reject)=>{
|
|
172
|
-
try {
|
|
173
|
-
const reader = new FileReader();
|
|
174
|
-
reader.onload = ()=>{
|
|
175
|
-
if (typeof reader.result === 'string') {
|
|
176
|
-
resolve(reader.result);
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
reject();
|
|
180
|
-
};
|
|
181
|
-
reader.readAsDataURL(blob);
|
|
182
|
-
} catch (e) {
|
|
183
|
-
reject(e);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
}, frameOutput = (frame)=>((frame ?? 0) + 1).toString().padStart(3, '0'), getAnimationData = async (input)=>{
|
|
187
|
-
try {
|
|
188
|
-
if (!input || typeof input !== 'string' && typeof input !== 'object') {
|
|
189
|
-
throw new Error('Broken file or invalid file format');
|
|
190
|
-
}
|
|
191
|
-
if (typeof input !== 'string') {
|
|
192
|
-
const animations = Array.isArray(input) ? input : [
|
|
193
|
-
input
|
|
194
|
-
];
|
|
195
|
-
return {
|
|
196
|
-
animations,
|
|
197
|
-
isDotLottie: false,
|
|
198
|
-
manifest: undefined
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
const result = await fetch(input, {
|
|
202
|
-
headers: {
|
|
203
|
-
'Content-Type': 'application/json; charset=UTF-8'
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
if (!result.ok) {
|
|
207
|
-
const error = new CustomError(result.statusText);
|
|
208
|
-
error.status = result.status;
|
|
209
|
-
throw error;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Check if file is JSON, first by parsing file name for extension,
|
|
213
|
-
* then – if filename has no extension – by cloning the response
|
|
214
|
-
* and parsing it for content.
|
|
215
|
-
*/ const ext = getExt(input);
|
|
216
|
-
if (ext === 'json' || !ext) {
|
|
217
|
-
if (ext) {
|
|
218
|
-
const lottie = await result.json();
|
|
219
|
-
return {
|
|
220
|
-
animations: [
|
|
221
|
-
lottie
|
|
222
|
-
],
|
|
223
|
-
isDotLottie: false,
|
|
224
|
-
manifest: undefined
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
const text = await result.clone().text();
|
|
228
|
-
try {
|
|
229
|
-
const lottie = JSON.parse(text);
|
|
230
|
-
return {
|
|
231
|
-
animations: [
|
|
232
|
-
lottie
|
|
233
|
-
],
|
|
234
|
-
isDotLottie: false,
|
|
235
|
-
manifest: undefined
|
|
236
|
-
};
|
|
237
|
-
} catch (_e) {
|
|
238
|
-
/* empty */ }
|
|
239
|
-
}
|
|
240
|
-
const { data, manifest } = await getLottieJSON(result);
|
|
241
|
-
return {
|
|
242
|
-
animations: data,
|
|
243
|
-
isDotLottie: true,
|
|
244
|
-
manifest
|
|
245
|
-
};
|
|
246
|
-
} catch (err) {
|
|
247
|
-
console.error(`❌ ${handleErrors(err).message}`);
|
|
248
|
-
return {
|
|
249
|
-
animations: undefined,
|
|
250
|
-
isDotLottie: false,
|
|
251
|
-
manifest: undefined
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
}, getArrayBuffer = async (zippable)=>{
|
|
255
|
-
const arrayBuffer = await new Promise((resolve, reject)=>{
|
|
256
|
-
zip(zippable, {
|
|
257
|
-
level: 9
|
|
258
|
-
}, (err, data)=>{
|
|
259
|
-
if (err) {
|
|
260
|
-
reject(err);
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
if (!(data.buffer instanceof ArrayBuffer)) {
|
|
264
|
-
reject('Data is not transferable');
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
resolve(data.buffer);
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
return arrayBuffer;
|
|
271
|
-
}, /**
|
|
272
|
-
* Get extension from filename, URL or path
|
|
273
|
-
* @param { string } str Filename, URL or path
|
|
274
|
-
*/ getExt = (str)=>{
|
|
275
|
-
if (typeof str !== 'string' || !str || !hasExt(str)) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
return str.split('.').pop()?.toLowerCase();
|
|
279
|
-
}, getExtFromB64 = (str)=>{
|
|
280
|
-
const mime = str.split(':')[1].split(';')[0], ext = mime.split('/')[1].split('+')[0];
|
|
281
|
-
return ext;
|
|
282
|
-
}, /**
|
|
283
|
-
* Parse URL to get filename
|
|
284
|
-
* @param { string } src The url string
|
|
285
|
-
* @param { boolean } keepExt Whether to include file extension
|
|
286
|
-
* @returns { string } Filename, in lowercase
|
|
287
|
-
*/ getFilename = (src, keepExt)=>{
|
|
288
|
-
// Because the regex strips all special characters, we need to extract the file extension, so we can add it later if we need it
|
|
289
|
-
getExt(src);
|
|
290
|
-
return `${src.split('/').pop()?.replace(/\.[^.]*$/, '').replace(/\W+/g, '-')}${''}` // .toLowerCase()
|
|
291
|
-
;
|
|
292
|
-
}, getLottieJSON = async (resp)=>{
|
|
293
|
-
const unzipped = await unzip(resp), manifest = getManifest(unzipped), data = [], toResolve = [];
|
|
294
|
-
for (const { id } of manifest.animations){
|
|
295
|
-
const str = strFromU8(unzipped[`animations/${id}.json`]), lottie = JSON.parse(prepareString(str));
|
|
296
|
-
toResolve.push(resolveAssets(unzipped, lottie.assets));
|
|
297
|
-
data.push(lottie);
|
|
298
|
-
}
|
|
299
|
-
await Promise.all(toResolve);
|
|
300
|
-
return {
|
|
301
|
-
data,
|
|
302
|
-
manifest
|
|
303
|
-
};
|
|
304
|
-
}, getManifest = (unzipped)=>{
|
|
305
|
-
const file = strFromU8(unzipped['manifest.json'], false), manifest = JSON.parse(file);
|
|
306
|
-
if (!('animations' in manifest)) {
|
|
307
|
-
throw new Error('Manifest not found');
|
|
308
|
-
}
|
|
309
|
-
if (!manifest.animations.length) {
|
|
310
|
-
throw new Error('No animations listed in manifest');
|
|
311
|
-
}
|
|
312
|
-
return manifest;
|
|
313
|
-
}, getMimeFromExt = (ext)=>{
|
|
314
|
-
switch(ext){
|
|
315
|
-
case 'svg':
|
|
316
|
-
case 'svg+xml':
|
|
317
|
-
return 'image/svg+xml';
|
|
318
|
-
case 'jpg':
|
|
319
|
-
case 'jpeg':
|
|
320
|
-
return 'image/jpeg';
|
|
321
|
-
case 'png':
|
|
322
|
-
case 'gif':
|
|
323
|
-
case 'webp':
|
|
324
|
-
case 'avif':
|
|
325
|
-
return `image/${ext}`;
|
|
326
|
-
case 'mp3':
|
|
327
|
-
case 'mpeg':
|
|
328
|
-
case 'wav':
|
|
329
|
-
return `audio/${ext}`;
|
|
330
|
-
default:
|
|
331
|
-
return '';
|
|
332
|
-
}
|
|
333
|
-
}, handleErrors = (err)=>{
|
|
334
|
-
const res = {
|
|
335
|
-
message: 'Unknown error',
|
|
336
|
-
status: isServer() ? 500 : 400
|
|
337
|
-
};
|
|
338
|
-
if (err && typeof err === 'object') {
|
|
339
|
-
if ('message' in err && typeof err.message === 'string') {
|
|
340
|
-
res.message = err.message;
|
|
341
|
-
}
|
|
342
|
-
if ('status' in err) {
|
|
343
|
-
res.status = Number(err.status);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
return res;
|
|
347
|
-
}, hasExt = (path)=>{
|
|
348
|
-
const lastDotIndex = path?.split('/').pop()?.lastIndexOf('.');
|
|
349
|
-
return (lastDotIndex ?? 0) > 1 && path && path.length - 1 > (lastDotIndex ?? 0);
|
|
350
|
-
}, isAudio = (asset)=>!('h' in asset) && !('w' in asset) && 'p' in asset && 'e' in asset && 'u' in asset && 'id' in asset, isBase64 = (str)=>{
|
|
351
|
-
if (!str) {
|
|
352
|
-
return false;
|
|
353
|
-
}
|
|
354
|
-
const regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
|
|
355
|
-
return regex.test(parseBase64(str));
|
|
356
|
-
}, isImage = (asset)=>'w' in asset && 'h' in asset && !('xt' in asset) && 'p' in asset, isServer = ()=>!(typeof window !== 'undefined' && window.document), parseBase64 = (str)=>str.substring(str.indexOf(',') + 1), prepareString = (str)=>str.replace(new RegExp(/"""/, 'g'), '""').replace(/(["'])(.*?)\1/g, (_match, quote, content)=>{
|
|
357
|
-
const replacedContent = content.replace(/[^\w\s\d.#]/g, '');
|
|
358
|
-
return `${quote}${replacedContent}${quote}`;
|
|
359
|
-
}), resolveAssets = async (unzipped, assets)=>{
|
|
360
|
-
if (!Array.isArray(assets)) {
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
const toResolve = [];
|
|
364
|
-
for (const asset of assets){
|
|
365
|
-
if (!isAudio(asset) && !isImage(asset)) {
|
|
366
|
-
continue;
|
|
367
|
-
}
|
|
368
|
-
const type = isImage(asset) ? 'images' : 'audio', u8 = unzipped?.[`${type}/${asset.p}`];
|
|
369
|
-
if (!u8) {
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
toResolve.push(new Promise((resolveAsset)=>{
|
|
373
|
-
const assetB64 = isServer() ? Buffer.from(u8).toString('base64') : btoa(u8.reduce((dat, byte)=>`${dat}${String.fromCharCode(byte)}`, ''));
|
|
374
|
-
asset.p = asset.p?.startsWith('data:') || isBase64(asset.p) ? asset.p : `data:${getMimeFromExt(getExt(asset.p))};base64,${assetB64}`;
|
|
375
|
-
asset.e = 1;
|
|
376
|
-
asset.u = '';
|
|
377
|
-
resolveAsset();
|
|
378
|
-
}));
|
|
379
|
-
}
|
|
380
|
-
await Promise.all(toResolve);
|
|
381
|
-
}, unzip = async (resp)=>{
|
|
382
|
-
const u8 = new Uint8Array(await resp.arrayBuffer()), unzipped = await new Promise((resolve, reject)=>{
|
|
383
|
-
unzip$1(u8, /* { filter }, */ (err, file)=>{
|
|
384
|
-
if (err) {
|
|
385
|
-
reject(err);
|
|
386
|
-
}
|
|
387
|
-
resolve(file);
|
|
388
|
-
});
|
|
389
|
-
});
|
|
390
|
-
return unzipped;
|
|
391
|
-
}, useId = (prefix)=>{
|
|
392
|
-
const s4 = ()=>((1 + Math.random()) * 0x10000 | 0).toString(16).substring(1);
|
|
393
|
-
return `${prefix ?? `:${s4()}`}_${s4()}`;
|
|
394
|
-
};
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Render Player
|
|
398
|
-
*/ function renderPlayer() {
|
|
399
|
-
this.template.innerHTML = /* HTML */ `<div class="animation-container main" data-controls="${this.controls ?? false}" lang="${this.description ? document?.documentElement?.lang : 'en'}" aria-label="${this.description ?? 'Lottie animation'}" data-loaded="${this._playerState.loaded}"><figure class="animation" style="background:${this.background}">${this.playerState === PlayerState.Error ? /* HTML */ `<div class="error"><svg preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="1920" height="1080" viewBox="0 0 1920 1080"><path fill="#fff" d="M0 0h1920v1080H0z"/><path fill="#3a6d8b" d="M1190.2 531 1007 212.4c-22-38.2-77.2-38-98.8.5L729.5 531.3c-21.3 37.9 6.1 84.6 49.5 84.6l361.9.3c43.7 0 71.1-47.3 49.3-85.2zM937.3 288.7c.2-7.5 3.3-23.9 23.2-23.9 16.3 0 23 16.1 23 23.5 0 55.3-10.7 197.2-12.2 214.5-.1 1-.9 1.7-1.9 1.7h-18.3c-1 0-1.8-.7-1.9-1.7-1.4-17.5-13.4-162.9-11.9-214.1zm24.2 283.8c-13.1 0-23.7-10.6-23.7-23.7s10.6-23.7 23.7-23.7 23.7 10.6 23.7 23.7-10.6 23.7-23.7 23.7zM722.1 644h112.6v34.4h-70.4V698h58.8v31.7h-58.8v22.6h72.4v36.2H722.1V644zm162 57.1h.6c8.3-12.9 18.2-17.8 31.3-17.8 3 0 5.1.4 6.3 1v32.6h-.8c-22.4-3.8-35.6 6.3-35.6 29.5v42.3h-38.2V685.5h36.4v15.6zm78.9 0h.6c8.3-12.9 18.2-17.8 31.3-17.8 3 0 5.1.4 6.3 1v32.6h-.8c-22.4-3.8-35.6 6.3-35.6 29.5v42.3h-38.2V685.5H963v15.6zm39.5 36.2c0-31.3 22.2-54.8 56.6-54.8 34.4 0 56.2 23.5 56.2 54.8s-21.8 54.6-56.2 54.6c-34.4-.1-56.6-23.3-56.6-54.6zm74 0c0-17.4-6.1-29.1-17.8-29.1-11.7 0-17.4 11.7-17.4 29.1 0 17.4 5.7 29.1 17.4 29.1s17.8-11.8 17.8-29.1zm83.1-36.2h.6c8.3-12.9 18.2-17.8 31.3-17.8 3 0 5.1.4 6.3 1v32.6h-.8c-22.4-3.8-35.6 6.3-35.6 29.5v42.3h-38.2V685.5h36.4v15.6z"/><path fill="none" d="M718.9 807.7h645v285.4h-645z"/><text fill="#3a6d8b" style="text-align:center;position:absolute;left:100%;font-size:47px;font-family:system-ui,-apple-system,BlinkMacSystemFont,'.SFNSText-Regular',sans-serif" x="50%" y="848.017" text-anchor="middle">${this._errorMessage}</text></svg></div>` : ''}</figure><slot name="controls"></slot></div>`;
|
|
400
|
-
this.shadow.adoptedStyleSheets = [
|
|
401
|
-
DotLottiePlayer.styles
|
|
402
|
-
];
|
|
403
|
-
this.shadow.appendChild(this.template.content.cloneNode(true));
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* Render Controls
|
|
408
|
-
*/ function renderControls() {
|
|
409
|
-
const slot = this.shadow.querySelector('slot[name=controls]');
|
|
410
|
-
if (!slot) {
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
413
|
-
if (!this.controls) {
|
|
414
|
-
slot.innerHTML = '';
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
slot.innerHTML = /* HTML */ `<div class="lottie-controls toolbar ${this.playerState === PlayerState.Error ? 'has-error' : ''}" aria-label="Lottie Animation controls"><button class="togglePlay" data-active="false" aria-label="Toggle Play/Pause"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M8.016 5.016L18.985 12 8.016 18.984V5.015z"/></svg></button> <button class="stop" data-active="true" aria-label="Stop"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M6 6h12v12H6V6z"/></svg></button> <button class="prev" aria-label="Previous animation" hidden><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M17.9 18.2 8.1 12l9.8-6.2v12.4zm-10.3 0H6.1V5.8h1.5v12.4z"/></svg></button> <button class="next" aria-label="Next animation" hidden><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="m6.1 5.8 9.8 6.2-9.8 6.2V5.8zM16.4 5.8h1.5v12.4h-1.5z"/></svg></button><form class="progress-container${this.simple ? ' simple' : ''}"><input class="seeker" type="range" min="0" max="100" step="1" value="${this._seeker.toString()}" aria-valuemin="0" aria-valuemax="100" role="slider" aria-valuenow="${this._seeker.toString()}" tabindex="0" aria-label="Slider for search"><progress max="100" value="${this._seeker}"></progress></form>${this.simple ? '' : /* HTML */ `<button class="toggleLoop" data-active="${this.loop}" tabindex="0" aria-label="Toggle loop"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M17.016 17.016v-4.031h1.969v6h-12v3l-3.984-3.984 3.984-3.984v3h10.031zM6.984 6.984v4.031H5.015v-6h12v-3l3.984 3.984-3.984 3.984v-3H6.984z"/></svg></button> <button class="toggleBoomerang" data-active="${this.mode === PlayMode.Bounce}" aria-label="Toggle boomerang" tabindex="0"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="m11.8 13.2-.3.3c-.5.5-1.1 1.1-1.7 1.5-.5.4-1 .6-1.5.8-.5.2-1.1.3-1.6.3s-1-.1-1.5-.3c-.6-.2-1-.5-1.4-1-.5-.6-.8-1.2-.9-1.9-.2-.9-.1-1.8.3-2.6.3-.7.8-1.2 1.3-1.6.3-.2.6-.4 1-.5.2-.2.5-.2.8-.3.3 0 .7-.1 1 0 .3 0 .6.1.9.2.9.3 1.7.9 2.4 1.5.4.4.8.7 1.1 1.1l.1.1.4-.4c.6-.6 1.2-1.2 1.9-1.6.5-.3 1-.6 1.5-.7.4-.1.7-.2 1-.2h.9c1 .1 1.9.5 2.6 1.4.4.5.7 1.1.8 1.8.2.9.1 1.7-.2 2.5-.4.9-1 1.5-1.8 2-.4.2-.7.4-1.1.4-.4.1-.8.1-1.2.1-.5 0-.9-.1-1.3-.3-.8-.3-1.5-.9-2.1-1.5-.4-.4-.8-.7-1.1-1.1h-.3zm-1.1-1.1c-.1-.1-.1-.1 0 0-.3-.3-.6-.6-.8-.9-.5-.5-1-.9-1.6-1.2-.4-.3-.8-.4-1.3-.4-.4 0-.8 0-1.1.2-.5.2-.9.6-1.1 1-.2.3-.3.7-.3 1.1 0 .3 0 .6.1.9.1.5.4.9.8 1.2.5.4 1.1.5 1.7.5.5 0 1-.2 1.5-.5.6-.4 1.1-.8 1.6-1.3.1-.3.3-.5.5-.6zM13 12c.5.5 1 1 1.5 1.4.5.5 1.1.9 1.9 1 .4.1.8 0 1.2-.1.3-.1.6-.3.9-.5.4-.4.7-.9.8-1.4.1-.5 0-.9-.1-1.4-.3-.8-.8-1.2-1.7-1.4-.4-.1-.8-.1-1.2 0-.5.1-1 .4-1.4.7-.5.4-1 .8-1.4 1.2-.2.2-.4.3-.5.5z"/></svg></button> <button class="toggleSettings" aria-label="Settings" aria-haspopup="true" aria-expanded="${!!this._isSettingsOpen}" aria-controls="${this._identifier}-settings"><svg width="24" height="24" aria-hidden="true" focusable="false"><circle cx="12" cy="5.4" r="2.5"/><circle cx="12" cy="12" r="2.5"/><circle cx="12" cy="18.6" r="2.5"/></svg></button><div id="${this._identifier}-settings" class="popover" hidden><button class="convert" aria-label="Convert JSON animation to dotLottie format" hidden><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M17.016 17.016v-4.031h1.969v6h-12v3l-3.984-3.984 3.984-3.984v3h10.031zM6.984 6.984v4.031H5.015v-6h12v-3l3.984 3.984-3.984 3.984v-3H6.984z"/></svg> Convert to dotLottie</button> <button class="snapshot" aria-label="Download still image"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M16.8 10.8 12 15.6l-4.8-4.8h3V3.6h3.6v7.2h3zM12 15.6H3v4.8h18v-4.8h-9zm7.8 2.4h-2.4v-1.2h2.4V18z"/></svg> Download still image</button></div>`}</div>`;
|
|
418
|
-
const togglePlay = this.shadow.querySelector('.togglePlay');
|
|
419
|
-
if (togglePlay instanceof HTMLButtonElement) {
|
|
420
|
-
togglePlay.onclick = this.togglePlay;
|
|
421
|
-
}
|
|
422
|
-
const stop = this.shadow.querySelector('.stop');
|
|
423
|
-
if (stop instanceof HTMLButtonElement) {
|
|
424
|
-
stop.onclick = this.stop;
|
|
425
|
-
}
|
|
426
|
-
const prev = this.shadow.querySelector('.prev');
|
|
427
|
-
if (prev instanceof HTMLButtonElement) {
|
|
428
|
-
prev.onclick = this.prev;
|
|
429
|
-
}
|
|
430
|
-
const next = this.shadow.querySelector('.next');
|
|
431
|
-
if (next instanceof HTMLButtonElement) {
|
|
432
|
-
next.onclick = this.next;
|
|
433
|
-
}
|
|
434
|
-
const seeker = this.shadow.querySelector('.seeker');
|
|
435
|
-
if (seeker instanceof HTMLInputElement) {
|
|
436
|
-
seeker.onchange = this._handleSeekChange;
|
|
437
|
-
seeker.onmousedown = this._freeze;
|
|
438
|
-
}
|
|
439
|
-
if (!this.simple) {
|
|
440
|
-
const toggleLoop = this.shadow.querySelector('.toggleLoop');
|
|
441
|
-
if (toggleLoop instanceof HTMLButtonElement) {
|
|
442
|
-
toggleLoop.onclick = this.toggleLoop;
|
|
443
|
-
}
|
|
444
|
-
const toggleBoomerang = this.shadow.querySelector('.toggleBoomerang');
|
|
445
|
-
if (toggleBoomerang instanceof HTMLButtonElement) {
|
|
446
|
-
toggleBoomerang.onclick = this.toggleBoomerang;
|
|
447
|
-
}
|
|
448
|
-
const convert = this.shadow.querySelector('.convert');
|
|
449
|
-
if (convert instanceof HTMLButtonElement) {
|
|
450
|
-
convert.onclick = this.convert;
|
|
451
|
-
}
|
|
452
|
-
const snapshot = this.shadow.querySelector('.snapshot');
|
|
453
|
-
if (snapshot instanceof HTMLButtonElement) {
|
|
454
|
-
snapshot.onclick = ()=>this.snapshot(true);
|
|
455
|
-
}
|
|
456
|
-
const toggleSettings = this.shadow.querySelector('.toggleSettings');
|
|
457
|
-
if (toggleSettings instanceof HTMLButtonElement) {
|
|
458
|
-
toggleSettings.onclick = this._handleSettingsClick;
|
|
459
|
-
toggleSettings.onblur = this._handleBlur;
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Credit to:
|
|
466
|
-
* @author Leonardo Favre <https://github.com/leofavre/observed-properties>
|
|
467
|
-
* @description Enhanced HTML element with reactive state handlers
|
|
468
|
-
*/ /* eslint-disable @typescript-eslint/ban-ts-comment */ const UPDATE_ON_CONNECTED = Symbol('UPDATE_ON_CONNECTED');
|
|
469
|
-
if (isServer()) {
|
|
470
|
-
// Mock HTMLElement for server-side rendering
|
|
471
|
-
// @ts-ignore
|
|
472
|
-
global.HTMLElement = class EmptyHTMLElement {
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
/**
|
|
476
|
-
* HTMLElement enhanced to track property changes
|
|
477
|
-
*/ class EnhancedElement extends HTMLElement {
|
|
478
|
-
constructor(){
|
|
479
|
-
super();
|
|
480
|
-
// @ts-ignore
|
|
481
|
-
const { observedProperties = [] } = this.constructor;
|
|
482
|
-
if (UPDATE_ON_CONNECTED in this) {
|
|
483
|
-
this[UPDATE_ON_CONNECTED] = [];
|
|
484
|
-
}
|
|
485
|
-
if ('propertyChangedCallback' in this && typeof this.propertyChangedCallback === 'function') {
|
|
486
|
-
for (const propName of observedProperties){
|
|
487
|
-
const initialValue = this[propName], CACHED_VALUE = Symbol(propName);
|
|
488
|
-
// @ts-ignore
|
|
489
|
-
this[CACHED_VALUE] = initialValue;
|
|
490
|
-
Object.defineProperty(this, propName, {
|
|
491
|
-
get () {
|
|
492
|
-
return this[CACHED_VALUE];
|
|
493
|
-
},
|
|
494
|
-
set (value) {
|
|
495
|
-
const oldValue = this[CACHED_VALUE];
|
|
496
|
-
this[CACHED_VALUE] = value;
|
|
497
|
-
this.propertyChangedCallback(propName, oldValue, value);
|
|
498
|
-
}
|
|
499
|
-
});
|
|
500
|
-
if (typeof initialValue !== 'undefined') {
|
|
501
|
-
if (UPDATE_ON_CONNECTED in this && Array.isArray(this[UPDATE_ON_CONNECTED])) {
|
|
502
|
-
this[UPDATE_ON_CONNECTED].push(propName);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
connectedCallback() {
|
|
509
|
-
let arr = [];
|
|
510
|
-
if (UPDATE_ON_CONNECTED in this && Array.isArray(this[UPDATE_ON_CONNECTED])) {
|
|
511
|
-
arr = this[UPDATE_ON_CONNECTED];
|
|
512
|
-
}
|
|
513
|
-
for (const propName of arr){
|
|
514
|
-
if (!('propertyChangedCallback' in this) || typeof this.propertyChangedCallback !== 'function') {
|
|
515
|
-
continue;
|
|
516
|
-
}
|
|
517
|
-
if (propName in this) {
|
|
518
|
-
this.propertyChangedCallback(propName, undefined, this[propName]);
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
var name="@aarsteinmedia/dotlottie-player";var version="4.0.13";var description="Web Component for playing Lottie animations in your web app. Previously @johanaarstein/dotlottie-player";var exports={".":{"import":"./dist/esm/index.js",node:"./dist/esm/index.js",require:"./dist/cjs/index.js",types:"./dist/index.d.ts"}};var main="./dist/esm/index.js";var unpkg="./dist/index.js";var module="./dist/esm/index.js";var types="./dist/index.d.ts";var type="module";var homepage="https://www.aarstein.media/en/dotlottie-player";var repository={url:"git+https://github.com/aarsteinmedia/dotlottie-player.git",type:"git"};var bugs="https://github.com/aarsteinmedia/dotlottie-player/issues";var author={name:"Johan Martin Aarstein",email:"johan@aarstein.media",url:"https://www.aarstein.media",organization:"Aarstein Media"};var contributors=[{name:"Anthony Colpron",email:"anthonycolpron@gmail.com",url:"https://github.com/anthony-colpron"}];var license="GPL-2.0-or-later";var scripts={test:"wtr",prebuild:"rimraf ./dist",build:"rollup -c","prebuild:types":"rimraf ./types","build:types":"tsc -p ./tsconfig.prod.json && tsc-alias","build:cem":"npx cem analyze --config cem.config.mjs",prod:"pnpm build:types && pnpm build && pnpm build:cem",dev:"rollup -c -w --environment NODE_ENV:development","lint:js":"eslint","lint:js:fix":"eslint --fix","lint:css":"npx stylelint **/*.css","lint:css:fix":"npx stylelint **/*.css --fix","lint:pkg":"npmPkgJsonLint .","lint:pkg:fix":"npmPkgJsonLint . --fix"};var dependencies={fflate:"^0.8.2","lottie-web":"^5.12.2"};var peerDependencies={"@types/react":">= 16.0.0"};var devDependencies={"@custom-elements-manifest/analyzer":"^0.10.4","@eslint/compat":"^1.2.6","@eslint/js":"^9.20.0","@esm-bundle/chai":"4.3.4-fix.0","@open-wc/testing":"^4.0.0","@rollup/plugin-commonjs":"^28.0.2","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^16.0.0","@rollup/plugin-typescript":"^12.1.2","@swc/core":"^1.10.18","@types/mocha":"^10.0.10","@types/node":"^22.13.4","@types/path-browserify":"^1.0.3","@web/dev-server-esbuild":"^1.0.4","@web/dev-server-import-maps":"^0.2.1","@web/dev-server-rollup":"^0.6.4","@web/test-runner":"^0.20.0","@web/test-runner-playwright":"^0.11.0",autoprefixer:"^10.4.20",esbuild:"^0.24.2",eslint:"^9.20.1","eslint-config-prettier":"^10.0.1","eslint-import-resolver-typescript":"^3.8.3","eslint-plugin-import":"^2.31.0","eslint-plugin-jsdoc":"^50.6.3","eslint-plugin-perfectionist":"^4.9.0","eslint-plugin-prettier":"^5.2.3",globals:"^16.0.0","npm-package-json-lint":"^8.0.0","npm-package-json-lint-config-default":"^7.0.1","postcss-flexbugs-fixes":"^5.0.2",prettier:"^3.5.1",rimraf:"^6.0.1",rollup:"^4.34.8","rollup-plugin-dts":"^6.1.1","rollup-plugin-html-literals":"^1.1.8","rollup-plugin-livereload":"^2.0.5","rollup-plugin-postcss":"^4.0.2","rollup-plugin-serve":"^3.0.0","rollup-plugin-summary":"^3.0.0","rollup-plugin-swc3":"^0.12.1","rollup-plugin-typescript-paths":"^1.5.0",stylelint:"^16.14.1","stylelint-config-recommended":"^15.0.0","tsc-alias":"^1.8.10",tslib:"^2.8.1",typescript:"^5.7.3","typescript-eslint":"^8.24.1"};var pnpm={onlyBuiltDependencies:["@parcel/watcher","@swc/core","esbuild"]};var browserslist={production:[">0.3%","not dead","not op_mini all"],development:["last 1 chrome version","last 1 firefox version","last 1 safari version"]};var customElements$1="custom-elements.json";var files=["CHANGELOG.md","custom-elements.json","dist","README.md"];var keywords=["lottie","dotlottie","animation","web component","svg","vector","player"];var publishConfig={access:"public"};var engines={node:">= 8.17.0"};var funding={type:"paypal",url:"https://www.paypal.com/donate/?hosted_button_id=E7C7DMN8KSQ6A"};var pkg = {name:name,version:version,description:description,exports:exports,main:main,unpkg:unpkg,module:module,types:types,type:type,homepage:homepage,repository:repository,bugs:bugs,author:author,contributors:contributors,license:license,scripts:scripts,dependencies:dependencies,peerDependencies:peerDependencies,devDependencies:devDependencies,pnpm:pnpm,browserslist:browserslist,customElements:customElements$1,files:files,keywords:keywords,publishConfig:publishConfig,engines:engines,funding:funding};
|
|
525
|
-
|
|
526
|
-
var css_248z = "* {\n box-sizing: border-box;\n}\n\n:host {\n --lottie-player-toolbar-height: 35px;\n --lottie-player-toolbar-background-color: #fff;\n --lottie-player-toolbar-icon-color: #000;\n --lottie-player-toolbar-icon-hover-color: #000;\n --lottie-player-toolbar-icon-active-color: #4285f4;\n --lottie-player-seeker-track-color: rgb(0 0 0 / 20%);\n --lottie-player-seeker-thumb-color: #4285f4;\n --lottie-player-seeker-display: block;\n\n width: 100%;\n height: 100%;\n\n &:not([hidden]) {\n display: block;\n }\n\n .main {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n margin: 0;\n padding: 0;\n }\n\n .animation {\n width: 100%;\n height: 100%;\n display: flex;\n margin: 0;\n padding: 0;\n }\n\n [data-controls='true'] .animation {\n height: calc(100% - 35px);\n }\n\n .animation-container {\n position: relative;\n }\n\n .popover {\n position: absolute;\n right: 5px;\n bottom: 40px;\n background-color: var(--lottie-player-toolbar-background-color);\n border-radius: 5px;\n padding: 10px 15px;\n border: solid 2px var(--lottie-player-toolbar-icon-color);\n animation: fade-in 0.2s ease-in-out;\n\n &::before {\n content: '';\n right: 10px;\n border: 7px solid transparent;\n margin-right: -7px;\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none;\n top: 100%;\n border-top-color: var(--lottie-player-toolbar-icon-color);\n }\n }\n\n .error {\n display: flex;\n margin: auto;\n justify-content: center;\n height: 100%;\n align-items: center;\n\n & svg {\n width: 100%;\n height: auto;\n }\n }\n\n .toolbar {\n display: flex;\n place-items: center center;\n background: var(--lottie-player-toolbar-background-color);\n margin: 0;\n height: 35px;\n padding: 5px;\n border-radius: 5px;\n gap: 5px;\n\n &.has-error {\n pointer-events: none;\n opacity: 0.5;\n }\n\n & button {\n cursor: pointer;\n fill: var(--lottie-player-toolbar-icon-color);\n color: var(--lottie-player-toolbar-icon-color);\n background: none;\n border: 0;\n padding: 0;\n outline: 0;\n height: 100%;\n margin: 0;\n align-items: center;\n gap: 5px;\n opacity: 0.9;\n\n &:not([hidden]) {\n display: flex;\n }\n\n &:hover {\n opacity: 1;\n }\n\n &[data-active='true'] {\n opacity: 1;\n fill: var(--lottie-player-toolbar-icon-active-color);\n }\n\n &:disabled {\n opacity: 0.5;\n }\n\n &:focus {\n outline: 0;\n }\n\n & svg {\n pointer-events: none;\n\n & > * {\n fill: inherit;\n }\n }\n\n &.disabled svg {\n display: none;\n }\n }\n }\n\n .progress-container {\n position: relative;\n width: 100%;\n\n &.simple {\n margin-right: 12px;\n }\n }\n\n .seeker {\n appearance: none;\n outline: none;\n width: 100%;\n height: 20px;\n border-radius: 3px;\n border: 0;\n cursor: pointer;\n background-color: transparent;\n\n display: var(--lottie-player-seeker-display);\n color: var(--lottie-player-seeker-thumb-color);\n margin: 0;\n padding: 7.5px 0;\n position: relative;\n z-index: 1;\n\n &::-webkit-slider-runnable-track,\n &::-webkit-slider-thumb {\n appearance: none;\n outline: none;\n }\n\n &::-webkit-slider-thumb {\n height: 15px;\n width: 15px;\n border-radius: 50%;\n border: 0;\n background-color: var(--lottie-player-seeker-thumb-color);\n cursor: pointer;\n -webkit-transition: transform 0.2s ease-in-out;\n transition: transform 0.2s ease-in-out;\n transform: scale(0);\n }\n\n &:hover::-webkit-slider-thumb,\n &:focus::-webkit-slider-thumb {\n transform: scale(1);\n }\n\n &::-moz-range-progress {\n background-color: var(--lottie-player-seeker-thumb-color);\n height: 5px;\n border-radius: 3px;\n }\n\n &::-moz-range-thumb {\n height: 15px;\n width: 15px;\n border-radius: 50%;\n background-color: var(--lottie-player-seeker-thumb-color);\n border: 0;\n cursor: pointer;\n -moz-transition: transform 0.2s ease-in-out;\n transition: transform 0.2s ease-in-out;\n transform: scale(0);\n }\n\n &:hover::-moz-range-thumb,\n &:focus::-moz-range-thumb {\n transform: scale(1);\n }\n\n &::-ms-track {\n width: 100%;\n height: 5px;\n cursor: pointer;\n background: transparent;\n border-color: transparent;\n color: transparent;\n }\n\n &::-ms-fill-upper {\n background: var(--lottie-player-seeker-track-color);\n border-radius: 3px;\n }\n\n &::-ms-fill-lower {\n background-color: var(--lottie-player-seeker-thumb-color);\n border-radius: 3px;\n }\n\n &::-ms-thumb {\n border: 0;\n height: 15px;\n width: 15px;\n border-radius: 50%;\n background: var(--lottie-player-seeker-thumb-color);\n cursor: pointer;\n -ms-transition: transform 0.2s ease-in-out;\n transition: transform 0.2s ease-in-out;\n transform: scale(0);\n }\n\n &:hover::-ms-thumb {\n transform: scale(1);\n }\n\n &:focus {\n &::-ms-thumb {\n transform: scale(1);\n }\n\n &::-ms-fill-lower,\n &::-ms-fill-upper {\n background: var(--lottie-player-seeker-track-color);\n }\n }\n }\n\n & progress {\n appearance: none;\n outline: none;\n position: absolute;\n width: 100%;\n height: 5px;\n border-radius: 3px;\n border: 0;\n top: 0;\n left: 0;\n margin: 7.5px 0;\n background-color: var(--lottie-player-seeker-track-color);\n pointer-events: none;\n\n &::-webkit-progress-inner-element {\n border-radius: 3px;\n overflow: hidden;\n }\n\n &::-webkit-slider-runnable-track {\n background-color: transparent;\n }\n\n &::-webkit-progress-value {\n background-color: var(--lottie-player-seeker-thumb-color);\n }\n }\n\n & *::-moz-progress-bar {\n background-color: var(--lottie-player-seeker-thumb-color);\n }\n}\n\n@keyframes fade-in {\n 0% {\n opacity: 0;\n }\n\n 100% {\n opacity: 1;\n }\n}\n\n@media (prefers-color-scheme: dark) {\n :host {\n --lottie-player-toolbar-background-color: #000;\n --lottie-player-toolbar-icon-color: #fff;\n --lottie-player-toolbar-icon-hover-color: #fff;\n --lottie-player-seeker-track-color: rgb(255 255 255 / 60%);\n }\n}\n";
|
|
527
|
-
|
|
528
|
-
/**
|
|
529
|
-
* dotLottie Player Web Component
|
|
530
|
-
* @export
|
|
531
|
-
* @class DotLottiePlayer
|
|
532
|
-
* @extends { EnhancedElement }
|
|
533
|
-
* @description Web Component for playing Lottie animations in your web app.
|
|
534
|
-
*/ class DotLottiePlayer extends EnhancedElement {
|
|
535
|
-
constructor(){
|
|
536
|
-
super(), this._renderControls = renderControls, this._render = renderPlayer, /**
|
|
537
|
-
* Multi-animation settings
|
|
538
|
-
*/ this._multiAnimationSettings = [], /**
|
|
539
|
-
* Animation Container
|
|
540
|
-
*/ this._container = null, /**
|
|
541
|
-
* @state
|
|
542
|
-
* Player state
|
|
543
|
-
*/ this.playerState = PlayerState.Loading, /**
|
|
544
|
-
* @state
|
|
545
|
-
* Whether settings toolbar is open
|
|
546
|
-
*/ this._isSettingsOpen = false, /**
|
|
547
|
-
* @state
|
|
548
|
-
* Seeker
|
|
549
|
-
*/ this._seeker = 0, /**
|
|
550
|
-
* @state
|
|
551
|
-
* Which animation to show, if several
|
|
552
|
-
*/ this._currentAnimation = 0, this._lottieInstance = null, this._identifier = this.id || useId('dotlottie'), this._errorMessage = 'Something went wrong', this._isBounce = false, this._isDotLottie = false, this._playerState = {
|
|
553
|
-
count: 0,
|
|
554
|
-
loaded: false,
|
|
555
|
-
prev: PlayerState.Loading,
|
|
556
|
-
scrollTimeout: null,
|
|
557
|
-
scrollY: 0,
|
|
558
|
-
visible: false
|
|
559
|
-
}, /**
|
|
560
|
-
* Handle settings click event
|
|
561
|
-
*/ this._handleSettingsClick = ({ target })=>{
|
|
562
|
-
this._toggleSettings();
|
|
563
|
-
// Because Safari does not add focus on click, we need to add it manually, so the onblur event will fire
|
|
564
|
-
if (target instanceof HTMLElement) {
|
|
565
|
-
target.focus();
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
this._complete = this._complete.bind(this);
|
|
569
|
-
this._dataFailed = this._dataFailed.bind(this);
|
|
570
|
-
this._dataReady = this._dataReady.bind(this);
|
|
571
|
-
this._DOMLoaded = this._DOMLoaded.bind(this);
|
|
572
|
-
this._enterFrame = this._enterFrame.bind(this);
|
|
573
|
-
this._freeze = this._freeze.bind(this);
|
|
574
|
-
this._handleBlur = this._handleBlur.bind(this);
|
|
575
|
-
this._handleScroll = this._handleScroll.bind(this);
|
|
576
|
-
this._handleSeekChange = this._handleSeekChange.bind(this);
|
|
577
|
-
this._handleWindowBlur = this._handleWindowBlur.bind(this);
|
|
578
|
-
this._loopComplete = this._loopComplete.bind(this);
|
|
579
|
-
this._mouseEnter = this._mouseEnter.bind(this);
|
|
580
|
-
this._mouseLeave = this._mouseLeave.bind(this);
|
|
581
|
-
this._onVisibilityChange = this._onVisibilityChange.bind(this);
|
|
582
|
-
this._switchInstance = this._switchInstance.bind(this);
|
|
583
|
-
this.togglePlay = this.togglePlay.bind(this);
|
|
584
|
-
this.stop = this.stop.bind(this);
|
|
585
|
-
this.prev = this.prev.bind(this);
|
|
586
|
-
this.next = this.next.bind(this);
|
|
587
|
-
this._renderControls = this._renderControls.bind(this);
|
|
588
|
-
this.snapshot = this.snapshot.bind(this);
|
|
589
|
-
this.toggleLoop = this.toggleLoop.bind(this);
|
|
590
|
-
this.toggleBoomerang = this.toggleBoomerang.bind(this);
|
|
591
|
-
this.convert = this.convert.bind(this);
|
|
592
|
-
this.destroy = this.destroy.bind(this);
|
|
593
|
-
this.template = document.createElement('template');
|
|
594
|
-
this.shadow = this.attachShadow({
|
|
595
|
-
mode: 'open'
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
/**
|
|
599
|
-
* Initialize everything on component first render
|
|
600
|
-
*/ async connectedCallback() {
|
|
601
|
-
super.connectedCallback();
|
|
602
|
-
this._render();
|
|
603
|
-
this._container = this.shadow.querySelector('.animation');
|
|
604
|
-
this._renderControls();
|
|
605
|
-
// Add listener for Visibility API's change event.
|
|
606
|
-
if (typeof document.hidden !== 'undefined') {
|
|
607
|
-
document.addEventListener('visibilitychange', this._onVisibilityChange);
|
|
608
|
-
}
|
|
609
|
-
// Add intersection observer for detecting component being out-of-view.
|
|
610
|
-
this._addIntersectionObserver();
|
|
611
|
-
// Setup lottie player
|
|
612
|
-
await this.load(this.src);
|
|
613
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Rendered));
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Cleanup on component destroy
|
|
617
|
-
*/ disconnectedCallback() {
|
|
618
|
-
// Remove intersection observer for detecting component being out-of-view
|
|
619
|
-
if (this._intersectionObserver) {
|
|
620
|
-
this._intersectionObserver.disconnect();
|
|
621
|
-
this._intersectionObserver = undefined;
|
|
622
|
-
}
|
|
623
|
-
// Destroy the animation instance
|
|
624
|
-
if (this._lottieInstance) {
|
|
625
|
-
this._lottieInstance.destroy();
|
|
626
|
-
}
|
|
627
|
-
// Remove the attached Visibility API's change event listener
|
|
628
|
-
document.removeEventListener('visibilitychange', this._onVisibilityChange);
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* Attributes to observe
|
|
632
|
-
*/ static get observedAttributes() {
|
|
633
|
-
return [
|
|
634
|
-
'animateOnScroll',
|
|
635
|
-
'autoplay',
|
|
636
|
-
'controls',
|
|
637
|
-
'direction',
|
|
638
|
-
'hover',
|
|
639
|
-
'loop',
|
|
640
|
-
'mode',
|
|
641
|
-
'speed',
|
|
642
|
-
'src',
|
|
643
|
-
'subframe'
|
|
644
|
-
];
|
|
645
|
-
}
|
|
646
|
-
/**
|
|
647
|
-
* Runs when the value of an attribute is changed on the component
|
|
648
|
-
*/ async attributeChangedCallback(name, _oldValue, value) {
|
|
649
|
-
if (!this._lottieInstance) {
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
if (name === 'animateOnScroll') {
|
|
653
|
-
if (value === '' || Boolean(value)) {
|
|
654
|
-
this._lottieInstance.autoplay = false;
|
|
655
|
-
addEventListener('scroll', this._handleScroll, {
|
|
656
|
-
capture: true,
|
|
657
|
-
passive: true
|
|
658
|
-
});
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
removeEventListener('scroll', this._handleScroll, true);
|
|
662
|
-
}
|
|
663
|
-
if (name === 'autoplay') {
|
|
664
|
-
if (this.animateOnScroll) {
|
|
665
|
-
return;
|
|
666
|
-
}
|
|
667
|
-
if (value === '' || Boolean(value)) {
|
|
668
|
-
this.play();
|
|
669
|
-
return;
|
|
670
|
-
}
|
|
671
|
-
this.stop();
|
|
672
|
-
}
|
|
673
|
-
if (name === 'controls') {
|
|
674
|
-
this._renderControls();
|
|
675
|
-
}
|
|
676
|
-
if (name === 'direction') {
|
|
677
|
-
if (Number(value) === -1) {
|
|
678
|
-
return this.setDirection(-1);
|
|
679
|
-
}
|
|
680
|
-
this.setDirection(1);
|
|
681
|
-
}
|
|
682
|
-
if (name === 'hover' && this._container) {
|
|
683
|
-
if (value === '' || Boolean(value)) {
|
|
684
|
-
this._container.addEventListener('mouseenter', this._mouseEnter);
|
|
685
|
-
this._container.addEventListener('mouseleave', this._mouseLeave);
|
|
686
|
-
return;
|
|
687
|
-
}
|
|
688
|
-
this._container.removeEventListener('mouseenter', this._mouseEnter);
|
|
689
|
-
this._container.removeEventListener('mouseleave', this._mouseLeave);
|
|
690
|
-
}
|
|
691
|
-
if (name === 'loop') {
|
|
692
|
-
const toggleLoop = this.shadow.querySelector('.toggleLoop');
|
|
693
|
-
if (toggleLoop instanceof HTMLButtonElement) {
|
|
694
|
-
toggleLoop.dataset.active = value;
|
|
695
|
-
}
|
|
696
|
-
this.setLoop(value === '' || Boolean(value));
|
|
697
|
-
}
|
|
698
|
-
if (name === 'mode') {
|
|
699
|
-
const toggleBoomerang = this.shadow.querySelector('.toggleBoomerang');
|
|
700
|
-
if (toggleBoomerang instanceof HTMLButtonElement) {
|
|
701
|
-
toggleBoomerang.dataset.active = (value === PlayMode.Bounce).toString();
|
|
702
|
-
}
|
|
703
|
-
this._isBounce = value === PlayMode.Bounce;
|
|
704
|
-
}
|
|
705
|
-
if (name === 'speed') {
|
|
706
|
-
const val = Number(value);
|
|
707
|
-
if (val && !isNaN(val)) {
|
|
708
|
-
this.setSpeed(val);
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
if (name === 'src') {
|
|
712
|
-
await this.load(value);
|
|
713
|
-
}
|
|
714
|
-
if (name === 'subframe') {
|
|
715
|
-
this.setSubframe(value === '' || Boolean(value));
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
static get observedProperties() {
|
|
719
|
-
return [
|
|
720
|
-
'playerState',
|
|
721
|
-
'_isSettingsOpen',
|
|
722
|
-
'_seeker',
|
|
723
|
-
'_currentAnimation',
|
|
724
|
-
'_animations'
|
|
725
|
-
];
|
|
726
|
-
}
|
|
727
|
-
// name: string, oldValue: string, newValue: string
|
|
728
|
-
propertyChangedCallback(name, _oldValue, value) {
|
|
729
|
-
if (!this.shadow) {
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
const togglePlay = this.shadow.querySelector('.togglePlay'), stop = this.shadow.querySelector('.stop'), prev = this.shadow.querySelector('.prev'), next = this.shadow.querySelector('.next'), seeker = this.shadow.querySelector('.seeker'), progress = this.shadow.querySelector('progress'), popover = this.shadow.querySelector('.popover'), convert = this.shadow.querySelector('.convert');
|
|
733
|
-
if (!(togglePlay instanceof HTMLButtonElement) || !(stop instanceof HTMLButtonElement) || !(next instanceof HTMLButtonElement) || !(prev instanceof HTMLButtonElement) || !(seeker instanceof HTMLInputElement) || !(progress instanceof HTMLProgressElement)) {
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
if (name === 'playerState') {
|
|
737
|
-
togglePlay.dataset.active = (value === PlayerState.Playing || value === PlayerState.Paused).toString();
|
|
738
|
-
stop.dataset.active = (value === PlayerState.Stopped).toString();
|
|
739
|
-
if (value === PlayerState.Playing) {
|
|
740
|
-
togglePlay.innerHTML = /* HTML */ `<svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M14.016 5.016H18v13.969h-3.984V5.016zM6 18.984V5.015h3.984v13.969H6z"/></svg>`;
|
|
741
|
-
} else {
|
|
742
|
-
togglePlay.innerHTML = /* HTML */ `<svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M8.016 5.016L18.985 12 8.016 18.984V5.015z"/></svg>`;
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
if (name === '_seeker' && typeof value === 'number') {
|
|
746
|
-
seeker.value = value.toString();
|
|
747
|
-
seeker.ariaValueNow = value.toString();
|
|
748
|
-
progress.value = value;
|
|
749
|
-
}
|
|
750
|
-
if (name === '_animations' && Array.isArray(value)) {
|
|
751
|
-
if (this._currentAnimation + 1 < value.length) {
|
|
752
|
-
next.hidden = false;
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
if (name === '_currentAnimation' && typeof value === 'number') {
|
|
756
|
-
if (value + 1 >= this._animations.length) {
|
|
757
|
-
next.hidden = true;
|
|
758
|
-
} else {
|
|
759
|
-
next.hidden = false;
|
|
760
|
-
}
|
|
761
|
-
if (value) {
|
|
762
|
-
prev.hidden = false;
|
|
763
|
-
} else {
|
|
764
|
-
prev.hidden = true;
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
if (name === '_isSettingsOpen' && typeof value === 'boolean' && popover instanceof HTMLDivElement && convert instanceof HTMLButtonElement) {
|
|
768
|
-
popover.hidden = !value;
|
|
769
|
-
convert.hidden = this._isDotLottie;
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
/**
|
|
773
|
-
* Whether to trigger next frame with scroll
|
|
774
|
-
*/ set animateOnScroll(value) {
|
|
775
|
-
this.setAttribute('animateOnScroll', (!!value).toString());
|
|
776
|
-
}
|
|
777
|
-
get animateOnScroll() {
|
|
778
|
-
const val = this.getAttribute('animateOnScroll');
|
|
779
|
-
if (val === 'true' || val === '' || val === '1') {
|
|
780
|
-
return true;
|
|
781
|
-
}
|
|
782
|
-
return false;
|
|
783
|
-
}
|
|
784
|
-
/**
|
|
785
|
-
* Autoplay
|
|
786
|
-
*/ set autoplay(value) {
|
|
787
|
-
this.setAttribute('autoplay', (!!value).toString());
|
|
788
|
-
}
|
|
789
|
-
get autoplay() {
|
|
790
|
-
const val = this.getAttribute('autoplay');
|
|
791
|
-
if (val === 'true' || val === '' || val === '1') {
|
|
792
|
-
return true;
|
|
793
|
-
}
|
|
794
|
-
return false;
|
|
795
|
-
}
|
|
796
|
-
/**
|
|
797
|
-
* Background color
|
|
798
|
-
*/ set background(value) {
|
|
799
|
-
this.setAttribute('background', value);
|
|
800
|
-
}
|
|
801
|
-
get background() {
|
|
802
|
-
return this.getAttribute('background') || 'transparent';
|
|
803
|
-
}
|
|
804
|
-
/**
|
|
805
|
-
* Show controls
|
|
806
|
-
*/ set controls(value) {
|
|
807
|
-
this.setAttribute('controls', (!!value).toString());
|
|
808
|
-
}
|
|
809
|
-
get controls() {
|
|
810
|
-
const val = this.getAttribute('controls');
|
|
811
|
-
if (val === 'true' || val === '' || val === '1') {
|
|
812
|
-
return true;
|
|
813
|
-
}
|
|
814
|
-
return false;
|
|
815
|
-
}
|
|
816
|
-
/**
|
|
817
|
-
* Number of times to loop
|
|
818
|
-
*/ set count(value) {
|
|
819
|
-
this.setAttribute('count', value.toString());
|
|
820
|
-
}
|
|
821
|
-
get count() {
|
|
822
|
-
const val = this.getAttribute('count');
|
|
823
|
-
if (val) {
|
|
824
|
-
return Number(val);
|
|
825
|
-
}
|
|
826
|
-
return 0;
|
|
827
|
-
}
|
|
828
|
-
/**
|
|
829
|
-
* Description for screen readers
|
|
830
|
-
*/ set description(value) {
|
|
831
|
-
if (value) {
|
|
832
|
-
this.setAttribute('description', value);
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
get description() {
|
|
836
|
-
return this.getAttribute('description');
|
|
837
|
-
}
|
|
838
|
-
/**
|
|
839
|
-
* Direction of animation
|
|
840
|
-
*/ set direction(value) {
|
|
841
|
-
this.setAttribute('direction', value.toString());
|
|
842
|
-
}
|
|
843
|
-
get direction() {
|
|
844
|
-
const val = Number(this.getAttribute('direction'));
|
|
845
|
-
if (val === -1) {
|
|
846
|
-
return val;
|
|
847
|
-
}
|
|
848
|
-
return 1;
|
|
849
|
-
}
|
|
850
|
-
/**
|
|
851
|
-
* Whether to play on mouseover
|
|
852
|
-
*/ set hover(value) {
|
|
853
|
-
this.setAttribute('hover', value.toString());
|
|
854
|
-
}
|
|
855
|
-
get hover() {
|
|
856
|
-
const val = this.getAttribute('hover');
|
|
857
|
-
if (val === 'true' || val === '' || val === '1') {
|
|
858
|
-
return true;
|
|
859
|
-
}
|
|
860
|
-
return false;
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* Pause between loop intrations, in miliseconds
|
|
864
|
-
*/ set intermission(value) {
|
|
865
|
-
this.setAttribute('intermission', value.toString());
|
|
866
|
-
}
|
|
867
|
-
get intermission() {
|
|
868
|
-
const val = Number(this.getAttribute('intermission'));
|
|
869
|
-
if (!isNaN(val)) {
|
|
870
|
-
return val;
|
|
871
|
-
}
|
|
872
|
-
return 0;
|
|
873
|
-
}
|
|
874
|
-
/**
|
|
875
|
-
* Loop animation
|
|
876
|
-
*/ set loop(value) {
|
|
877
|
-
this.setAttribute('loop', (!!value).toString());
|
|
878
|
-
}
|
|
879
|
-
get loop() {
|
|
880
|
-
const val = this.getAttribute('loop');
|
|
881
|
-
if (val === 'true' || val === '' || val === '1') {
|
|
882
|
-
return true;
|
|
883
|
-
}
|
|
884
|
-
return false;
|
|
885
|
-
}
|
|
886
|
-
/**
|
|
887
|
-
* Play mode
|
|
888
|
-
*/ set mode(value) {
|
|
889
|
-
this.setAttribute('mode', value.toString());
|
|
890
|
-
}
|
|
891
|
-
get mode() {
|
|
892
|
-
const val = this.getAttribute('mode');
|
|
893
|
-
if (val === PlayMode.Bounce) {
|
|
894
|
-
return val;
|
|
895
|
-
}
|
|
896
|
-
return PlayMode.Normal;
|
|
897
|
-
}
|
|
898
|
-
/**
|
|
899
|
-
* Resizing to container
|
|
900
|
-
*/ set objectfit(value) {
|
|
901
|
-
this.setAttribute('objectfit', value);
|
|
902
|
-
}
|
|
903
|
-
get objectfit() {
|
|
904
|
-
const val = this.getAttribute('objectfit');
|
|
905
|
-
if (val && Object.values(ObjectFit).includes(val)) {
|
|
906
|
-
return val;
|
|
907
|
-
}
|
|
908
|
-
return ObjectFit.Contain;
|
|
909
|
-
}
|
|
910
|
-
/**
|
|
911
|
-
* Resizing to container (Deprecated)
|
|
912
|
-
*/ set preserveAspectRatio(value) {
|
|
913
|
-
this.setAttribute('preserveAspectRatio', value || PreserveAspectRatio.Contain);
|
|
914
|
-
}
|
|
915
|
-
get preserveAspectRatio() {
|
|
916
|
-
const val = this.getAttribute('preserveAspectRatio');
|
|
917
|
-
if (val && Object.values(PreserveAspectRatio).includes(val)) {
|
|
918
|
-
return val;
|
|
919
|
-
}
|
|
920
|
-
return null;
|
|
921
|
-
}
|
|
922
|
-
/**
|
|
923
|
-
* Renderer to use: svg, canvas or html
|
|
924
|
-
*/ set renderer(value) {
|
|
925
|
-
this.setAttribute('renderer', value);
|
|
926
|
-
}
|
|
927
|
-
get renderer() {
|
|
928
|
-
const val = this.getAttribute('renderer');
|
|
929
|
-
if (val === 'canvas' || val === 'html') {
|
|
930
|
-
return val;
|
|
931
|
-
}
|
|
932
|
-
return 'svg';
|
|
933
|
-
}
|
|
934
|
-
/**
|
|
935
|
-
* Hide advanced controls
|
|
936
|
-
*/ set simple(value) {
|
|
937
|
-
this.setAttribute('simple', value.toString());
|
|
938
|
-
}
|
|
939
|
-
get simple() {
|
|
940
|
-
const val = this.getAttribute('simple');
|
|
941
|
-
if (val === 'true' || val === '' || val === '1') {
|
|
942
|
-
return true;
|
|
943
|
-
}
|
|
944
|
-
return false;
|
|
945
|
-
}
|
|
946
|
-
/**
|
|
947
|
-
* Speed
|
|
948
|
-
*/ set speed(value) {
|
|
949
|
-
this.setAttribute('speed', value?.toString());
|
|
950
|
-
}
|
|
951
|
-
get speed() {
|
|
952
|
-
const val = this.getAttribute('speed');
|
|
953
|
-
if (val !== null && !isNaN(Number(val))) {
|
|
954
|
-
return Number(val);
|
|
955
|
-
}
|
|
956
|
-
return 1;
|
|
957
|
-
}
|
|
958
|
-
/**
|
|
959
|
-
* Source, either path or JSON string
|
|
960
|
-
*/ set src(value) {
|
|
961
|
-
this.setAttribute('src', value || '');
|
|
962
|
-
}
|
|
963
|
-
get src() {
|
|
964
|
-
return this.getAttribute('src');
|
|
965
|
-
}
|
|
966
|
-
/**
|
|
967
|
-
* Subframe
|
|
968
|
-
*/ set subframe(value) {
|
|
969
|
-
this.setAttribute('subframe', (!!value).toString());
|
|
970
|
-
}
|
|
971
|
-
get subframe() {
|
|
972
|
-
const val = this.getAttribute('subframe');
|
|
973
|
-
if (val === 'true' || val === '' || val === '1') {
|
|
974
|
-
return true;
|
|
975
|
-
}
|
|
976
|
-
return false;
|
|
977
|
-
}
|
|
978
|
-
/**
|
|
979
|
-
* Get Multi-animation settings
|
|
980
|
-
* @returns { AnimationSettings[] }
|
|
981
|
-
*/ getMultiAnimationSettings() {
|
|
982
|
-
return this._multiAnimationSettings;
|
|
983
|
-
}
|
|
984
|
-
/**
|
|
985
|
-
* Set Multi-animation settings
|
|
986
|
-
* @param { AnimationSettings[] } settings
|
|
987
|
-
*/ setMultiAnimationSettings(settings) {
|
|
988
|
-
this._multiAnimationSettings = settings;
|
|
989
|
-
}
|
|
990
|
-
/**
|
|
991
|
-
* Set playback segment
|
|
992
|
-
* @param { AnimationSegment } settings
|
|
993
|
-
*/ setSegment(segment) {
|
|
994
|
-
this._segment = segment;
|
|
995
|
-
}
|
|
996
|
-
/**
|
|
997
|
-
* Get playback segment
|
|
998
|
-
* @returns { AnimationSegment }
|
|
999
|
-
*/ getSegment() {
|
|
1000
|
-
return this._segment;
|
|
1001
|
-
}
|
|
1002
|
-
/**
|
|
1003
|
-
* Get options from props
|
|
1004
|
-
* @returns { AnimationConfig }
|
|
1005
|
-
*/ _getOptions() {
|
|
1006
|
-
if (!this._container) {
|
|
1007
|
-
throw new Error('Container not rendered');
|
|
1008
|
-
}
|
|
1009
|
-
const preserveAspectRatio = this.preserveAspectRatio ?? (this.objectfit && aspectRatio(this.objectfit)), currentAnimationSettings = this._multiAnimationSettings?.length ? this._multiAnimationSettings?.[this._currentAnimation] : undefined, currentAnimationManifest = this._manifest.animations?.[this._currentAnimation];
|
|
1010
|
-
// Loop
|
|
1011
|
-
let loop = !!this.loop;
|
|
1012
|
-
if (currentAnimationManifest.loop !== undefined && this.loop === undefined) {
|
|
1013
|
-
loop = !!currentAnimationManifest.loop;
|
|
1014
|
-
}
|
|
1015
|
-
if (currentAnimationSettings?.loop !== undefined) {
|
|
1016
|
-
loop = !!currentAnimationSettings.loop;
|
|
1017
|
-
}
|
|
1018
|
-
// Autoplay
|
|
1019
|
-
let autoplay = !!this.autoplay;
|
|
1020
|
-
if (currentAnimationManifest.autoplay !== undefined && this.autoplay === undefined) {
|
|
1021
|
-
autoplay = !!currentAnimationManifest.autoplay;
|
|
1022
|
-
}
|
|
1023
|
-
if (currentAnimationSettings?.autoplay !== undefined) {
|
|
1024
|
-
autoplay = !!currentAnimationSettings.autoplay;
|
|
1025
|
-
}
|
|
1026
|
-
if (this.animateOnScroll) {
|
|
1027
|
-
autoplay = false;
|
|
1028
|
-
}
|
|
1029
|
-
// Segment
|
|
1030
|
-
let initialSegment = this._segment;
|
|
1031
|
-
if (this._segment?.every((val)=>val > 0)) {
|
|
1032
|
-
initialSegment = [
|
|
1033
|
-
this._segment[0] - 1,
|
|
1034
|
-
this._segment[1] - 1
|
|
1035
|
-
];
|
|
1036
|
-
}
|
|
1037
|
-
if (this._segment?.some((val)=>val < 0)) {
|
|
1038
|
-
initialSegment = undefined;
|
|
1039
|
-
}
|
|
1040
|
-
const options = {
|
|
1041
|
-
autoplay,
|
|
1042
|
-
container: this._container,
|
|
1043
|
-
initialSegment,
|
|
1044
|
-
loop,
|
|
1045
|
-
renderer: this.renderer,
|
|
1046
|
-
rendererSettings: {
|
|
1047
|
-
imagePreserveAspectRatio: preserveAspectRatio
|
|
1048
|
-
}
|
|
1049
|
-
};
|
|
1050
|
-
switch(this.renderer){
|
|
1051
|
-
case 'svg':
|
|
1052
|
-
options.rendererSettings = {
|
|
1053
|
-
...options.rendererSettings,
|
|
1054
|
-
hideOnTransparent: true,
|
|
1055
|
-
preserveAspectRatio,
|
|
1056
|
-
progressiveLoad: true
|
|
1057
|
-
};
|
|
1058
|
-
break;
|
|
1059
|
-
case 'canvas':
|
|
1060
|
-
options.rendererSettings = {
|
|
1061
|
-
...options.rendererSettings,
|
|
1062
|
-
clearCanvas: true,
|
|
1063
|
-
preserveAspectRatio,
|
|
1064
|
-
progressiveLoad: true
|
|
1065
|
-
};
|
|
1066
|
-
break;
|
|
1067
|
-
case 'html':
|
|
1068
|
-
options.rendererSettings = {
|
|
1069
|
-
...options.rendererSettings,
|
|
1070
|
-
hideOnTransparent: true
|
|
1071
|
-
};
|
|
1072
|
-
}
|
|
1073
|
-
return options;
|
|
1074
|
-
}
|
|
1075
|
-
/**
|
|
1076
|
-
* Add IntersectionObserver
|
|
1077
|
-
*/ _addIntersectionObserver() {
|
|
1078
|
-
if (!this._container || this._intersectionObserver || !('IntersectionObserver' in window)) {
|
|
1079
|
-
return;
|
|
1080
|
-
}
|
|
1081
|
-
this._intersectionObserver = new IntersectionObserver((entries)=>{
|
|
1082
|
-
for (const entry of entries){
|
|
1083
|
-
if (!entry.isIntersecting || document.hidden) {
|
|
1084
|
-
if (this.playerState === PlayerState.Playing) {
|
|
1085
|
-
this._freeze();
|
|
1086
|
-
}
|
|
1087
|
-
this._playerState.visible = false;
|
|
1088
|
-
continue;
|
|
1089
|
-
}
|
|
1090
|
-
if (!this.animateOnScroll && this.playerState === PlayerState.Frozen) {
|
|
1091
|
-
this.play();
|
|
1092
|
-
}
|
|
1093
|
-
if (!this._playerState.scrollY) {
|
|
1094
|
-
this._playerState.scrollY = scrollY;
|
|
1095
|
-
}
|
|
1096
|
-
this._playerState.visible = true;
|
|
1097
|
-
}
|
|
1098
|
-
});
|
|
1099
|
-
this._intersectionObserver.observe(this._container);
|
|
1100
|
-
}
|
|
1101
|
-
/**
|
|
1102
|
-
* Initialize Lottie Web player
|
|
1103
|
-
*/ async load(src) {
|
|
1104
|
-
if (!this.shadowRoot || !src) {
|
|
1105
|
-
return;
|
|
1106
|
-
}
|
|
1107
|
-
// Load the resource
|
|
1108
|
-
try {
|
|
1109
|
-
const { animations, isDotLottie, manifest } = await getAnimationData(src);
|
|
1110
|
-
if (!animations || animations.some((animation)=>!this._isLottie(animation))) {
|
|
1111
|
-
throw new Error('Broken or corrupted file');
|
|
1112
|
-
}
|
|
1113
|
-
this._isBounce = this.mode === PlayMode.Bounce;
|
|
1114
|
-
if (this._multiAnimationSettings?.length) {
|
|
1115
|
-
if (this._multiAnimationSettings[this._currentAnimation]?.mode) {
|
|
1116
|
-
this._isBounce = this._multiAnimationSettings[this._currentAnimation].mode === PlayMode.Bounce;
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
this._isDotLottie = !!isDotLottie;
|
|
1120
|
-
this._animations = animations;
|
|
1121
|
-
this._manifest = manifest ?? {
|
|
1122
|
-
animations: [
|
|
1123
|
-
{
|
|
1124
|
-
autoplay: !this.animateOnScroll && this.autoplay,
|
|
1125
|
-
direction: this.direction,
|
|
1126
|
-
id: useId(),
|
|
1127
|
-
loop: this.loop,
|
|
1128
|
-
mode: this.mode,
|
|
1129
|
-
speed: this.speed
|
|
1130
|
-
}
|
|
1131
|
-
]
|
|
1132
|
-
};
|
|
1133
|
-
// Clear previous animation, if any
|
|
1134
|
-
if (this._lottieInstance) {
|
|
1135
|
-
this._lottieInstance.destroy();
|
|
1136
|
-
}
|
|
1137
|
-
this.playerState = PlayerState.Stopped;
|
|
1138
|
-
if (!this.animateOnScroll && (this.autoplay || this._multiAnimationSettings?.[this._currentAnimation]?.autoplay)) {
|
|
1139
|
-
this.playerState = PlayerState.Playing;
|
|
1140
|
-
}
|
|
1141
|
-
// Initialize lottie player and load animation
|
|
1142
|
-
this._lottieInstance = Lottie.default.loadAnimation({
|
|
1143
|
-
...this._getOptions(),
|
|
1144
|
-
animationData: animations[this._currentAnimation]
|
|
1145
|
-
});
|
|
1146
|
-
} catch (err) {
|
|
1147
|
-
this._errorMessage = handleErrors(err).message;
|
|
1148
|
-
this.playerState = PlayerState.Error;
|
|
1149
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
|
|
1150
|
-
return;
|
|
1151
|
-
}
|
|
1152
|
-
this._addEventListeners();
|
|
1153
|
-
const speed = this._multiAnimationSettings?.[this._currentAnimation]?.speed ?? this.speed ?? this._manifest.animations[this._currentAnimation].speed, direction = this._multiAnimationSettings?.[this._currentAnimation]?.direction ?? this.direction ?? this._manifest.animations[this._currentAnimation].direction ?? 1;
|
|
1154
|
-
// Set initial playback speed and direction
|
|
1155
|
-
this._lottieInstance.setSpeed(speed);
|
|
1156
|
-
this._lottieInstance.setDirection(direction);
|
|
1157
|
-
this._lottieInstance.setSubframe(!!this.subframe);
|
|
1158
|
-
// Start playing if autoplay is enabled
|
|
1159
|
-
if (this.autoplay || this.animateOnScroll) {
|
|
1160
|
-
if (this.direction === -1) {
|
|
1161
|
-
this.seek('99%');
|
|
1162
|
-
}
|
|
1163
|
-
if (!('IntersectionObserver' in window)) {
|
|
1164
|
-
if (!this.animateOnScroll) {
|
|
1165
|
-
this.play();
|
|
1166
|
-
}
|
|
1167
|
-
this._playerState.visible = true;
|
|
1168
|
-
}
|
|
1169
|
-
this._addIntersectionObserver();
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
/**
|
|
1173
|
-
* Get Lottie Manifest
|
|
1174
|
-
*/ getManifest() {
|
|
1175
|
-
return this._manifest;
|
|
1176
|
-
}
|
|
1177
|
-
/**
|
|
1178
|
-
* Toggle event listeners
|
|
1179
|
-
*/ _toggleEventListeners(action) {
|
|
1180
|
-
const method = action === 'add' ? 'addEventListener' : 'removeEventListener';
|
|
1181
|
-
if (this._lottieInstance) {
|
|
1182
|
-
this._lottieInstance[method]('enterFrame', this._enterFrame);
|
|
1183
|
-
this._lottieInstance[method]('complete', this._complete);
|
|
1184
|
-
this._lottieInstance[method]('loopComplete', this._loopComplete);
|
|
1185
|
-
this._lottieInstance[method]('DOMLoaded', this._DOMLoaded);
|
|
1186
|
-
this._lottieInstance[method]('data_ready', this._dataReady);
|
|
1187
|
-
this._lottieInstance[method]('data_failed', this._dataFailed);
|
|
1188
|
-
}
|
|
1189
|
-
if (this._container && this.hover) {
|
|
1190
|
-
this._container[method]('mouseenter', this._mouseEnter);
|
|
1191
|
-
this._container[method]('mouseleave', this._mouseLeave);
|
|
1192
|
-
}
|
|
1193
|
-
window[method]('focus', this._handleWindowBlur, {
|
|
1194
|
-
capture: false,
|
|
1195
|
-
passive: true
|
|
1196
|
-
});
|
|
1197
|
-
window[method]('blur', this._handleWindowBlur, {
|
|
1198
|
-
capture: false,
|
|
1199
|
-
passive: true
|
|
1200
|
-
});
|
|
1201
|
-
if (this.animateOnScroll) {
|
|
1202
|
-
window[method]('scroll', this._handleScroll, {
|
|
1203
|
-
capture: true,
|
|
1204
|
-
passive: true
|
|
1205
|
-
});
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
/**
|
|
1209
|
-
* Add event listeners
|
|
1210
|
-
*/ _addEventListeners() {
|
|
1211
|
-
this._toggleEventListeners('add');
|
|
1212
|
-
}
|
|
1213
|
-
/**
|
|
1214
|
-
* Remove event listeners
|
|
1215
|
-
*/ _removeEventListeners() {
|
|
1216
|
-
this._toggleEventListeners('remove');
|
|
1217
|
-
}
|
|
1218
|
-
_loopComplete() {
|
|
1219
|
-
if (!this._lottieInstance) {
|
|
1220
|
-
return;
|
|
1221
|
-
}
|
|
1222
|
-
const { playDirection, // firstFrame,
|
|
1223
|
-
totalFrames } = this._lottieInstance, inPoint = this._segment ? this._segment[0] : 0, outPoint = this._segment ? this._segment[0] : totalFrames;
|
|
1224
|
-
if (this.count) {
|
|
1225
|
-
if (this._isBounce) {
|
|
1226
|
-
this._playerState.count += 0.5;
|
|
1227
|
-
} else {
|
|
1228
|
-
this._playerState.count += 1;
|
|
1229
|
-
}
|
|
1230
|
-
if (this._playerState.count >= this.count) {
|
|
1231
|
-
this.setLoop(false);
|
|
1232
|
-
this.playerState = PlayerState.Completed;
|
|
1233
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Complete));
|
|
1234
|
-
return;
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Loop));
|
|
1238
|
-
if (this._isBounce) {
|
|
1239
|
-
this._lottieInstance.goToAndStop(playDirection === -1 ? inPoint : outPoint * 0.99, true);
|
|
1240
|
-
this._lottieInstance.setDirection(playDirection * -1);
|
|
1241
|
-
return setTimeout(()=>{
|
|
1242
|
-
if (!this.animateOnScroll) {
|
|
1243
|
-
this._lottieInstance?.play();
|
|
1244
|
-
}
|
|
1245
|
-
}, this.intermission);
|
|
1246
|
-
}
|
|
1247
|
-
this._lottieInstance.goToAndStop(playDirection === -1 ? outPoint * 0.99 : inPoint, true);
|
|
1248
|
-
return setTimeout(()=>{
|
|
1249
|
-
if (!this.animateOnScroll) {
|
|
1250
|
-
this._lottieInstance?.play();
|
|
1251
|
-
}
|
|
1252
|
-
}, this.intermission);
|
|
1253
|
-
}
|
|
1254
|
-
_enterFrame() {
|
|
1255
|
-
if (!this._lottieInstance) {
|
|
1256
|
-
return;
|
|
1257
|
-
}
|
|
1258
|
-
const { currentFrame, totalFrames } = this._lottieInstance;
|
|
1259
|
-
this._seeker = Math.round(currentFrame / totalFrames * 100);
|
|
1260
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Frame, {
|
|
1261
|
-
detail: {
|
|
1262
|
-
frame: currentFrame,
|
|
1263
|
-
seeker: this._seeker
|
|
1264
|
-
}
|
|
1265
|
-
}));
|
|
1266
|
-
}
|
|
1267
|
-
_complete() {
|
|
1268
|
-
if (!this._lottieInstance) {
|
|
1269
|
-
return;
|
|
1270
|
-
}
|
|
1271
|
-
if (this._animations.length > 1) {
|
|
1272
|
-
if (this._multiAnimationSettings?.[this._currentAnimation + 1]?.autoplay) {
|
|
1273
|
-
return this.next();
|
|
1274
|
-
}
|
|
1275
|
-
if (this.loop && this._currentAnimation === this._animations.length - 1) {
|
|
1276
|
-
this._currentAnimation = 0;
|
|
1277
|
-
return this._switchInstance();
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
const { currentFrame, totalFrames } = this._lottieInstance;
|
|
1281
|
-
this._seeker = Math.round(currentFrame / totalFrames * 100);
|
|
1282
|
-
this.playerState = PlayerState.Completed;
|
|
1283
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Complete, {
|
|
1284
|
-
detail: {
|
|
1285
|
-
frame: currentFrame,
|
|
1286
|
-
seeker: this._seeker
|
|
1287
|
-
}
|
|
1288
|
-
}));
|
|
1289
|
-
}
|
|
1290
|
-
_DOMLoaded() {
|
|
1291
|
-
this._playerState.loaded = true;
|
|
1292
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Ready));
|
|
1293
|
-
}
|
|
1294
|
-
_dataReady() {
|
|
1295
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Load));
|
|
1296
|
-
}
|
|
1297
|
-
_dataFailed() {
|
|
1298
|
-
this.playerState = PlayerState.Error;
|
|
1299
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
|
|
1300
|
-
}
|
|
1301
|
-
_handleWindowBlur({ type }) {
|
|
1302
|
-
if (this.playerState === PlayerState.Playing && type === 'blur') {
|
|
1303
|
-
this._freeze();
|
|
1304
|
-
}
|
|
1305
|
-
if (this.playerState === PlayerState.Frozen && type === 'focus') {
|
|
1306
|
-
this.play();
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
/**
|
|
1310
|
-
* Handle MouseEnter
|
|
1311
|
-
*/ _mouseEnter() {
|
|
1312
|
-
if (this.hover && this.playerState !== PlayerState.Playing) {
|
|
1313
|
-
this.play();
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
/**
|
|
1317
|
-
* Handle MouseLeave
|
|
1318
|
-
*/ _mouseLeave() {
|
|
1319
|
-
if (this.hover && this.playerState === PlayerState.Playing) {
|
|
1320
|
-
this.stop();
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
/**
|
|
1324
|
-
* Handle visibility change events
|
|
1325
|
-
*/ _onVisibilityChange() {
|
|
1326
|
-
if (document.hidden && this.playerState === PlayerState.Playing) {
|
|
1327
|
-
this._freeze();
|
|
1328
|
-
return;
|
|
1329
|
-
}
|
|
1330
|
-
if (this.playerState === PlayerState.Frozen) {
|
|
1331
|
-
this.play();
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
/**
|
|
1335
|
-
* Handle scroll
|
|
1336
|
-
*/ _handleScroll() {
|
|
1337
|
-
if (!this.animateOnScroll || !this._lottieInstance) {
|
|
1338
|
-
return;
|
|
1339
|
-
}
|
|
1340
|
-
if (isServer()) {
|
|
1341
|
-
console.warn('DotLottie: Scroll animations might not work properly in a Server Side Rendering context. Try to wrap this in a client component.');
|
|
1342
|
-
return;
|
|
1343
|
-
}
|
|
1344
|
-
if (this._playerState.visible) {
|
|
1345
|
-
if (this._playerState.scrollTimeout) {
|
|
1346
|
-
clearTimeout(this._playerState.scrollTimeout);
|
|
1347
|
-
}
|
|
1348
|
-
this._playerState.scrollTimeout = setTimeout(()=>{
|
|
1349
|
-
this.playerState = PlayerState.Paused;
|
|
1350
|
-
}, 400);
|
|
1351
|
-
const adjustedScroll = scrollY > this._playerState.scrollY ? scrollY - this._playerState.scrollY : this._playerState.scrollY - scrollY, clampedScroll = Math.min(Math.max(adjustedScroll / 3, 1), this._lottieInstance.totalFrames * 3), roundedScroll = clampedScroll / 3;
|
|
1352
|
-
requestAnimationFrame(()=>{
|
|
1353
|
-
if (roundedScroll < (this._lottieInstance?.totalFrames ?? 0)) {
|
|
1354
|
-
this.playerState = PlayerState.Playing;
|
|
1355
|
-
this._lottieInstance?.goToAndStop(roundedScroll, true);
|
|
1356
|
-
} else {
|
|
1357
|
-
this.playerState = PlayerState.Paused;
|
|
1358
|
-
}
|
|
1359
|
-
});
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
/**
|
|
1363
|
-
* Handles click and drag actions on the progress track
|
|
1364
|
-
* @param { Event & { HTMLInputElement } } event
|
|
1365
|
-
*/ _handleSeekChange({ target }) {
|
|
1366
|
-
if (!(target instanceof HTMLInputElement) || !this._lottieInstance || isNaN(Number(target.value))) {
|
|
1367
|
-
return;
|
|
1368
|
-
}
|
|
1369
|
-
this.seek(Math.round(Number(target.value) / 100 * this._lottieInstance.totalFrames));
|
|
1370
|
-
}
|
|
1371
|
-
_isLottie(json) {
|
|
1372
|
-
const mandatory = [
|
|
1373
|
-
'v',
|
|
1374
|
-
'ip',
|
|
1375
|
-
'op',
|
|
1376
|
-
'layers',
|
|
1377
|
-
'fr',
|
|
1378
|
-
'w',
|
|
1379
|
-
'h'
|
|
1380
|
-
];
|
|
1381
|
-
return mandatory.every((field)=>Object.prototype.hasOwnProperty.call(json, field));
|
|
1382
|
-
}
|
|
1383
|
-
/**
|
|
1384
|
-
* Creates a new dotLottie file, by combinig several animations
|
|
1385
|
-
* @param { [ AnimationConfig ] } configs
|
|
1386
|
-
* @param { string } fileName
|
|
1387
|
-
* @param { boolean } shouldDownload Whether to trigger a download in the browser.
|
|
1388
|
-
* If set to false the function returns an ArrayBuffer. Defaults to true.
|
|
1389
|
-
*
|
|
1390
|
-
*/ async addAnimation(configs, fileName, shouldDownload = true) {
|
|
1391
|
-
// Initialize meta object for animation, with fallbacks for
|
|
1392
|
-
// when the method is called indepenently
|
|
1393
|
-
const { animations = [], manifest = {
|
|
1394
|
-
animations: this.src ? [
|
|
1395
|
-
{
|
|
1396
|
-
id: this._identifier
|
|
1397
|
-
}
|
|
1398
|
-
] : []
|
|
1399
|
-
} } = this.src ? await getAnimationData(this.src) : {};
|
|
1400
|
-
try {
|
|
1401
|
-
manifest.generator = pkg.name;
|
|
1402
|
-
for (const config of configs){
|
|
1403
|
-
const { url } = config, { animations: animationsToAdd } = await getAnimationData(url);
|
|
1404
|
-
if (!animationsToAdd) {
|
|
1405
|
-
throw new Error('No animation loaded');
|
|
1406
|
-
}
|
|
1407
|
-
if (manifest.animations.some(({ id })=>id === config.id)) {
|
|
1408
|
-
throw new Error('Duplicate id for animation');
|
|
1409
|
-
}
|
|
1410
|
-
manifest.animations = [
|
|
1411
|
-
...manifest.animations,
|
|
1412
|
-
{
|
|
1413
|
-
id: config.id
|
|
1414
|
-
}
|
|
1415
|
-
];
|
|
1416
|
-
animations?.push(...animationsToAdd);
|
|
1417
|
-
}
|
|
1418
|
-
return {
|
|
1419
|
-
result: await createDotLottie({
|
|
1420
|
-
animations,
|
|
1421
|
-
fileName,
|
|
1422
|
-
manifest,
|
|
1423
|
-
shouldDownload
|
|
1424
|
-
}),
|
|
1425
|
-
success: true
|
|
1426
|
-
};
|
|
1427
|
-
} catch (err) {
|
|
1428
|
-
return {
|
|
1429
|
-
error: handleErrors(err).message,
|
|
1430
|
-
success: false
|
|
1431
|
-
};
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
/**
|
|
1435
|
-
* Returns the lottie-web instance used in the component
|
|
1436
|
-
*/ getLottie() {
|
|
1437
|
-
return this._lottieInstance;
|
|
1438
|
-
}
|
|
1439
|
-
/**
|
|
1440
|
-
* Play
|
|
1441
|
-
*/ async play() {
|
|
1442
|
-
if (!this._lottieInstance) {
|
|
1443
|
-
return;
|
|
1444
|
-
}
|
|
1445
|
-
if (this.playerState) {
|
|
1446
|
-
this._playerState.prev = this.playerState;
|
|
1447
|
-
}
|
|
1448
|
-
try {
|
|
1449
|
-
this._lottieInstance.play();
|
|
1450
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Play));
|
|
1451
|
-
} finally{
|
|
1452
|
-
this.playerState = PlayerState.Playing;
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
/**
|
|
1456
|
-
* Pause
|
|
1457
|
-
*/ pause() {
|
|
1458
|
-
if (!this._lottieInstance) {
|
|
1459
|
-
return;
|
|
1460
|
-
}
|
|
1461
|
-
if (this.playerState) {
|
|
1462
|
-
this._playerState.prev = this.playerState;
|
|
1463
|
-
}
|
|
1464
|
-
try {
|
|
1465
|
-
this._lottieInstance.pause();
|
|
1466
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Pause));
|
|
1467
|
-
} finally{
|
|
1468
|
-
this.playerState = PlayerState.Paused;
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
/**
|
|
1472
|
-
* Stop
|
|
1473
|
-
*/ stop() {
|
|
1474
|
-
if (!this._lottieInstance) {
|
|
1475
|
-
return;
|
|
1476
|
-
}
|
|
1477
|
-
if (this.playerState) {
|
|
1478
|
-
this._playerState.prev = this.playerState;
|
|
1479
|
-
}
|
|
1480
|
-
this._playerState.count = 0;
|
|
1481
|
-
try {
|
|
1482
|
-
this._lottieInstance.stop();
|
|
1483
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Stop));
|
|
1484
|
-
} finally{
|
|
1485
|
-
this.playerState = PlayerState.Stopped;
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
/**
|
|
1489
|
-
* Destroy animation and element
|
|
1490
|
-
*/ destroy() {
|
|
1491
|
-
if (!this._lottieInstance) {
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
|
-
this.playerState = PlayerState.Destroyed;
|
|
1495
|
-
this._lottieInstance.destroy();
|
|
1496
|
-
this._lottieInstance = null;
|
|
1497
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Destroyed));
|
|
1498
|
-
this.remove();
|
|
1499
|
-
document.removeEventListener('visibilitychange', this._onVisibilityChange);
|
|
1500
|
-
}
|
|
1501
|
-
/**
|
|
1502
|
-
* Seek to a given frame
|
|
1503
|
-
* @param { number | string } value Frame to seek to
|
|
1504
|
-
*/ seek(value) {
|
|
1505
|
-
if (!this._lottieInstance) {
|
|
1506
|
-
return;
|
|
1507
|
-
}
|
|
1508
|
-
// Extract frame number from either number or percentage value
|
|
1509
|
-
const matches = value.toString().match(/^([0-9]+)(%?)$/);
|
|
1510
|
-
if (!matches) {
|
|
1511
|
-
return;
|
|
1512
|
-
}
|
|
1513
|
-
// Calculate and set the frame number
|
|
1514
|
-
const frame = Math.round(matches[2] === '%' ? this._lottieInstance.totalFrames * Number(matches[1]) / 100 : Number(matches[1]));
|
|
1515
|
-
// Set seeker to new frame number
|
|
1516
|
-
this._seeker = frame;
|
|
1517
|
-
// Send lottie player to the new frame
|
|
1518
|
-
if (this.playerState === PlayerState.Playing || this.playerState === PlayerState.Frozen && this._playerState.prev === PlayerState.Playing) {
|
|
1519
|
-
this._lottieInstance.goToAndPlay(frame, true);
|
|
1520
|
-
this.playerState = PlayerState.Playing;
|
|
1521
|
-
return;
|
|
1522
|
-
}
|
|
1523
|
-
this._lottieInstance.goToAndStop(frame, true);
|
|
1524
|
-
this._lottieInstance.pause();
|
|
1525
|
-
}
|
|
1526
|
-
/**
|
|
1527
|
-
* Snapshot and download the current frame as SVG
|
|
1528
|
-
*/ snapshot(shouldDownload = true, name = 'AM Lottie') {
|
|
1529
|
-
try {
|
|
1530
|
-
if (!this.shadowRoot) {
|
|
1531
|
-
throw new Error('Unknown error');
|
|
1532
|
-
}
|
|
1533
|
-
// Get SVG element and serialize markup
|
|
1534
|
-
const svgElement = this.shadowRoot.querySelector('.animation svg');
|
|
1535
|
-
if (!svgElement) {
|
|
1536
|
-
throw new Error('Could not retrieve animation from DOM');
|
|
1537
|
-
}
|
|
1538
|
-
const data = svgElement instanceof Node ? new XMLSerializer().serializeToString(svgElement) : null;
|
|
1539
|
-
if (!data) {
|
|
1540
|
-
throw new Error('Could not serialize SVG element');
|
|
1541
|
-
}
|
|
1542
|
-
if (shouldDownload) {
|
|
1543
|
-
download(data, {
|
|
1544
|
-
mimeType: 'image/svg+xml',
|
|
1545
|
-
name: `${getFilename(this.src || name)}-${frameOutput(this._seeker)}.svg`
|
|
1546
|
-
});
|
|
1547
|
-
}
|
|
1548
|
-
return data;
|
|
1549
|
-
} catch (err) {
|
|
1550
|
-
console.error(err);
|
|
1551
|
-
return null;
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
/**
|
|
1555
|
-
* Toggles subframe, for more smooth animations
|
|
1556
|
-
* @param { boolean } value Whether animation uses subframe
|
|
1557
|
-
*/ setSubframe(value) {
|
|
1558
|
-
if (!this._lottieInstance) {
|
|
1559
|
-
return;
|
|
1560
|
-
}
|
|
1561
|
-
this._lottieInstance.setSubframe(value);
|
|
1562
|
-
}
|
|
1563
|
-
/**
|
|
1564
|
-
* Dynamically set count for loops
|
|
1565
|
-
*/ setCount(value) {
|
|
1566
|
-
this.count = value;
|
|
1567
|
-
}
|
|
1568
|
-
/**
|
|
1569
|
-
* Freeze animation.
|
|
1570
|
-
* This internal state pauses animation and is used to differentiate between
|
|
1571
|
-
* user requested pauses and component instigated pauses.
|
|
1572
|
-
*/ _freeze() {
|
|
1573
|
-
if (!this._lottieInstance) {
|
|
1574
|
-
return;
|
|
1575
|
-
}
|
|
1576
|
-
if (this.playerState) {
|
|
1577
|
-
this._playerState.prev = this.playerState;
|
|
1578
|
-
}
|
|
1579
|
-
try {
|
|
1580
|
-
this._lottieInstance.pause();
|
|
1581
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Freeze));
|
|
1582
|
-
} finally{
|
|
1583
|
-
this.playerState = PlayerState.Frozen;
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
/**
|
|
1587
|
-
* Reload animation
|
|
1588
|
-
*/ async reload() {
|
|
1589
|
-
if (!this._lottieInstance || !this.src) {
|
|
1590
|
-
return;
|
|
1591
|
-
}
|
|
1592
|
-
this._lottieInstance.destroy();
|
|
1593
|
-
await this.load(this.src);
|
|
1594
|
-
}
|
|
1595
|
-
/**
|
|
1596
|
-
* Set animation playback speed
|
|
1597
|
-
* @param { number } value Playback speed
|
|
1598
|
-
*/ setSpeed(value = 1) {
|
|
1599
|
-
if (!this._lottieInstance) {
|
|
1600
|
-
return;
|
|
1601
|
-
}
|
|
1602
|
-
this._lottieInstance.setSpeed(value);
|
|
1603
|
-
}
|
|
1604
|
-
/**
|
|
1605
|
-
* Animation play direction
|
|
1606
|
-
* @param { AnimationDirection } value Animation direction
|
|
1607
|
-
*/ setDirection(value) {
|
|
1608
|
-
if (!this._lottieInstance) {
|
|
1609
|
-
return;
|
|
1610
|
-
}
|
|
1611
|
-
this._lottieInstance.setDirection(value);
|
|
1612
|
-
}
|
|
1613
|
-
/**
|
|
1614
|
-
* Set loop
|
|
1615
|
-
* @param { boolean } value
|
|
1616
|
-
*/ setLoop(value) {
|
|
1617
|
-
if (!this._lottieInstance) {
|
|
1618
|
-
return;
|
|
1619
|
-
}
|
|
1620
|
-
this._lottieInstance.setLoop(value);
|
|
1621
|
-
}
|
|
1622
|
-
/**
|
|
1623
|
-
* Toggle playing state
|
|
1624
|
-
*/ togglePlay() {
|
|
1625
|
-
if (!this._lottieInstance) {
|
|
1626
|
-
return;
|
|
1627
|
-
}
|
|
1628
|
-
const { currentFrame, playDirection, totalFrames } = this._lottieInstance;
|
|
1629
|
-
if (this.playerState === PlayerState.Playing) {
|
|
1630
|
-
return this.pause();
|
|
1631
|
-
}
|
|
1632
|
-
if (this.playerState !== PlayerState.Completed) {
|
|
1633
|
-
return this.play();
|
|
1634
|
-
}
|
|
1635
|
-
this.playerState = PlayerState.Playing;
|
|
1636
|
-
if (this._isBounce) {
|
|
1637
|
-
this.setDirection(playDirection * -1);
|
|
1638
|
-
return this._lottieInstance.goToAndPlay(currentFrame, true);
|
|
1639
|
-
}
|
|
1640
|
-
if (playDirection === -1) {
|
|
1641
|
-
return this._lottieInstance.goToAndPlay(totalFrames, true);
|
|
1642
|
-
}
|
|
1643
|
-
return this._lottieInstance.goToAndPlay(0, true);
|
|
1644
|
-
}
|
|
1645
|
-
/**
|
|
1646
|
-
* Toggle loop
|
|
1647
|
-
*/ toggleLoop() {
|
|
1648
|
-
const val = !this.loop;
|
|
1649
|
-
this.loop = val;
|
|
1650
|
-
this.setLoop(val);
|
|
1651
|
-
}
|
|
1652
|
-
/**
|
|
1653
|
-
* Toggle Boomerang
|
|
1654
|
-
*/ toggleBoomerang() {
|
|
1655
|
-
const curr = this._multiAnimationSettings?.[this._currentAnimation];
|
|
1656
|
-
if (curr?.mode !== undefined) {
|
|
1657
|
-
if (curr.mode === PlayMode.Normal) {
|
|
1658
|
-
curr.mode = PlayMode.Bounce;
|
|
1659
|
-
this._isBounce = true;
|
|
1660
|
-
return;
|
|
1661
|
-
}
|
|
1662
|
-
curr.mode = PlayMode.Normal;
|
|
1663
|
-
this._isBounce = false;
|
|
1664
|
-
return;
|
|
1665
|
-
}
|
|
1666
|
-
if (this.mode === PlayMode.Normal) {
|
|
1667
|
-
this.mode = PlayMode.Bounce;
|
|
1668
|
-
this._isBounce = true;
|
|
1669
|
-
return;
|
|
1670
|
-
}
|
|
1671
|
-
this.mode = PlayMode.Normal;
|
|
1672
|
-
this._isBounce = false;
|
|
1673
|
-
}
|
|
1674
|
-
/**
|
|
1675
|
-
* Toggle show Settings
|
|
1676
|
-
*/ _toggleSettings(flag) {
|
|
1677
|
-
if (flag === undefined) {
|
|
1678
|
-
this._isSettingsOpen = !this._isSettingsOpen;
|
|
1679
|
-
return;
|
|
1680
|
-
}
|
|
1681
|
-
this._isSettingsOpen = flag;
|
|
1682
|
-
}
|
|
1683
|
-
/**
|
|
1684
|
-
* Handle blur
|
|
1685
|
-
*/ _handleBlur() {
|
|
1686
|
-
setTimeout(()=>this._toggleSettings(false), 200);
|
|
1687
|
-
}
|
|
1688
|
-
_switchInstance(isPrevious = false) {
|
|
1689
|
-
// Bail early if there is not animation to play
|
|
1690
|
-
if (!this._animations[this._currentAnimation]) {
|
|
1691
|
-
return;
|
|
1692
|
-
}
|
|
1693
|
-
try {
|
|
1694
|
-
// Clear previous animation
|
|
1695
|
-
if (this._lottieInstance) {
|
|
1696
|
-
this._lottieInstance.destroy();
|
|
1697
|
-
}
|
|
1698
|
-
// Re-initialize lottie player
|
|
1699
|
-
this._lottieInstance = Lottie.default.loadAnimation({
|
|
1700
|
-
...this._getOptions(),
|
|
1701
|
-
animationData: this._animations[this._currentAnimation]
|
|
1702
|
-
});
|
|
1703
|
-
// Check play mode for current animation
|
|
1704
|
-
if (this._multiAnimationSettings?.[this._currentAnimation]?.mode) {
|
|
1705
|
-
this._isBounce = this._multiAnimationSettings[this._currentAnimation].mode === PlayMode.Bounce;
|
|
1706
|
-
}
|
|
1707
|
-
// Remove event listeners to new Lottie instance, and add new
|
|
1708
|
-
this._removeEventListeners();
|
|
1709
|
-
this._addEventListeners();
|
|
1710
|
-
this.dispatchEvent(new CustomEvent(isPrevious ? PlayerEvents.Previous : PlayerEvents.Next));
|
|
1711
|
-
if (this._multiAnimationSettings?.[this._currentAnimation]?.autoplay ?? this.autoplay) {
|
|
1712
|
-
if (this.animateOnScroll) {
|
|
1713
|
-
this._lottieInstance?.goToAndStop(0, true);
|
|
1714
|
-
this.playerState = PlayerState.Paused;
|
|
1715
|
-
return;
|
|
1716
|
-
}
|
|
1717
|
-
this._lottieInstance?.goToAndPlay(0, true);
|
|
1718
|
-
this.playerState = PlayerState.Playing;
|
|
1719
|
-
return;
|
|
1720
|
-
}
|
|
1721
|
-
this._lottieInstance?.goToAndStop(0, true);
|
|
1722
|
-
this.playerState = PlayerState.Stopped;
|
|
1723
|
-
} catch (err) {
|
|
1724
|
-
this._errorMessage = handleErrors(err).message;
|
|
1725
|
-
this.playerState = PlayerState.Error;
|
|
1726
|
-
this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
|
|
1727
|
-
}
|
|
1728
|
-
}
|
|
1729
|
-
/**
|
|
1730
|
-
* Skip to next animation
|
|
1731
|
-
*/ next() {
|
|
1732
|
-
this._currentAnimation++;
|
|
1733
|
-
this._switchInstance();
|
|
1734
|
-
}
|
|
1735
|
-
/**
|
|
1736
|
-
* Skip to previous animation
|
|
1737
|
-
*/ prev() {
|
|
1738
|
-
this._currentAnimation--;
|
|
1739
|
-
this._switchInstance(true);
|
|
1740
|
-
}
|
|
1741
|
-
async convert({ animations, fileName, manifest, shouldDownload = true, src, typeCheck }) {
|
|
1742
|
-
if (typeCheck || this._isDotLottie) {
|
|
1743
|
-
return createJSON({
|
|
1744
|
-
animation: (await getAnimationData(src || this.src))?.animations?.[0],
|
|
1745
|
-
fileName: `${getFilename(fileName || this.src || 'converted')}.json`,
|
|
1746
|
-
shouldDownload
|
|
1747
|
-
});
|
|
1748
|
-
}
|
|
1749
|
-
return createDotLottie({
|
|
1750
|
-
animations: animations || (await getAnimationData(this.src))?.animations,
|
|
1751
|
-
fileName: `${getFilename(fileName || this.src || 'converted')}.lottie`,
|
|
1752
|
-
manifest: {
|
|
1753
|
-
...manifest || this._manifest,
|
|
1754
|
-
generator: pkg.name
|
|
1755
|
-
},
|
|
1756
|
-
shouldDownload
|
|
1757
|
-
});
|
|
1758
|
-
}
|
|
1759
|
-
/**
|
|
1760
|
-
* Return the styles for the component
|
|
1761
|
-
*/ static get styles() {
|
|
1762
|
-
const styleSheet = new CSSStyleSheet();
|
|
1763
|
-
styleSheet.replace(css_248z);
|
|
1764
|
-
return styleSheet;
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
|
|
1768
|
-
/**
|
|
1769
|
-
* Expose DotLottiePlayer class as global variable
|
|
1770
|
-
* @returns { DotLottiePlayer }
|
|
1771
|
-
*/ globalThis.dotLottiePlayer = ()=>new DotLottiePlayer();
|
|
1772
|
-
const tagName = 'dotlottie-player';
|
|
1773
|
-
if (!isServer()) {
|
|
1774
|
-
customElements.define('dotlottie-player', DotLottiePlayer);
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
export { PlayMode, PlayerEvents, PlayerState, DotLottiePlayer as default, tagName };
|