@editframe/elements 0.16.0-beta.1 → 0.16.2-beta.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/dist/EF_FRAMEGEN.d.ts +2 -0
- package/dist/EF_FRAMEGEN.js +11 -12
- package/dist/elements/EFTemporal.js +1 -0
- package/dist/elements/EFTimegroup.d.ts +2 -1
- package/dist/elements/EFTimegroup.js +21 -5
- package/package.json +2 -2
- package/src/elements/EFTemporal.ts +1 -0
- package/src/elements/EFTimegroup.browsertest.ts +66 -0
- package/src/elements/EFTimegroup.ts +30 -7
- package/types.json +1 -1
package/dist/EF_FRAMEGEN.d.ts
CHANGED
package/dist/EF_FRAMEGEN.js
CHANGED
|
@@ -3,27 +3,30 @@ import { deepGetElementsWithFrameTasks } from "./elements/EFTemporal.js";
|
|
|
3
3
|
import { shallowGetTimegroups } from "./elements/EFTimegroup.js";
|
|
4
4
|
class TriggerCanvas {
|
|
5
5
|
constructor() {
|
|
6
|
+
this.canvasInitialized = false;
|
|
6
7
|
this.canvas = document.createElement("canvas");
|
|
8
|
+
const ctx = this.canvas.getContext("2d", { willReadFrequently: true });
|
|
9
|
+
if (!ctx) throw new Error("Canvas 2d context not ready");
|
|
10
|
+
this.ctx = ctx;
|
|
11
|
+
this.ctx.fillStyle = "transparent";
|
|
12
|
+
}
|
|
13
|
+
initialize() {
|
|
14
|
+
if (this.canvasInitialized) return;
|
|
15
|
+
this.canvasInitialized = true;
|
|
7
16
|
this.canvas.width = 1;
|
|
8
17
|
this.canvas.height = 1;
|
|
9
18
|
Object.assign(this.canvas.style, {
|
|
10
19
|
position: "fixed",
|
|
11
20
|
top: "0px",
|
|
12
21
|
left: "0px",
|
|
13
|
-
width: "
|
|
14
|
-
height: "
|
|
22
|
+
width: "100%",
|
|
23
|
+
height: "100%",
|
|
15
24
|
zIndex: "100000"
|
|
16
25
|
});
|
|
17
26
|
document.body.appendChild(this.canvas);
|
|
18
|
-
const ctx = this.canvas.getContext("2d", { willReadFrequently: true });
|
|
19
|
-
if (!ctx) throw new Error("Canvas 2d context not ready");
|
|
20
|
-
this.ctx = ctx;
|
|
21
|
-
this.ctx.fillStyle = "transparent";
|
|
22
27
|
}
|
|
23
28
|
trigger() {
|
|
24
|
-
console.log("TRIGGERING CANVAS");
|
|
25
29
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
26
|
-
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
32
|
class EFFramegen {
|
|
@@ -119,13 +122,9 @@ class EFFramegen {
|
|
|
119
122
|
}
|
|
120
123
|
this.time = this.renderOptions.encoderOptions.fromMs + frameNumber * this.frameDurationMs;
|
|
121
124
|
firstGroup.currentTimeMs = this.time;
|
|
122
|
-
console.log("trace: Awaiting initialBusyTasks");
|
|
123
125
|
await this.initialBusyTasks;
|
|
124
|
-
console.log("trace: Awaiting microtask");
|
|
125
126
|
await new Promise(queueMicrotask);
|
|
126
|
-
console.log("trace: Awaiting frame tasks");
|
|
127
127
|
const now = performance.now();
|
|
128
|
-
console.log("trace: HTML", document.body.innerHTML);
|
|
129
128
|
await Promise.all(
|
|
130
129
|
temporals.filter((temporal) => temporal.frameTask.status < TaskStatus.COMPLETE).map((temporal) => {
|
|
131
130
|
return temporal.frameTask;
|
|
@@ -6,7 +6,7 @@ export declare class EFTimegroup extends EFTimegroup_base {
|
|
|
6
6
|
#private;
|
|
7
7
|
static styles: import('lit').CSSResult;
|
|
8
8
|
_timeGroupContext: this;
|
|
9
|
-
mode: "fixed" | "sequence" | "contain";
|
|
9
|
+
mode: "fit" | "fixed" | "sequence" | "contain";
|
|
10
10
|
overlapMs: number;
|
|
11
11
|
fit: "none" | "contain" | "cover";
|
|
12
12
|
set currentTime(time: number);
|
|
@@ -19,6 +19,7 @@ export declare class EFTimegroup extends EFTimegroup_base {
|
|
|
19
19
|
disconnectedCallback(): void;
|
|
20
20
|
get storageKey(): string;
|
|
21
21
|
get intrinsicDurationMs(): number | undefined;
|
|
22
|
+
get hasOwnDuration(): boolean;
|
|
22
23
|
get durationMs(): number;
|
|
23
24
|
/**
|
|
24
25
|
* Wait for all media elements to load their initial segments.
|
|
@@ -128,26 +128,42 @@ let EFTimegroup = class extends EFTemporal(LitElement) {
|
|
|
128
128
|
}
|
|
129
129
|
return void 0;
|
|
130
130
|
}
|
|
131
|
+
get hasOwnDuration() {
|
|
132
|
+
return this.mode === "contain" || this.mode === "sequence" || this.mode === "fixed" && this.hasExplicitDuration;
|
|
133
|
+
}
|
|
131
134
|
get durationMs() {
|
|
132
135
|
switch (this.mode) {
|
|
136
|
+
case "fit": {
|
|
137
|
+
if (!this.parentTimegroup) {
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
return this.parentTimegroup.durationMs;
|
|
141
|
+
}
|
|
133
142
|
case "fixed":
|
|
134
143
|
return super.durationMs;
|
|
135
144
|
case "sequence": {
|
|
136
145
|
let duration = 0;
|
|
137
|
-
this.childTemporals.forEach((
|
|
146
|
+
this.childTemporals.forEach((child, index) => {
|
|
147
|
+
if (child instanceof EFTimegroup && child.mode === "fit") {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
138
150
|
if (index > 0) {
|
|
139
151
|
duration -= this.overlapMs;
|
|
140
152
|
}
|
|
141
|
-
duration +=
|
|
153
|
+
duration += child.durationMs;
|
|
142
154
|
});
|
|
143
155
|
return duration;
|
|
144
156
|
}
|
|
145
157
|
case "contain": {
|
|
146
158
|
let maxDuration = 0;
|
|
147
|
-
for (const
|
|
148
|
-
if (
|
|
149
|
-
|
|
159
|
+
for (const child of this.childTemporals) {
|
|
160
|
+
if (child instanceof EFTimegroup && child.mode === "fit") {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (!child.hasOwnDuration) {
|
|
164
|
+
continue;
|
|
150
165
|
}
|
|
166
|
+
maxDuration = Math.max(maxDuration, child.durationMs);
|
|
151
167
|
}
|
|
152
168
|
return maxDuration;
|
|
153
169
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editframe/elements",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.2-beta.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"license": "UNLICENSED",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@bramus/style-observer": "^1.3.0",
|
|
30
|
-
"@editframe/assets": "0.16.
|
|
30
|
+
"@editframe/assets": "0.16.2-beta.0",
|
|
31
31
|
"@lit/context": "^1.1.2",
|
|
32
32
|
"@lit/task": "^1.0.1",
|
|
33
33
|
"d3": "^7.9.0",
|
|
@@ -55,6 +55,72 @@ const renderTimegroup = (result: TemplateResult) => {
|
|
|
55
55
|
return firstChild;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
+
describe(`<ef-timegroup mode='fit'>`, () => {
|
|
59
|
+
test("duration is zero when there is no parent to fit into", () => {
|
|
60
|
+
const timegroup = renderTimegroup(
|
|
61
|
+
html`<ef-timegroup mode="fit"></ef-timegroup>`,
|
|
62
|
+
);
|
|
63
|
+
assert.equal(timegroup.durationMs, 0);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("duration is zero when there is no parent to fit into, even if there are children with duration", () => {
|
|
67
|
+
const timegroup = renderTimegroup(
|
|
68
|
+
html`<ef-timegroup mode="fit">
|
|
69
|
+
<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>
|
|
70
|
+
</ef-timegroup>`,
|
|
71
|
+
);
|
|
72
|
+
assert.equal(timegroup.durationMs, 0);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("duration is the duration of the parent timegroup", () => {
|
|
76
|
+
const timegroup = renderTimegroup(
|
|
77
|
+
html`<ef-timegroup mode="fixed" duration="10s">
|
|
78
|
+
<ef-timegroup id="child" mode="fit"></ef-timegroup>
|
|
79
|
+
</ef-timegroup>`,
|
|
80
|
+
);
|
|
81
|
+
const child = timegroup.querySelector("#child") as EFTimegroup;
|
|
82
|
+
assert.equal(child.durationMs, 10_000);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("fit mode items inside a sequence are given zero duration and do not factor into the duration of the sequence", () => {
|
|
86
|
+
const timegroup = renderTimegroup(
|
|
87
|
+
html`<ef-timegroup mode="sequence">
|
|
88
|
+
<ef-timegroup id="child" mode="fit"></ef-timegroup>
|
|
89
|
+
</ef-timegroup>`,
|
|
90
|
+
);
|
|
91
|
+
const child = timegroup.querySelector("#child") as EFTimegroup;
|
|
92
|
+
assert.equal(child.durationMs, 0);
|
|
93
|
+
assert.equal(timegroup.durationMs, 0);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("fit mode can be used to constrain a 'background' timegroup into a 'foreground' sequence", async () => {
|
|
97
|
+
const timegroup = renderTimegroup(
|
|
98
|
+
html`
|
|
99
|
+
<ef-timegroup mode="contain">
|
|
100
|
+
<ef-timegroup id="foreground" mode="sequence">
|
|
101
|
+
<ef-timegroup mode="fixed" duration="10s"></ef-timegroup>
|
|
102
|
+
<ef-timegroup mode="fixed" duration="10s"></ef-timegroup>
|
|
103
|
+
</ef-timegroup>
|
|
104
|
+
<ef-timegroup id="background" mode="fit">
|
|
105
|
+
<ef-timegroup mode="fixed" duration="30s"></ef-timegroup>
|
|
106
|
+
</ef-timegroup>
|
|
107
|
+
</ef-timegroup>
|
|
108
|
+
`,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const foreground = timegroup.querySelector("#foreground") as EFTimegroup;
|
|
112
|
+
const background = timegroup.querySelector("#background") as EFTimegroup;
|
|
113
|
+
assert.equal(foreground.durationMs, 20_000);
|
|
114
|
+
console.log("INFO", {
|
|
115
|
+
mode: background.mode,
|
|
116
|
+
duration: background.durationMs,
|
|
117
|
+
parentTimegroup: background.parentTimegroup,
|
|
118
|
+
});
|
|
119
|
+
console.log(background.parentTimegroup?.durationMs);
|
|
120
|
+
assert.equal(background.durationMs, 20_000);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
58
124
|
describe(`<ef-timegroup mode="fixed">`, () => {
|
|
59
125
|
test("can explicitly set a duration in seconds", async () => {
|
|
60
126
|
const timegroup = renderTimegroup(
|
|
@@ -54,7 +54,7 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
54
54
|
type: String,
|
|
55
55
|
attribute: "mode",
|
|
56
56
|
})
|
|
57
|
-
mode: "fixed" | "sequence" | "contain" = "contain";
|
|
57
|
+
mode: "fit" | "fixed" | "sequence" | "contain" = "contain";
|
|
58
58
|
|
|
59
59
|
@property({
|
|
60
60
|
type: Number,
|
|
@@ -146,26 +146,49 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
146
146
|
return undefined;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
get
|
|
149
|
+
get hasOwnDuration() {
|
|
150
|
+
return (
|
|
151
|
+
this.mode === "contain" ||
|
|
152
|
+
this.mode === "sequence" ||
|
|
153
|
+
(this.mode === "fixed" && this.hasExplicitDuration)
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
get durationMs(): number {
|
|
150
158
|
switch (this.mode) {
|
|
159
|
+
case "fit": {
|
|
160
|
+
if (!this.parentTimegroup) {
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
return this.parentTimegroup.durationMs;
|
|
164
|
+
}
|
|
151
165
|
case "fixed":
|
|
152
166
|
return super.durationMs;
|
|
153
167
|
case "sequence": {
|
|
154
168
|
let duration = 0;
|
|
155
|
-
this.childTemporals.forEach((
|
|
169
|
+
this.childTemporals.forEach((child, index) => {
|
|
170
|
+
if (child instanceof EFTimegroup && child.mode === "fit") {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
156
173
|
if (index > 0) {
|
|
157
174
|
duration -= this.overlapMs;
|
|
158
175
|
}
|
|
159
|
-
duration +=
|
|
176
|
+
duration += child.durationMs;
|
|
160
177
|
});
|
|
161
178
|
return duration;
|
|
162
179
|
}
|
|
163
180
|
case "contain": {
|
|
164
181
|
let maxDuration = 0;
|
|
165
|
-
for (const
|
|
166
|
-
|
|
167
|
-
|
|
182
|
+
for (const child of this.childTemporals) {
|
|
183
|
+
// fit timegroups look "up" to their parent timegroup for their duration
|
|
184
|
+
// so we need to skip them to avoid an infinite loop
|
|
185
|
+
if (child instanceof EFTimegroup && child.mode === "fit") {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (!child.hasOwnDuration) {
|
|
189
|
+
continue;
|
|
168
190
|
}
|
|
191
|
+
maxDuration = Math.max(maxDuration, child.durationMs);
|
|
169
192
|
}
|
|
170
193
|
return maxDuration;
|
|
171
194
|
}
|