lexgui 0.1.32 → 0.1.33
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/build/components/timeline.js +2059 -1443
- package/build/components/videoeditor.js +191 -100
- package/build/lexgui.css +27 -5
- package/build/lexgui.js +65 -30
- package/build/lexgui.module.js +62 -5
- package/changelog.md +7 -0
- package/examples/timeline.html +39 -24
- package/examples/video_editor.html +30 -13
- package/examples/video_editor2.html +118 -0
- package/package.json +1 -1
|
@@ -22,19 +22,19 @@ class TimeBar {
|
|
|
22
22
|
constructor( area, type, options = {} ) {
|
|
23
23
|
|
|
24
24
|
this.type = type;
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
// Create canvas
|
|
27
27
|
this.canvas = document.createElement( 'canvas' );
|
|
28
28
|
this.canvas.width = area.size[0];
|
|
29
29
|
this.canvas.height = area.size[1];
|
|
30
30
|
area.attach( this.canvas );
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
this.ctx = this.canvas.getContext("2d");
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
const barHeight = options.barHeight ?? 5;
|
|
35
35
|
this.markerWidth = options.markerWidth ?? 8;
|
|
36
|
-
this.offset = options.offset
|
|
37
|
-
|
|
36
|
+
this.offset = options.offset || 4;
|
|
37
|
+
|
|
38
38
|
this.width = this.canvas.width - this.offset * 2;
|
|
39
39
|
this.height = barHeight;
|
|
40
40
|
|
|
@@ -48,19 +48,19 @@ class TimeBar {
|
|
|
48
48
|
const h = this.canvas.height - y * 2;
|
|
49
49
|
this.trimRec = [this.startX, y, w, h];
|
|
50
50
|
|
|
51
|
-
this._draw();
|
|
52
|
-
|
|
53
51
|
this.lastPosition = new LX.vec2( 0, 0 );
|
|
52
|
+
|
|
53
|
+
this._draw();
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
_draw() {
|
|
57
57
|
const ctx = this.ctx;
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
ctx.save();
|
|
60
60
|
ctx.fillStyle = TimeBar.BACKGROUND_COLOR;
|
|
61
61
|
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
62
62
|
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
// // Draw background timeline
|
|
65
65
|
ctx.fillStyle = TimeBar.COLOR;
|
|
66
66
|
ctx.fillRect(this.position.x, this.position.y, this.width, this.height);
|
|
@@ -68,7 +68,7 @@ class TimeBar {
|
|
|
68
68
|
// Draw background trimed timeline
|
|
69
69
|
ctx.fillStyle = TimeBar.ACTIVE_COLOR;
|
|
70
70
|
ctx.fillRect(this.startX, this.position.y, this.endX - this.offset - this.startX, this.height);
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
ctx.restore();
|
|
73
73
|
|
|
74
74
|
// Min-Max time markers
|
|
@@ -80,31 +80,31 @@ class TimeBar {
|
|
|
80
80
|
_addTrim(name, x, options) {
|
|
81
81
|
|
|
82
82
|
options = options || {};
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
const y = this.trimRec[1];
|
|
85
85
|
const w = this.trimRec[2];
|
|
86
86
|
const h = this.trimRec[3];
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
const ctx = this.ctx;
|
|
89
89
|
if(this.hovering == name) {
|
|
90
90
|
// Shadow
|
|
91
91
|
ctx.shadowColor = "white";
|
|
92
|
-
ctx.shadowBlur = 2;
|
|
92
|
+
ctx.shadowBlur = 2;
|
|
93
93
|
}
|
|
94
94
|
ctx.globalAlpha = 1;
|
|
95
95
|
ctx.fillStyle = ctx.strokeStyle = options.fillColor || '#111' // "#FFF";
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
ctx.beginPath();
|
|
98
98
|
ctx.roundRect(x - w * 0.5, y, w, h, 2);
|
|
99
99
|
ctx.fill();
|
|
100
100
|
ctx.fillStyle = ctx.strokeStyle = options.fillColor || '#111' // "#FFF";
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
ctx.strokeStyle = "white";
|
|
103
103
|
ctx.beginPath();
|
|
104
104
|
ctx.lineWitdh = 2;
|
|
105
105
|
ctx.moveTo(x, y + 4);
|
|
106
106
|
ctx.lineTo(x, y + h - 4);
|
|
107
|
-
ctx.stroke();
|
|
107
|
+
ctx.stroke();
|
|
108
108
|
ctx.shadowBlur = 0;
|
|
109
109
|
|
|
110
110
|
}
|
|
@@ -112,48 +112,48 @@ class TimeBar {
|
|
|
112
112
|
_addMarker(name, x, options) {
|
|
113
113
|
|
|
114
114
|
options = options || {};
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
let y = this.offset;
|
|
117
117
|
const w = options.width ? options.width : (this.dragging == name ? 6 : 4);
|
|
118
118
|
const h = this.canvas.height - this.offset * 2;
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
let ctx = this.ctx;
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
ctx.globalAlpha = 1;
|
|
123
123
|
|
|
124
124
|
ctx.fillStyle = ctx.strokeStyle = options.fillColor || '#111' // "#FFF";
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
if(this.hovering == name) {
|
|
128
128
|
// Shadow
|
|
129
129
|
ctx.shadowColor = "white";
|
|
130
|
-
ctx.shadowBlur = 2;
|
|
130
|
+
ctx.shadowBlur = 2;
|
|
131
131
|
}
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
// Current time line
|
|
134
|
-
ctx.fillStyle = ctx.strokeStyle = "white";
|
|
134
|
+
ctx.fillStyle = ctx.strokeStyle = "white";
|
|
135
135
|
ctx.beginPath();
|
|
136
136
|
ctx.moveTo(x, y);
|
|
137
137
|
ctx.lineTo(x, y + h * 0.5);
|
|
138
|
-
ctx.stroke();
|
|
138
|
+
ctx.stroke();
|
|
139
139
|
ctx.closePath();
|
|
140
140
|
ctx.fillStyle = ctx.strokeStyle = options.fillColor || '#111' // "#FFF";
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
|
|
142
|
+
|
|
143
143
|
y -= this.offset + 4;
|
|
144
144
|
// Current time ball grab
|
|
145
145
|
ctx.fillStyle = options.fillColor || '#e5e5e5';
|
|
146
146
|
ctx.beginPath();
|
|
147
147
|
ctx.roundRect(x - w * 0.5, y + this.offset, w, w, 5);
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
ctx.fill();
|
|
150
|
-
ctx.shadowBlur = 0;
|
|
150
|
+
ctx.shadowBlur = 0;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
onMouseDown (e) {
|
|
154
154
|
|
|
155
155
|
e.preventDefault();
|
|
156
|
-
|
|
156
|
+
|
|
157
157
|
if(!this.canvas || e.target != this.canvas) {
|
|
158
158
|
return;
|
|
159
159
|
}
|
|
@@ -162,25 +162,25 @@ class TimeBar {
|
|
|
162
162
|
// Process mouse
|
|
163
163
|
const x = e.offsetX;
|
|
164
164
|
const y = e.offsetY;
|
|
165
|
-
|
|
165
|
+
|
|
166
166
|
// Check if some marker is clicked
|
|
167
167
|
const threshold = this.markerWidth;
|
|
168
168
|
|
|
169
169
|
if(Math.abs(this.startX - x) < threshold && this.trimRec[1] < y && y < this.trimRec[3] + this.trimRec[1] ) {
|
|
170
170
|
this.dragging = 'start';
|
|
171
171
|
canvas.style.cursor = "grabbing";
|
|
172
|
-
}
|
|
172
|
+
}
|
|
173
173
|
else if(Math.abs(this.endX - x) < threshold && this.trimRec[1] < y && y < this.trimRec[3] + this.trimRec[1] ) {
|
|
174
174
|
this.dragging = 'end';
|
|
175
175
|
canvas.style.cursor = "grabbing";
|
|
176
|
-
}
|
|
176
|
+
}
|
|
177
177
|
else if(Math.abs(this.currentX - x) < threshold) {
|
|
178
178
|
this.dragging = 'current';
|
|
179
179
|
canvas.style.cursor = "grabbing";
|
|
180
|
-
}
|
|
180
|
+
}
|
|
181
181
|
else {
|
|
182
182
|
if(x < this.startX) {
|
|
183
|
-
this.currentX = this.startX;
|
|
183
|
+
this.currentX = this.startX;
|
|
184
184
|
}
|
|
185
185
|
else if(x > this.endX) {
|
|
186
186
|
this.currentX = this.endX;
|
|
@@ -194,22 +194,46 @@ class TimeBar {
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
update (x) {
|
|
197
|
-
this.currentX = Math.min(Math.max(this.startX, x), this.endX);
|
|
197
|
+
this.currentX = Math.min(Math.max(this.startX, x), this.endX);
|
|
198
198
|
this._draw();
|
|
199
|
+
|
|
200
|
+
if(this.onDraw) {
|
|
201
|
+
this.onDraw();
|
|
202
|
+
}
|
|
199
203
|
}
|
|
200
204
|
|
|
201
205
|
onMouseUp (e) {
|
|
202
206
|
e.preventDefault();
|
|
203
|
-
|
|
207
|
+
|
|
204
208
|
this.dragging = false;
|
|
205
209
|
this.hovering = false;
|
|
206
|
-
|
|
210
|
+
|
|
207
211
|
if(!this.canvas) {
|
|
208
212
|
return;
|
|
209
213
|
}
|
|
210
214
|
|
|
211
215
|
const canvas = this.canvas;
|
|
212
216
|
canvas.style.cursor = "default";
|
|
217
|
+
|
|
218
|
+
// Process mouse
|
|
219
|
+
const x = e.target == this.canvas ? e.offsetX : e.offsetX - this.canvas.offsetLeft ;
|
|
220
|
+
const y = e.target == this.canvas ? e.offsetY : e.offsetY - this.canvas.offsetTop ;
|
|
221
|
+
const threshold = 5;
|
|
222
|
+
|
|
223
|
+
if(this.trimRec[1] < y && y < this.trimRec[3] + this.trimRec[1]) {
|
|
224
|
+
if(x < this.startX) {
|
|
225
|
+
this.currentX = this.startX;
|
|
226
|
+
}
|
|
227
|
+
else if(x > this.endX) {
|
|
228
|
+
this.currentX = this.endX;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
this.currentX = x;
|
|
232
|
+
}
|
|
233
|
+
if(this.onChangeCurrent) {
|
|
234
|
+
this.onChangeCurrent(this.currentX);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
213
237
|
}
|
|
214
238
|
|
|
215
239
|
onMouseMove (e) {
|
|
@@ -225,13 +249,13 @@ class TimeBar {
|
|
|
225
249
|
switch(this.dragging) {
|
|
226
250
|
case 'start':
|
|
227
251
|
if(x < this.position.x) {
|
|
228
|
-
this.currentX = this.startX = this.position.x;
|
|
252
|
+
this.currentX = this.startX = this.position.x;
|
|
229
253
|
}
|
|
230
254
|
else if(x > this.endX) {
|
|
231
|
-
this.currentX = this.startX = this.endX;
|
|
255
|
+
this.currentX = this.startX = this.endX;
|
|
232
256
|
}
|
|
233
257
|
else {
|
|
234
|
-
this.currentX = this.startX = x;
|
|
258
|
+
this.currentX = this.startX = x;
|
|
235
259
|
}
|
|
236
260
|
|
|
237
261
|
if(this.onChangeStart) {
|
|
@@ -243,15 +267,15 @@ class TimeBar {
|
|
|
243
267
|
break;
|
|
244
268
|
case 'end':
|
|
245
269
|
if(x > this.width || x <= 0) {
|
|
246
|
-
this.currentX = this.endX = this.width;
|
|
270
|
+
this.currentX = this.endX = this.width;
|
|
247
271
|
}
|
|
248
272
|
else if(x < this.startX) {
|
|
249
|
-
this.currentX = this.endX = this.startX;
|
|
273
|
+
this.currentX = this.endX = this.startX;
|
|
250
274
|
}
|
|
251
275
|
else {
|
|
252
|
-
this.currentX = this.endX = x;
|
|
276
|
+
this.currentX = this.endX = x;
|
|
253
277
|
}
|
|
254
|
-
|
|
278
|
+
|
|
255
279
|
if(this.onChangeEnd) {
|
|
256
280
|
this.onChangeEnd(this.endX);
|
|
257
281
|
}
|
|
@@ -260,9 +284,9 @@ class TimeBar {
|
|
|
260
284
|
}
|
|
261
285
|
break;
|
|
262
286
|
case 'current':
|
|
263
|
-
|
|
287
|
+
|
|
264
288
|
if(x < this.startX) {
|
|
265
|
-
this.currentX = this.startX;
|
|
289
|
+
this.currentX = this.startX;
|
|
266
290
|
}
|
|
267
291
|
else if(x > this.endX) {
|
|
268
292
|
this.currentX = this.endX;
|
|
@@ -280,7 +304,7 @@ class TimeBar {
|
|
|
280
304
|
if(!this.canvas) {
|
|
281
305
|
return;
|
|
282
306
|
}
|
|
283
|
-
|
|
307
|
+
|
|
284
308
|
const canvas = this.canvas;
|
|
285
309
|
|
|
286
310
|
if(Math.abs(this.startX - x) < threshold && this.trimRec[1] < y && y < this.trimRec[3] + this.trimRec[1] ) {
|
|
@@ -311,11 +335,11 @@ class TimeBar {
|
|
|
311
335
|
const currentRatio = this.currentX / this.width;
|
|
312
336
|
const endRatio = this.endX / this.width;
|
|
313
337
|
this.width = this.canvas.width - this.offset * 2;
|
|
314
|
-
|
|
315
|
-
this.startX = Math.max(this.width * startRatio, this.offset);
|
|
316
|
-
this.currentX = Math.min(Math.max(this.width * currentRatio, this.offset), this.width);
|
|
317
|
-
this.endX = Math.min(this.width * endRatio, this.width);
|
|
318
|
-
|
|
338
|
+
|
|
339
|
+
this.startX = Math.max(this.width * startRatio, this.offset);
|
|
340
|
+
this.currentX = Math.min(Math.max(this.width * currentRatio, this.offset), this.width);
|
|
341
|
+
this.endX = Math.min(this.width * endRatio, this.width);
|
|
342
|
+
|
|
319
343
|
this._draw();
|
|
320
344
|
}
|
|
321
345
|
}
|
|
@@ -335,17 +359,26 @@ class VideoEditor {
|
|
|
335
359
|
this.startTimeString = "0:0";
|
|
336
360
|
this.endTimeString = "0:0";
|
|
337
361
|
|
|
338
|
-
area.
|
|
339
|
-
let [videoArea, controlsArea] = area.split({ type: 'vertical', sizes:["80%", null], minimizable: false, resize: false });
|
|
362
|
+
let [videoArea, controlsArea] = area.split({ type: 'vertical', sizes: ["80%", null], minimizable: false, resize: false });
|
|
340
363
|
controlsArea.root.classList.add('lexconstrolsarea');
|
|
341
|
-
|
|
364
|
+
|
|
342
365
|
// Create video element and load it
|
|
343
|
-
let video = this.video = document.createElement( 'video' );
|
|
344
|
-
|
|
366
|
+
let video = this.video = options.video ?? document.createElement( 'video' );
|
|
367
|
+
if(options.src) {
|
|
368
|
+
this.video.src = options.src;
|
|
369
|
+
}
|
|
345
370
|
this.video.loop = true;
|
|
346
371
|
this._loadVideo(options);
|
|
347
|
-
videoArea
|
|
372
|
+
if(options.videoArea) {
|
|
373
|
+
options.videoArea.root.classList.add("lexvideoeditor");
|
|
374
|
+
videoArea.attach(options.videoArea);
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
videoArea.attach(video);
|
|
378
|
+
videoArea.root.classList.add("lexvideoeditor");
|
|
379
|
+
}
|
|
348
380
|
|
|
381
|
+
this.controlsArea = controlsArea;
|
|
349
382
|
// Create playing timeline area and attach panels
|
|
350
383
|
let [topArea, bottomArea] = controlsArea.split({ type: 'vertical', sizes:["50%", null], minimizable: false, resize: false });
|
|
351
384
|
bottomArea.setSize([bottomArea.size[0], 40]);
|
|
@@ -354,7 +387,7 @@ class VideoEditor {
|
|
|
354
387
|
|
|
355
388
|
topArea.root.classList.add('lexbar');
|
|
356
389
|
bottomArea.root.classList.add('lexbar');
|
|
357
|
-
this.controlsCurrentPanel = new LX.Panel({className: 'lexcontrolspanel lextime'});
|
|
390
|
+
this.controlsCurrentPanel = new LX.Panel({className: 'lexcontrolspanel lextime'});
|
|
358
391
|
this.controlsCurrentPanel.refresh = () => {
|
|
359
392
|
this.controlsCurrentPanel.clear();
|
|
360
393
|
this.controlsCurrentPanel.addLabel(this.currentTimeString, {float: "center"});
|
|
@@ -365,36 +398,36 @@ class VideoEditor {
|
|
|
365
398
|
|
|
366
399
|
const style = getComputedStyle(bottomArea.root);
|
|
367
400
|
let padding = Number(style.getPropertyValue('padding').replace("px",""));
|
|
368
|
-
this.timebar = new TimeBar(timeBarArea, TimeBar.TIMEBAR_TRIM, {offset: padding});
|
|
401
|
+
this.timebar = new TimeBar(timeBarArea, TimeBar.TIMEBAR_TRIM, {offset: padding});
|
|
369
402
|
|
|
370
403
|
// Create controls panel (play/pause button and start time)
|
|
371
|
-
this.controlsPanelLeft = new LX.Panel({className: 'lexcontrolspanel'});
|
|
404
|
+
this.controlsPanelLeft = new LX.Panel({className: 'lexcontrolspanel'});
|
|
372
405
|
this.controlsPanelLeft.refresh = () => {
|
|
373
406
|
this.controlsPanelLeft.clear();
|
|
374
407
|
this.controlsPanelLeft.sameLine();
|
|
375
408
|
this.controlsPanelLeft.addButton('', '<i class="fa-solid ' + (this.playing ? 'fa-pause' : 'fa-play') + '"></>', (v) => {
|
|
376
409
|
this.playing = !this.playing;
|
|
377
410
|
if(this.playing) {
|
|
378
|
-
|
|
411
|
+
|
|
379
412
|
this.video.play();
|
|
380
|
-
if(!this.requestId) {
|
|
381
|
-
|
|
382
|
-
}
|
|
413
|
+
// if(!this.requestId) {
|
|
414
|
+
// this.requestId = requestAnimationFrame(this._update.bind(this))
|
|
415
|
+
// }
|
|
383
416
|
}
|
|
384
417
|
else {
|
|
385
|
-
if(this.requestId) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
418
|
+
// if(this.requestId) {
|
|
419
|
+
// cancelAnimationFrame(this.requestId);
|
|
420
|
+
// this.requestId = null;
|
|
421
|
+
// }
|
|
389
422
|
this.video.pause();
|
|
390
423
|
}
|
|
391
424
|
this.controlsPanelLeft.refresh();
|
|
392
425
|
}, { width: '40px'});
|
|
393
|
-
|
|
426
|
+
|
|
394
427
|
this.controlsPanelLeft.addLabel(this.startTimeString, {width: 50});
|
|
395
428
|
this.controlsPanelLeft.endLine();
|
|
396
|
-
|
|
397
|
-
let availableWidth = leftArea.root.clientWidth - controlsLeft.root.clientWidth;
|
|
429
|
+
|
|
430
|
+
let availableWidth = leftArea.root.clientWidth - controlsLeft.root.clientWidth;
|
|
398
431
|
this.timebar.resize([availableWidth, timeBarArea.root.clientHeight]);
|
|
399
432
|
}
|
|
400
433
|
|
|
@@ -403,61 +436,94 @@ class VideoEditor {
|
|
|
403
436
|
controlsLeft.attach(this.controlsPanelLeft);
|
|
404
437
|
|
|
405
438
|
// Create right controls panel (ens time)
|
|
406
|
-
this.controlsPanelRight = new LX.Panel({className: 'lexcontrolspanel'});
|
|
439
|
+
this.controlsPanelRight = new LX.Panel({className: 'lexcontrolspanel'});
|
|
407
440
|
this.controlsPanelRight.refresh = () => {
|
|
408
|
-
this.controlsPanelRight.clear();
|
|
441
|
+
this.controlsPanelRight.clear();
|
|
409
442
|
this.controlsPanelRight.addLabel(this.endTimeString, {width: 50});
|
|
410
443
|
}
|
|
411
444
|
this.controlsPanelRight.refresh();
|
|
412
445
|
controlsRight.root.style.minWidth = 'fit-content';
|
|
413
|
-
controlsRight.attach(this.controlsPanelRight);
|
|
414
|
-
|
|
415
|
-
this.timebar.onChangeCurrent = this._setCurrentValue.bind(this);
|
|
416
|
-
this.timebar.onChangeStart = this._setStartValue.bind(this);
|
|
417
|
-
this.timebar.onChangeEnd = this._setEndValue.bind(this);
|
|
446
|
+
controlsRight.attach(this.controlsPanelRight);
|
|
447
|
+
|
|
448
|
+
this.timebar.onChangeCurrent = this._setCurrentValue.bind(this);
|
|
449
|
+
this.timebar.onChangeStart = this._setStartValue.bind(this);
|
|
450
|
+
this.timebar.onChangeEnd = this._setEndValue.bind(this);
|
|
418
451
|
|
|
419
452
|
window.addEventListener('resize', (v) => {
|
|
420
|
-
|
|
453
|
+
if(this.onResize) {
|
|
454
|
+
this.onResize([videoArea.root.clientWidth, videoArea.root.clientHeight]);
|
|
455
|
+
}
|
|
456
|
+
bottomArea.setSize([videoArea.root.clientWidth, 40]);
|
|
457
|
+
let availableWidth = this.controlsArea.root.clientWidth - controlsLeft.root.clientWidth - controlsRight.root.clientWidth;
|
|
421
458
|
this.timebar.resize([availableWidth, timeBarArea.root.clientHeight]);
|
|
422
459
|
})
|
|
423
460
|
|
|
461
|
+
videoArea.onresize = (v) => {
|
|
462
|
+
bottomArea.setSize([v.width, 40]);
|
|
463
|
+
}
|
|
464
|
+
|
|
424
465
|
timeBarArea.onresize = (v) => {
|
|
425
|
-
let availableWidth =
|
|
466
|
+
let availableWidth = this.controlsArea.root.clientWidth - controlsLeft.root.clientWidth - controlsRight.root.clientWidth;
|
|
426
467
|
this.timebar.resize([availableWidth, v.height]);
|
|
427
468
|
}
|
|
428
469
|
|
|
429
470
|
// Add canvas event listeneres
|
|
430
|
-
area.root.addEventListener( "mousedown",
|
|
431
|
-
|
|
432
|
-
|
|
471
|
+
area.root.addEventListener( "mousedown", (event) => {
|
|
472
|
+
if(this.controls) {
|
|
473
|
+
this.timebar.onMouseDown(event);
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
area.root.addEventListener( "mouseup", (event) => {
|
|
477
|
+
if(this.controls) {
|
|
478
|
+
this.timebar.onMouseUp(event);
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
area.root.addEventListener( "mousemove", (event) => {
|
|
482
|
+
if(this.controls) {
|
|
483
|
+
this.timebar.onMouseMove(event);
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
433
487
|
}
|
|
434
488
|
|
|
435
|
-
async _loadVideo( ) {
|
|
489
|
+
async _loadVideo( options = {} ) {
|
|
436
490
|
while(this.video.duration === Infinity || isNaN(this.video.duration) || !this.timebar) {
|
|
437
491
|
await new Promise(r => setTimeout(r, 1000));
|
|
438
492
|
this.video.currentTime = 10000000 * Math.random();
|
|
439
493
|
}
|
|
440
494
|
this.video.currentTime = 0;
|
|
441
|
-
this.endTime = this.video.duration;
|
|
442
|
-
|
|
495
|
+
this.endTime = this.video.duration;
|
|
496
|
+
this.timebar.currentX = this._timeToX(0);
|
|
443
497
|
this._setEndValue(this.timebar.endX);
|
|
444
498
|
this._setStartValue(this.timebar.startX);
|
|
445
499
|
this._setCurrentValue(this.timebar.currentX);
|
|
446
500
|
this.timebar.update(this.timebar.currentX);
|
|
501
|
+
this._update();
|
|
502
|
+
this.controls = options.controls ?? true;
|
|
503
|
+
if(!this.controls) {
|
|
504
|
+
this.hideControls();
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if(this.onVideoLoaded) {
|
|
508
|
+
this.onVideoLoaded(this.video);
|
|
509
|
+
}
|
|
447
510
|
}
|
|
448
511
|
|
|
449
512
|
_update () {
|
|
450
|
-
|
|
451
|
-
if(this.video.currentTime >= this.endTime) {
|
|
452
|
-
this.video.currentTime = this.startTime;
|
|
453
|
-
}
|
|
454
|
-
const x = this._timeToX(this.video.currentTime);
|
|
455
|
-
this._setCurrentValue(x, false);
|
|
456
|
-
this.timebar.update(x);
|
|
457
513
|
|
|
514
|
+
if(this.onDraw) {
|
|
515
|
+
this.onDraw();
|
|
516
|
+
}
|
|
458
517
|
if(this.playing) {
|
|
459
|
-
this.
|
|
518
|
+
if(this.video.currentTime >= this.endTime) {
|
|
519
|
+
this.video.currentTime = this.startTime;
|
|
520
|
+
}
|
|
521
|
+
const x = this._timeToX(this.video.currentTime);
|
|
522
|
+
this._setCurrentValue(x, false);
|
|
523
|
+
this.timebar.update(x);
|
|
460
524
|
}
|
|
525
|
+
|
|
526
|
+
this.requestId = requestAnimationFrame(this._update.bind(this));
|
|
461
527
|
}
|
|
462
528
|
|
|
463
529
|
_xToTime (x) {
|
|
@@ -486,23 +552,26 @@ class VideoEditor {
|
|
|
486
552
|
this.controlsCurrentPanel.refresh();
|
|
487
553
|
|
|
488
554
|
if(this.onSetTime) {
|
|
489
|
-
this.onSetTime(
|
|
555
|
+
this.onSetTime(t);
|
|
490
556
|
}
|
|
491
557
|
}
|
|
492
558
|
|
|
493
559
|
_setStartValue ( x ) {
|
|
494
560
|
const t = this._xToTime(x);
|
|
495
561
|
this.startTime = this.video.currentTime = t;
|
|
496
|
-
|
|
562
|
+
|
|
497
563
|
let mzminutes = Math.floor(t / 60);
|
|
498
564
|
let mzseconds = Math.floor(t - (mzminutes * 60));
|
|
499
565
|
let mzmiliseconds = Math.floor((t - mzseconds)*100);
|
|
500
|
-
|
|
566
|
+
|
|
501
567
|
mzmiliseconds = mzmiliseconds < 10 ? ('0' + mzmiliseconds) : mzmiliseconds;
|
|
502
568
|
mzseconds = mzseconds < 10 ? ('0' + mzseconds) : mzseconds;
|
|
503
569
|
mzminutes = mzminutes < 10 ? ('0' + mzminutes) : mzminutes;
|
|
504
570
|
this.startTimeString = mzminutes+':'+mzseconds+'.'+mzmiliseconds;
|
|
505
571
|
this.controlsPanelLeft.refresh();
|
|
572
|
+
if(this.onSetTime) {
|
|
573
|
+
this.onSetTime(t);
|
|
574
|
+
}
|
|
506
575
|
}
|
|
507
576
|
|
|
508
577
|
_setEndValue ( x ) {
|
|
@@ -512,13 +581,16 @@ class VideoEditor {
|
|
|
512
581
|
let mzminutes = Math.floor(t / 60);
|
|
513
582
|
let mzseconds = Math.floor(t - (mzminutes * 60));
|
|
514
583
|
let mzmiliseconds = Math.floor((t - mzseconds)*100);
|
|
515
|
-
|
|
584
|
+
|
|
516
585
|
mzmiliseconds = mzmiliseconds < 10 ? ('0' + mzmiliseconds) : mzmiliseconds;
|
|
517
586
|
mzseconds = mzseconds < 10 ? ('0' + mzseconds) : mzseconds;
|
|
518
587
|
mzminutes = mzminutes < 10 ? ('0' + mzminutes) : mzminutes;
|
|
519
|
-
|
|
588
|
+
|
|
520
589
|
this.endTimeString = mzminutes+':'+mzseconds+'.'+mzmiliseconds;
|
|
521
590
|
this.controlsPanelRight.refresh();
|
|
591
|
+
if(this.onSetTime) {
|
|
592
|
+
this.onSetTime(t);
|
|
593
|
+
}
|
|
522
594
|
}
|
|
523
595
|
|
|
524
596
|
getStartTime ( ) {
|
|
@@ -532,6 +604,25 @@ class VideoEditor {
|
|
|
532
604
|
getTrimedTimes ( ) {
|
|
533
605
|
return {start: this.startTime, end: this.endTime};
|
|
534
606
|
}
|
|
607
|
+
|
|
608
|
+
showControls ( ) {
|
|
609
|
+
this.controls = true;
|
|
610
|
+
this.controlsArea.show();
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
hideControls ( ) {
|
|
614
|
+
this.controls = false;
|
|
615
|
+
this.controlsArea.hide();
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
delete ( ) {
|
|
619
|
+
if(this.requestId) {
|
|
620
|
+
cancelAnimationFrame(this.requestId);
|
|
621
|
+
this.requestId = null;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
delete this;
|
|
625
|
+
}
|
|
535
626
|
}
|
|
536
627
|
|
|
537
628
|
LX.VideoEditor = VideoEditor;
|
package/build/lexgui.css
CHANGED
|
@@ -567,7 +567,11 @@ body.noevents * {
|
|
|
567
567
|
padding-right: 10px;
|
|
568
568
|
}
|
|
569
569
|
|
|
570
|
-
.lexinlinewidgets .lexwidgetname {
|
|
570
|
+
.lexinlinewidgets .lexwidgetname.float-center {
|
|
571
|
+
justify-content: center;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.lexinlinewidgets .lexwidgetname.float-right {
|
|
571
575
|
justify-content: end;
|
|
572
576
|
-moz-transform: translateX(-1em);
|
|
573
577
|
-webkit-transform: translateX(-1em);
|
|
@@ -968,7 +972,7 @@ body.noevents * {
|
|
|
968
972
|
width: 100%;
|
|
969
973
|
cursor: pointer;
|
|
970
974
|
color: rgba(216, 218, 230, 0.826);
|
|
971
|
-
height: 20px;
|
|
975
|
+
min-height: 20px;
|
|
972
976
|
line-height: 22px;
|
|
973
977
|
align-content: center;
|
|
974
978
|
display: flow-root;
|
|
@@ -2017,6 +2021,7 @@ meter::-webkit-meter-even-less-good-value {
|
|
|
2017
2021
|
top: 0;
|
|
2018
2022
|
justify-content: start;
|
|
2019
2023
|
pointer-events: none;
|
|
2024
|
+
z-index: 100;
|
|
2020
2025
|
}
|
|
2021
2026
|
|
|
2022
2027
|
.lexoverlaybuttons .lexwidget {
|
|
@@ -2806,6 +2811,17 @@ ul.lexassetscontent {
|
|
|
2806
2811
|
z-index: 1;
|
|
2807
2812
|
}
|
|
2808
2813
|
|
|
2814
|
+
.lexassetscontent.list li .lexcheckbox {
|
|
2815
|
+
display: block;
|
|
2816
|
+
left: 0 !important;
|
|
2817
|
+
z-index: 100;
|
|
2818
|
+
position: absolute;
|
|
2819
|
+
}
|
|
2820
|
+
|
|
2821
|
+
.lexassetscontent.list li .lexcheckbox input[type=checkbox]:checked:after {
|
|
2822
|
+
left: 0!important;
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2809
2825
|
.lexassetscontent li:hover span {
|
|
2810
2826
|
color: #f5f5f5;
|
|
2811
2827
|
}
|
|
@@ -3649,7 +3665,8 @@ pre .line-gutter {
|
|
|
3649
3665
|
/* Video Editor */
|
|
3650
3666
|
|
|
3651
3667
|
.lexvideoeditor {
|
|
3652
|
-
|
|
3668
|
+
display: flex;
|
|
3669
|
+
justify-content: center;
|
|
3653
3670
|
}
|
|
3654
3671
|
|
|
3655
3672
|
.lexvideoeditor video {
|
|
@@ -3657,8 +3674,8 @@ pre .line-gutter {
|
|
|
3657
3674
|
height: 100%;
|
|
3658
3675
|
}
|
|
3659
3676
|
|
|
3660
|
-
.lexvideoeditor
|
|
3661
|
-
|
|
3677
|
+
.lexarea.lexvideoeditor {
|
|
3678
|
+
|
|
3662
3679
|
}
|
|
3663
3680
|
|
|
3664
3681
|
.lexvideoeditor .lexarea .lexflexarea {
|
|
@@ -3724,3 +3741,8 @@ pre .line-gutter {
|
|
|
3724
3741
|
height: calc(100% );
|
|
3725
3742
|
padding: 5px;
|
|
3726
3743
|
} */
|
|
3744
|
+
|
|
3745
|
+
.resizeable {
|
|
3746
|
+
resize: both;
|
|
3747
|
+
overflow: auto;
|
|
3748
|
+
}
|