pixi-effects 0.27.1 → 0.27.2
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 +7 -0
- package/README.md +6 -6
- package/ai/chat-template.html +3 -3
- package/dist/Composition-DRCTWIYH.cjs +16 -0
- package/dist/{Composition-YW2G6EXL.cjs.map → Composition-DRCTWIYH.cjs.map} +1 -1
- package/dist/Composition-TZHVYIGH.js +7 -0
- package/dist/{Composition-BJVY5HP7.js.map → Composition-TZHVYIGH.js.map} +1 -1
- package/dist/{chunk-X42BGR6P.js → chunk-BQNNZEAX.js} +4 -4
- package/dist/{chunk-X42BGR6P.js.map → chunk-BQNNZEAX.js.map} +1 -1
- package/dist/{chunk-VH5R473P.cjs → chunk-C7HJJ7MZ.cjs} +61 -61
- package/dist/{chunk-VH5R473P.cjs.map → chunk-C7HJJ7MZ.cjs.map} +1 -1
- package/dist/{chunk-AR3HVHKF.js → chunk-K3F2YKL4.js} +3 -3
- package/dist/{chunk-AR3HVHKF.js.map → chunk-K3F2YKL4.js.map} +1 -1
- package/dist/{chunk-ETKTRQL2.cjs → chunk-YOV6MEXH.cjs} +4 -4
- package/dist/{chunk-ETKTRQL2.cjs.map → chunk-YOV6MEXH.cjs.map} +1 -1
- package/dist/index.cjs +32 -32
- package/dist/index.js +5 -5
- package/dist/loader.css +1 -1
- package/dist/{music-YPUZTWTN.cjs → music-6MTHQEXS.cjs} +269 -99
- package/dist/music-6MTHQEXS.cjs.map +1 -0
- package/dist/{music-JVRNXHQ5.js → music-72YJAMXH.js} +269 -99
- package/dist/music-72YJAMXH.js.map +1 -0
- package/dist/three.cjs +5 -5
- package/dist/three.js +1 -1
- package/llms-full.txt +1 -1
- package/package.json +1 -1
- package/skills/pixi-effects/SKILL.md +1 -1
- package/skills/pixi-effects/template.html +6 -6
- package/dist/Composition-BJVY5HP7.js +0 -7
- package/dist/Composition-YW2G6EXL.cjs +0 -16
- package/dist/music-JVRNXHQ5.js.map +0 -1
- package/dist/music-YPUZTWTN.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkC7HJJ7MZ_cjs = require('./chunk-C7HJJ7MZ.cjs');
|
|
4
|
+
var chunkYOV6MEXH_cjs = require('./chunk-YOV6MEXH.cjs');
|
|
5
5
|
var chunkP4GY3Z4G_cjs = require('./chunk-P4GY3Z4G.cjs');
|
|
6
6
|
var chunkZMAD3KJU_cjs = require('./chunk-ZMAD3KJU.cjs');
|
|
7
7
|
var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
|
|
@@ -1485,8 +1485,8 @@ function expandTransitions(spec) {
|
|
|
1485
1485
|
}
|
|
1486
1486
|
const transitions = out.transitions;
|
|
1487
1487
|
const sequences = out.sequences ?? [];
|
|
1488
|
-
const remap = out.duration !== void 0 ?
|
|
1489
|
-
const parentDuration = remap ?
|
|
1488
|
+
const remap = out.duration !== void 0 ? chunkYOV6MEXH_cjs.timeRemapOf(out) : null;
|
|
1489
|
+
const parentDuration = remap ? chunkYOV6MEXH_cjs.contentLength(remap, out.duration) : out.duration ?? Infinity;
|
|
1490
1490
|
const compW = out.width;
|
|
1491
1491
|
const compH = out.height;
|
|
1492
1492
|
const threeDByName = new Set(sequences.filter((s) => s.name && s.threeD).map((s) => s.name));
|
|
@@ -1554,16 +1554,16 @@ function expandTransitions(spec) {
|
|
|
1554
1554
|
if (toUses > 1) {
|
|
1555
1555
|
throw new Error(`pixi-effects: ${tag} sequence "${t.to}" is used as \`to\` in more than one transition`);
|
|
1556
1556
|
}
|
|
1557
|
-
const tStart =
|
|
1557
|
+
const tStart = chunkYOV6MEXH_cjs.resolveAt(t.at, parentDuration);
|
|
1558
1558
|
const tEnd = tStart + t.duration;
|
|
1559
1559
|
const fromSeq = fromEntry.seq;
|
|
1560
|
-
const fromStart =
|
|
1560
|
+
const fromStart = chunkYOV6MEXH_cjs.resolveAt(fromSeq.at, parentDuration);
|
|
1561
1561
|
const fromEnd = fromStart + (fromSeq.duration ?? parentDuration);
|
|
1562
1562
|
if (tStart < fromStart - EPS || tEnd > fromEnd + EPS) {
|
|
1563
1563
|
throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`from\` "${t.from}" (lives [${fromStart}, ${fromEnd}], so it ends at ${fromEnd})`);
|
|
1564
1564
|
}
|
|
1565
1565
|
const toSeq = toEntry.seq;
|
|
1566
|
-
const toStart =
|
|
1566
|
+
const toStart = chunkYOV6MEXH_cjs.resolveAt(toSeq.at, parentDuration);
|
|
1567
1567
|
const toEnd = toStart + (toSeq.duration ?? parentDuration);
|
|
1568
1568
|
if (tStart < toStart - EPS || tEnd > toEnd + EPS) {
|
|
1569
1569
|
throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`to\` "${t.to}" (lives [${toStart}, ${toEnd}], so it starts at ${toStart})`);
|
|
@@ -1623,7 +1623,7 @@ function wrapAsFullComposition(seq, compW, compH) {
|
|
|
1623
1623
|
delete inner.at;
|
|
1624
1624
|
delete inner.duration;
|
|
1625
1625
|
const m = inner.mask;
|
|
1626
|
-
const carriesMatte = m !== void 0 &&
|
|
1626
|
+
const carriesMatte = m !== void 0 && chunkC7HJJ7MZ_cjs.maskSourceOf(m).kind === "refs";
|
|
1627
1627
|
if (carriesMatte) delete inner.mask;
|
|
1628
1628
|
return {
|
|
1629
1629
|
...carriesMatte ? { mask: m } : {},
|
|
@@ -1950,7 +1950,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1950
1950
|
const group = parentScene ?? (name !== void 0 && blending.has(name) ? name : void 0);
|
|
1951
1951
|
if (group) scene.set(info, group);
|
|
1952
1952
|
if (zero || seq.showsNothingYet) scaledToNothing.add(info);
|
|
1953
|
-
if (seq instanceof
|
|
1953
|
+
if (seq instanceof chunkC7HJJ7MZ_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
|
|
1954
1954
|
});
|
|
1955
1955
|
};
|
|
1956
1956
|
walk2(root, "", false, true);
|
|
@@ -2011,10 +2011,10 @@ function walk(comp, parentStart, parentEnd, depth, prefix, rows, transitions, lo
|
|
|
2011
2011
|
const start = parentStart + (seq.at ?? 0);
|
|
2012
2012
|
const end = Math.min(parentEnd, seq.duration !== void 0 ? start + seq.duration : parentEnd);
|
|
2013
2013
|
const span = end - start;
|
|
2014
|
-
const keys = (seq.spec.keyframes ?? []).map((kf) => round(start +
|
|
2014
|
+
const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunkYOV6MEXH_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
|
|
2015
2015
|
const row = { path: prefix + name, name, type: seq.spec.type, depth, start: round(start), end: round(end), keys, detail: detailOf(seq), ...local ? { local } : {} };
|
|
2016
2016
|
const inner = [];
|
|
2017
|
-
const isComp = seq instanceof
|
|
2017
|
+
const isComp = seq instanceof chunkC7HJJ7MZ_cjs.CompositionSequence;
|
|
2018
2018
|
if (isComp) {
|
|
2019
2019
|
const label = seq.remapLabel();
|
|
2020
2020
|
walk(seq, label ? 0 : start, label ? seq.contentSpan : end, depth + 1, prefix + name + "/", inner, transitions, label ? `${name} ${label}` : local);
|
|
@@ -2671,8 +2671,8 @@ var Movie = class {
|
|
|
2671
2671
|
this.stops = normalizeStops(options.composition?.stops, this.duration, this.frameRate);
|
|
2672
2672
|
this._posterFrame = poster.frame;
|
|
2673
2673
|
this.background = options.background ?? "#000000";
|
|
2674
|
-
this.timeline =
|
|
2675
|
-
|
|
2674
|
+
this.timeline = chunkYOV6MEXH_cjs.createTimeline({ paused: true, defaults: { ease: "none" } });
|
|
2675
|
+
chunkYOV6MEXH_cjs.lengthen(this.timeline, this.duration);
|
|
2676
2676
|
const baseAppOptions = {
|
|
2677
2677
|
width: this.width,
|
|
2678
2678
|
height: this.height,
|
|
@@ -2731,7 +2731,7 @@ var Movie = class {
|
|
|
2731
2731
|
height: options.composition.height ?? this.height,
|
|
2732
2732
|
duration: options.composition.duration ?? this.duration
|
|
2733
2733
|
} : void 0;
|
|
2734
|
-
await
|
|
2734
|
+
await chunkYOV6MEXH_cjs.ensureFilterLibrary(seededComposition);
|
|
2735
2735
|
const userComposition = seededComposition ? expandTransitions(seededComposition) : void 0;
|
|
2736
2736
|
const rootSeqSpec = {
|
|
2737
2737
|
type: "composition",
|
|
@@ -2741,7 +2741,7 @@ var Movie = class {
|
|
|
2741
2741
|
...userComposition
|
|
2742
2742
|
};
|
|
2743
2743
|
if (userComposition) carryTransitionWindows(userComposition, rootSeqSpec);
|
|
2744
|
-
const composition = new
|
|
2744
|
+
const composition = new chunkC7HJJ7MZ_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
|
|
2745
2745
|
lp.begin("build", countLayers(rootSeqSpec));
|
|
2746
2746
|
await composition.build();
|
|
2747
2747
|
this._rootSequence = composition;
|
|
@@ -3468,8 +3468,8 @@ function splitText(text, style = {}, opts = {}) {
|
|
|
3468
3468
|
|
|
3469
3469
|
// src/presets/_ease.ts
|
|
3470
3470
|
function parseEase2(name) {
|
|
3471
|
-
|
|
3472
|
-
return
|
|
3471
|
+
chunkYOV6MEXH_cjs.checkEase(name, "a preset");
|
|
3472
|
+
return chunkYOV6MEXH_cjs.parseEase(name);
|
|
3473
3473
|
}
|
|
3474
3474
|
|
|
3475
3475
|
// src/presets/kenBurns.ts
|
|
@@ -3604,17 +3604,17 @@ function orbit(opts) {
|
|
|
3604
3604
|
throw new Error("pixi-effects: orbit() cannot combine `radius` with `dollyZoom` \u2014 the radius follows the animated fov");
|
|
3605
3605
|
}
|
|
3606
3606
|
const [cx, cy] = opts.center ?? [width / 2, height / 2];
|
|
3607
|
-
const fixedR = opts.radius ??
|
|
3607
|
+
const fixedR = opts.radius ?? chunkYOV6MEXH_cjs.homeDistance(height, fov ?? chunkYOV6MEXH_cjs.DEFAULT_FOV);
|
|
3608
3608
|
const start = opts.start ?? -degrees / 2;
|
|
3609
3609
|
const steps = Math.max(1, Math.round(duration * stepsPerSecond));
|
|
3610
3610
|
const easeFn = parseEase2(ease);
|
|
3611
3611
|
const dollyEase = dolly ? parseEase2(dolly.ease ?? ease) : null;
|
|
3612
3612
|
const pos = (i) => {
|
|
3613
3613
|
const p = i / steps;
|
|
3614
|
-
const a = (start + degrees * easeFn(p)) *
|
|
3614
|
+
const a = (start + degrees * easeFn(p)) * chunkYOV6MEXH_cjs.DEG;
|
|
3615
3615
|
if (!dolly) return { x: cx + fixedR * Math.sin(a), z: fixedR * Math.cos(a) };
|
|
3616
3616
|
const f = dolly.from + (dolly.to - dolly.from) * dollyEase(p);
|
|
3617
|
-
const R =
|
|
3617
|
+
const R = chunkYOV6MEXH_cjs.homeDistance(height, f);
|
|
3618
3618
|
return { x: cx + R * Math.sin(a), z: R * Math.cos(a), fov: f };
|
|
3619
3619
|
};
|
|
3620
3620
|
const keyframes = [];
|
|
@@ -3669,7 +3669,7 @@ function particles(opts) {
|
|
|
3669
3669
|
const round3 = (v) => Math.round(v * 1e6) / 1e6;
|
|
3670
3670
|
const out = [];
|
|
3671
3671
|
for (let i = 0; i < count; i++) {
|
|
3672
|
-
const r =
|
|
3672
|
+
const r = chunkYOV6MEXH_cjs.random(seed * 1000003 + i * 7919 + 17);
|
|
3673
3673
|
const pick = ([a2, b]) => a2 + r() * (b - a2);
|
|
3674
3674
|
const born = at + r() * emit;
|
|
3675
3675
|
const lifetime = pick(life);
|
|
@@ -3682,7 +3682,7 @@ function particles(opts) {
|
|
|
3682
3682
|
const turn = spin ? pick(spin) : 0;
|
|
3683
3683
|
const startAngle = spin ? r() * 360 : 0;
|
|
3684
3684
|
const swayAmp = sway?.amp ?? 0, swayFreq = sway?.freq ?? 1;
|
|
3685
|
-
const n0 = sway ?
|
|
3685
|
+
const n0 = sway ? chunkYOV6MEXH_cjs.noise(0, seed * 1000003 + i) : 0;
|
|
3686
3686
|
const at_ = (t) => {
|
|
3687
3687
|
const axis = (p0, v0, acc) => {
|
|
3688
3688
|
if (drag > 0) {
|
|
@@ -3691,7 +3691,7 @@ function particles(opts) {
|
|
|
3691
3691
|
}
|
|
3692
3692
|
return p0 + v0 * t + 0.5 * acc * t * t;
|
|
3693
3693
|
};
|
|
3694
|
-
const sw = sway ? swayAmp * (
|
|
3694
|
+
const sw = sway ? swayAmp * (chunkYOV6MEXH_cjs.noise(t * swayFreq, seed * 1000003 + i) - n0) : 0;
|
|
3695
3695
|
return { x: axis(x0, vx, wind) + sw, y: axis(y0, vy, gravity) };
|
|
3696
3696
|
};
|
|
3697
3697
|
const kfs = [];
|
|
@@ -3753,7 +3753,7 @@ function followPath(opts) {
|
|
|
3753
3753
|
if (steps > MAX_STEPS) throw new Error(`followPath(): ${steps} samples is too many (max ${MAX_STEPS}); lower frameRate or duration`);
|
|
3754
3754
|
const segments = [];
|
|
3755
3755
|
let total = 0;
|
|
3756
|
-
for (const line of
|
|
3756
|
+
for (const line of chunkYOV6MEXH_cjs.flattenSvgPath(d)) {
|
|
3757
3757
|
const p = line.closed ? [...line.pts, line.pts[0], line.pts[1]] : line.pts;
|
|
3758
3758
|
for (let i = 2; i < p.length; i += 2) {
|
|
3759
3759
|
const len = Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]);
|
|
@@ -3907,7 +3907,7 @@ function distances(n, from, grid, seed) {
|
|
|
3907
3907
|
if (n === 0) return [];
|
|
3908
3908
|
if (from === "random") {
|
|
3909
3909
|
const order = Array.from({ length: n }, (_, i) => i);
|
|
3910
|
-
const r =
|
|
3910
|
+
const r = chunkYOV6MEXH_cjs.random(seed);
|
|
3911
3911
|
for (let i = n - 1; i > 0; i--) {
|
|
3912
3912
|
const j = Math.floor(r() * (i + 1));
|
|
3913
3913
|
[order[i], order[j]] = [order[j], order[i]];
|
|
@@ -3969,7 +3969,7 @@ function wiggle(opts) {
|
|
|
3969
3969
|
to[n] = p.around;
|
|
3970
3970
|
return;
|
|
3971
3971
|
}
|
|
3972
|
-
const off = (
|
|
3972
|
+
const off = (chunkYOV6MEXH_cjs.rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
|
|
3973
3973
|
to[n] = typeof p.around === "number" ? p.around + off : `(${p.around}) ${off < 0 ? "-" : "+"} ${Math.abs(off)}`;
|
|
3974
3974
|
});
|
|
3975
3975
|
out.push({ at: at + s * stepLen, to, duration: stepLen, ease });
|
|
@@ -4333,7 +4333,7 @@ async function audioEnvelope(source, options = {}) {
|
|
|
4333
4333
|
|
|
4334
4334
|
// src/audio/musicEnvelope.ts
|
|
4335
4335
|
async function musicEnvelope(music, options = {}) {
|
|
4336
|
-
const { resolveMusic, renderMusic, musicLength, musicBeatTimes, TempoMap } = await import('./music-
|
|
4336
|
+
const { resolveMusic, renderMusic, musicLength, musicBeatTimes, TempoMap } = await import('./music-6MTHQEXS.cjs');
|
|
4337
4337
|
const messages = [];
|
|
4338
4338
|
const m = resolveMusic(music, "musicEnvelope()", (msg) => messages.push(msg));
|
|
4339
4339
|
if (!m) throw new Error(`pixi-effects: musicEnvelope(): ${messages.join(" ") || "the music has nothing to play"}`);
|
|
@@ -4346,7 +4346,7 @@ async function musicEnvelope(music, options = {}) {
|
|
|
4346
4346
|
|
|
4347
4347
|
// src/audio/musicBuffer.ts
|
|
4348
4348
|
async function musicBuffer(music, options = {}) {
|
|
4349
|
-
const { resolveMusic, renderMusic, musicLength } = await import('./music-
|
|
4349
|
+
const { resolveMusic, renderMusic, musicLength } = await import('./music-6MTHQEXS.cjs');
|
|
4350
4350
|
const messages = [];
|
|
4351
4351
|
const m = resolveMusic(music, "musicBuffer()", (msg) => messages.push(msg));
|
|
4352
4352
|
if (!m) throw new Error(`pixi-effects: musicBuffer(): ${messages.join(" ") || "the music has nothing to play"}`);
|
|
@@ -4444,19 +4444,19 @@ function withFade(spec, opts) {
|
|
|
4444
4444
|
|
|
4445
4445
|
Object.defineProperty(exports, "noise", {
|
|
4446
4446
|
enumerable: true,
|
|
4447
|
-
get: function () { return
|
|
4447
|
+
get: function () { return chunkYOV6MEXH_cjs.noise; }
|
|
4448
4448
|
});
|
|
4449
4449
|
Object.defineProperty(exports, "rand", {
|
|
4450
4450
|
enumerable: true,
|
|
4451
|
-
get: function () { return
|
|
4451
|
+
get: function () { return chunkYOV6MEXH_cjs.rand; }
|
|
4452
4452
|
});
|
|
4453
4453
|
Object.defineProperty(exports, "random", {
|
|
4454
4454
|
enumerable: true,
|
|
4455
|
-
get: function () { return
|
|
4455
|
+
get: function () { return chunkYOV6MEXH_cjs.random; }
|
|
4456
4456
|
});
|
|
4457
4457
|
Object.defineProperty(exports, "registerSequenceType", {
|
|
4458
4458
|
enumerable: true,
|
|
4459
|
-
get: function () { return
|
|
4459
|
+
get: function () { return chunkYOV6MEXH_cjs.registerSequenceType; }
|
|
4460
4460
|
});
|
|
4461
4461
|
exports.Movie = Movie;
|
|
4462
4462
|
exports.animateText = animateText;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CompositionSequence, maskSourceOf } from './chunk-
|
|
2
|
-
import { createTimeline, lengthen, ensureFilterLibrary, checkEase, parseEase, homeDistance, DEFAULT_FOV, random, noise, flattenSvgPath, rand, DEG, timeRemapOf, contentLength, resolveAt } from './chunk-
|
|
3
|
-
export { noise, rand, random, registerSequenceType } from './chunk-
|
|
1
|
+
import { CompositionSequence, maskSourceOf } from './chunk-K3F2YKL4.js';
|
|
2
|
+
import { createTimeline, lengthen, ensureFilterLibrary, checkEase, parseEase, homeDistance, DEFAULT_FOV, random, noise, flattenSvgPath, rand, DEG, timeRemapOf, contentLength, resolveAt } from './chunk-BQNNZEAX.js';
|
|
3
|
+
export { noise, rand, random, registerSequenceType } from './chunk-BQNNZEAX.js';
|
|
4
4
|
import { usesAdvancedBlend, enableAdvancedBlend } from './chunk-TYWFKCPY.js';
|
|
5
5
|
import { collectPropKeys } from './chunk-45QKLD6M.js';
|
|
6
6
|
import { warnUnknownOptions, suggestName } from './chunk-BXOCEZ4U.js';
|
|
@@ -4332,7 +4332,7 @@ async function audioEnvelope(source, options = {}) {
|
|
|
4332
4332
|
|
|
4333
4333
|
// src/audio/musicEnvelope.ts
|
|
4334
4334
|
async function musicEnvelope(music, options = {}) {
|
|
4335
|
-
const { resolveMusic, renderMusic, musicLength, musicBeatTimes, TempoMap } = await import('./music-
|
|
4335
|
+
const { resolveMusic, renderMusic, musicLength, musicBeatTimes, TempoMap } = await import('./music-72YJAMXH.js');
|
|
4336
4336
|
const messages = [];
|
|
4337
4337
|
const m = resolveMusic(music, "musicEnvelope()", (msg) => messages.push(msg));
|
|
4338
4338
|
if (!m) throw new Error(`pixi-effects: musicEnvelope(): ${messages.join(" ") || "the music has nothing to play"}`);
|
|
@@ -4345,7 +4345,7 @@ async function musicEnvelope(music, options = {}) {
|
|
|
4345
4345
|
|
|
4346
4346
|
// src/audio/musicBuffer.ts
|
|
4347
4347
|
async function musicBuffer(music, options = {}) {
|
|
4348
|
-
const { resolveMusic, renderMusic, musicLength } = await import('./music-
|
|
4348
|
+
const { resolveMusic, renderMusic, musicLength } = await import('./music-72YJAMXH.js');
|
|
4349
4349
|
const messages = [];
|
|
4350
4350
|
const m = resolveMusic(music, "musicBuffer()", (msg) => messages.push(msg));
|
|
4351
4351
|
if (!m) throw new Error(`pixi-effects: musicBuffer(): ${messages.join(" ") || "the music has nothing to play"}`);
|
package/dist/loader.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* pixi-effects loader: one line of HTML on the page, a few lines of CSS, no JavaScript of your own.
|
|
3
3
|
*
|
|
4
|
-
* <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pixi-effects@0.27.
|
|
4
|
+
* <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pixi-effects@0.27.2/dist/loader.css">
|
|
5
5
|
* <div class="stage" style="position: relative"> <!-- any box the canvas sits in, with position: relative -->
|
|
6
6
|
* <canvas id="stage" width="1280" height="720"></canvas>
|
|
7
7
|
* <div class="pe-loader" data-label="LOADING"></div> <!-- or class="pe-loader pe-loader--bar" -->
|