lexgui 0.7.9 → 0.7.11

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.
@@ -23,6 +23,7 @@ class TimeBar {
23
23
  constructor( area, type, options = {} ) {
24
24
 
25
25
  this.type = type;
26
+ this.duration = options.duration || 1.0;
26
27
 
27
28
  // Create canvas
28
29
  this.canvas = document.createElement( 'canvas' );
@@ -31,7 +32,7 @@ class TimeBar {
31
32
  area.attach( this.canvas );
32
33
 
33
34
  this.ctx = this.canvas.getContext("2d");
34
-
35
+
35
36
  this.markerWidth = options.markerWidth ?? 8;
36
37
  this.markerHeight = options.markerHeight ?? (this.canvas.height * 0.5);
37
38
  this.offset = options.offset || (this.markerWidth*0.5 + 5);
@@ -52,17 +53,75 @@ class TimeBar {
52
53
  // Retrieve again the color using LX.getThemeColor, which checks the applied theme
53
54
  this.updateTheme();
54
55
  } )
56
+
57
+ this.canvas.onmousedown = (e) => this.onMouseDown(e);
58
+ this.canvas.onmousemove = (e) => this.onMouseMove(e);
59
+ this.canvas.onmouseup = (e) => this.onMouseUp(e);
55
60
  }
56
61
 
57
- updateTheme(){
62
+ updateTheme( ) {
58
63
  TimeBar.BACKGROUND_COLOR = LX.getThemeColor("global-color-secondary");
59
64
  TimeBar.COLOR = LX.getThemeColor("global-color-quaternary");
60
65
  TimeBar.ACTIVE_COLOR = "#668ee4";
61
66
  }
67
+
68
+ setDuration( duration ) {
69
+ this.duration = duration;
70
+ }
62
71
 
63
- _draw() {
64
- const ctx = this.ctx;
72
+ xToTime( x ) {
73
+ return ((x - this.offset) / (this.lineWidth)) * this.duration;
74
+ }
75
+
76
+ timeToX( time ) {
77
+ return (time / this.duration) * (this.lineWidth) + this.offset;
78
+ }
79
+
80
+ setCurrentTime( time ) {
81
+ this.currentX = this.timeToX( time );
82
+ this.onSetCurrentValue( this.currentX );
83
+ }
84
+
85
+ setStartTime( time ) {
86
+ this.startX = this.timeToX( time );
87
+ this.onSetStartValue( this.startX )
88
+ }
89
+
90
+ setEndTime( time ) {
91
+ this.endX = this.timeToX( time );
92
+ this.onSetEndValue( this.endX );
93
+ }
94
+
95
+ onSetCurrentValue( x ) {
96
+ this.update( x );
97
+
98
+ const t = this.xToTime( x );
99
+ if( this.onChangeCurrent ) {
100
+ this.onChangeCurrent( t );
101
+ }
102
+ }
103
+
104
+ onSetStartValue( x ) {
105
+ this.update( x );
106
+
107
+ const t = this.xToTime( x );
108
+ if( this.onChangeStart ) {
109
+ this.onChangeStart( t );
110
+ }
111
+ }
112
+
113
+ onSetEndValue( x ) {
114
+ this.update( x );
65
115
 
116
+ const t = this.xToTime( x );
117
+ if( this.onChangeEnd ) {
118
+ this.onChangeEnd( t );
119
+ }
120
+ }
121
+
122
+ _draw( ) {
123
+ const ctx = this.ctx;
124
+
66
125
  ctx.save();
67
126
  ctx.fillStyle = TimeBar.BACKGROUND_COLOR;
68
127
  ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
@@ -82,6 +141,10 @@ class TimeBar {
82
141
  this._drawTrimMarker('start', this.startX, { color: null, fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9'});
83
142
  this._drawTrimMarker('end', this.endX, { color: null, fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9'});
84
143
  this._drawTimeMarker('current', this.currentX, { color: '#e5e5e5', fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9', width: this.markerWidth });
144
+
145
+ if( this.onDraw ) {
146
+ this.onDraw();
147
+ }
85
148
  }
86
149
 
87
150
  _drawTrimMarker(name, x, options) {
@@ -157,20 +220,20 @@ class TimeBar {
157
220
  ctx.shadowBlur = 0;
158
221
  }
159
222
 
160
- update (x) {
223
+ update( x ) {
161
224
  this.currentX = Math.min(Math.max(this.startX, x), this.endX);
162
225
  this._draw();
163
-
164
- if(this.onDraw) {
165
- this.onDraw();
166
- }
167
226
  }
168
227
 
169
- onMouseDown (e) {
228
+ onMouseDown( e ) {
229
+
230
+ if( this.onMouse ) {
231
+ this.onMouse( e );
232
+ }
170
233
 
171
234
  e.preventDefault();
172
235
 
173
- if(!this.canvas || e.target != this.canvas) {
236
+ if( !this.canvas || e.target != this.canvas || e.cancelBubble ) {
174
237
  return;
175
238
  }
176
239
  const canvas = this.canvas;
@@ -183,43 +246,46 @@ class TimeBar {
183
246
  const threshold = this.markerWidth;
184
247
 
185
248
  // grab trim markers only from the bottom
186
- if(Math.abs(this.startX - x) < threshold && this.position.y < y) {
249
+ if( Math.abs(this.startX - x) < threshold && this.position.y < y ) {
187
250
  this.dragging = 'start';
188
251
  canvas.style.cursor = "grabbing";
189
252
  }
190
- else if(Math.abs(this.endX - x) < threshold && this.position.y < y) {
253
+ else if( Math.abs(this.endX - x) < threshold && this.position.y < y ) {
191
254
  this.dragging = 'end';
192
255
  canvas.style.cursor = "grabbing";
193
256
  }
194
257
  else {
195
258
  this.dragging = 'current';
196
259
  canvas.style.cursor = "grabbing";
197
-
198
- if(x < this.startX) {
260
+
261
+ if( x < this.startX ) {
199
262
  this.currentX = this.startX;
200
263
  }
201
- else if(x > this.endX) {
264
+ else if( x > this.endX ) {
202
265
  this.currentX = this.endX;
203
266
  }
204
267
  else {
205
268
  this.currentX = x;
206
269
  }
207
270
 
208
- if(this.onChangeCurrent) {
209
- this.onChangeCurrent(this.currentX);
210
- }
271
+ this.onSetCurrentValue( this.currentX );
211
272
  }
212
273
 
213
274
  this._draw();
214
275
  }
215
276
 
216
- onMouseUp (e) {
277
+ onMouseUp( e ) {
278
+
279
+ if( this.onMouse ) {
280
+ this.onMouse( e );
281
+ }
282
+
217
283
  e.preventDefault();
218
284
 
219
285
  this.dragging = false;
220
286
  this.hovering = false;
221
287
 
222
- if(!this.canvas) {
288
+ if( !this.canvas || e.cancelBubble ) {
223
289
  return;
224
290
  }
225
291
 
@@ -227,8 +293,13 @@ class TimeBar {
227
293
  canvas.style.cursor = "default";
228
294
  }
229
295
 
230
- onMouseMove (e) {
231
- if(!this.canvas) {
296
+ onMouseMove( e ) {
297
+
298
+ if( this.onMouse ) {
299
+ this.onMouse( e );
300
+ }
301
+
302
+ if( !this.canvas || e.cancelBubble ) {
232
303
  return;
233
304
  }
234
305
 
@@ -239,43 +310,38 @@ class TimeBar {
239
310
  const x = e.target == canvas ? e.offsetX : e.clientX - canvas.offsetLeft;
240
311
  const y = e.target == canvas ? e.offsetY : e.clientY - canvas.offsetTop;
241
312
 
242
- if(this.dragging) {
243
- switch(this.dragging) {
313
+ if( this.dragging ) {
314
+ switch( this.dragging ) {
244
315
  case 'start':
245
- this.startX = Math.max(this.position.x, Math.min(this.endX, x));
316
+ this.startX = Math.max(this.position.x, Math.min(this.endX, x));
246
317
  this.currentX = this.startX;
247
- if(this.onChangeStart) {
248
- this.onChangeStart(this.startX);
249
- }
318
+ this.onSetStartValue(this.startX);
250
319
  break;
251
320
  case 'end':
252
- this.endX = Math.max(this.startX, Math.min(this.position.x + this.lineWidth, x));
321
+ this.endX = Math.max( this.startX, Math.min(this.position.x + this.lineWidth, x) );
253
322
  this.currentX = this.endX;
254
- if(this.onChangeEnd) {
255
- this.onChangeEnd(this.endX);
256
- }
323
+
324
+ this.onSetEndValue( this.endX );
257
325
  break;
258
326
  default:
259
- this.currentX = Math.max(this.startX, Math.min(this.endX, x));
327
+ this.currentX = Math.max( this.startX, Math.min(this.endX, x) );
260
328
  break;
261
329
  }
262
330
 
263
- if(this.onChangeCurrent) {
264
- this.onChangeCurrent(this.currentX);
265
- }
331
+ this.onSetCurrentValue( this.currentX );
266
332
  }
267
333
  else {
268
334
  const threshold = this.markerWidth * 0.5;
269
335
 
270
- if(Math.abs(this.startX - x) < threshold ) {
336
+ if( Math.abs(this.startX - x) < threshold ) {
271
337
  this.hovering = 'start';
272
338
  canvas.style.cursor = "grab";
273
339
  }
274
- else if(Math.abs(this.endX - x) < threshold) {
340
+ else if( Math.abs(this.endX - x) < threshold ) {
275
341
  this.hovering = 'end';
276
342
  canvas.style.cursor = "grab";
277
343
  }
278
- else if(Math.abs(this.currentX - x) < threshold) {
344
+ else if( Math.abs(this.currentX - x) < threshold ) {
279
345
  this.hovering = 'current';
280
346
  canvas.style.cursor = "grab";
281
347
  }
@@ -287,16 +353,16 @@ class TimeBar {
287
353
  this._draw();
288
354
  }
289
355
 
290
- resize (size) {
356
+ resize( size ) {
291
357
  this.canvas.width = size[0];
292
358
  this.canvas.height = size[1];
293
359
 
294
360
  let newWidth = size[0] - this.offset * 2;
295
- newWidth = newWidth < 0.00001 ? 0.00001 : newWidth; // actual width of the line = canvas.width - offsetleft - offsetRight
361
+ newWidth = newWidth < 0.00001 ? 0.00001 : newWidth; // actual width of the line = canvas.width - offsetleft - offsetRight
296
362
  const startRatio = (this.startX - this.offset) / this.lineWidth;
297
363
  const currentRatio = (this.currentX - this.offset) / this.lineWidth;
298
364
  const endRatio = (this.endX - this.offset) / this.lineWidth;
299
-
365
+
300
366
  this.lineWidth = newWidth;
301
367
  this.startX = Math.min( Math.max(newWidth * startRatio, 0), newWidth ) + this.offset;
302
368
  this.currentX = Math.min(Math.max(newWidth * currentRatio, 0), newWidth) + this.offset;
@@ -305,6 +371,7 @@ class TimeBar {
305
371
  this._draw();
306
372
  }
307
373
  }
374
+
308
375
  LX.TimeBar = TimeBar;
309
376
 
310
377
 
@@ -322,12 +389,13 @@ class VideoEditor {
322
389
  this.currentTime = this.startTime = 0;
323
390
  this.startTimeString = "0:0";
324
391
  this.endTimeString = "0:0";
325
-
392
+ this._updateTime = true;
393
+ this.speed = options.speed || 1;
326
394
  this.mainArea = area;
327
395
 
328
396
  let videoArea = null;
329
397
  let controlsArea = null;
330
- if(options.controlsArea) {
398
+ if( options.controlsArea ) {
331
399
  videoArea = area;
332
400
  controlsArea = options.controlsArea;
333
401
  }
@@ -335,7 +403,7 @@ class VideoEditor {
335
403
  [videoArea, controlsArea] = area.split({ type: 'vertical', sizes: ["85%", null], minimizable: false, resize: false });
336
404
  }
337
405
  controlsArea.root.classList.add('lexconstrolsarea');
338
-
406
+
339
407
  this.cropArea = document.createElement("div");
340
408
  this.cropArea.id = "cropArea";
341
409
  this.cropArea.className = "resize-area hidden"
@@ -343,20 +411,20 @@ class VideoEditor {
343
411
  this.brCrop = document.createElement("div");
344
412
  this.brCrop.className = " resize-handle br"; // bottom right
345
413
  this.cropArea.append(this.brCrop);
346
-
414
+
347
415
  this.crop = options.crop;
348
416
  this.dragOffsetX = 0;
349
417
  this.dragOffsetY = 0;
350
418
  // Create video element and load it
351
419
  let video = this.video = options.video ?? document.createElement( 'video' );
352
420
  this.loop = options.loop ?? false;
353
-
354
- if(options.src) {
421
+
422
+ if( options.src ) {
355
423
  this.video.src = options.src;
356
- this._loadVideo(options);
424
+ this.loadVideo( options );
357
425
  }
358
-
359
- if(options.videoArea) {
426
+
427
+ if( options.videoArea ) {
360
428
  options.videoArea.root.classList.add("lexvideoeditor");
361
429
  options.videoArea.attach(this.cropArea);
362
430
  videoArea.attach(options.videoArea);
@@ -408,7 +476,38 @@ class VideoEditor {
408
476
  this.controlsPanelLeft.refresh();
409
477
  }, { width: '40px', icon: (this.playing ? 'Pause@solid' : 'Play@solid'), className: "justify-center"});
410
478
 
411
- this.controlsPanelLeft.addLabel(this.startTimeString, {width: 100});
479
+ if(this.speedDialog) {
480
+ this.speedDialog.close();
481
+ }
482
+ this.speedDialog = null;
483
+ const btn = this.controlsPanelLeft.addButton('', '', (v, e) => {
484
+
485
+ // if(this.speedDialog) {
486
+ // this.speedDialog.close();
487
+ // this.speedDialog = null;
488
+ // return;
489
+ // }
490
+
491
+ const panel = new LX.Panel();
492
+ panel.addNumber("Speed", this.speed, (v) => {
493
+ this.speed = v;
494
+ this.video.playbackRate = v;
495
+ if( this.onChangeSpeed ) {
496
+ this.onChangeSpeed( v );
497
+ }
498
+ }, {min: 0, max: 2.5, step: 0.01, nameWidth: "50px"})
499
+
500
+ new LX.Popover( e.target, [ panel ], { align: "start", side: "top", sideOffset: 12 } );
501
+
502
+ }, { width: '40px', title: 'speed', icon: "Timer@solid", className: "justify-center" } );
503
+
504
+ this.controlsPanelLeft.addButton('', 'Loop', (v) => {
505
+ this.loop = !this.loop;
506
+
507
+ this.controlsPanelLeft.refresh();
508
+ }, { width: '40px', title: 'loop', icon: ( 'Repeat@solid'), className: `justify-center`, buttonClass: `${(this.loop ? 'bg-accent' : '')}`});
509
+
510
+ this.controlsPanelLeft.addLabel(this.startTimeString, {width: "100px"});
412
511
  this.controlsPanelLeft.endLine();
413
512
 
414
513
  let availableWidth = leftArea.root.clientWidth - controlsLeft.root.clientWidth;
@@ -417,7 +516,8 @@ class VideoEditor {
417
516
 
418
517
  this.controlsPanelLeft.refresh();
419
518
  controlsLeft.root.style.minWidth = 'fit-content';
420
- controlsLeft.root.classList.add(); controlsLeft.attach(this.controlsPanelLeft);
519
+ // controlsLeft.root.classList.add();
520
+ controlsLeft.attach(this.controlsPanelLeft);
421
521
 
422
522
  // Create right controls panel (ens time)
423
523
  this.controlsPanelRight = new LX.Panel({className: 'lexcontrolspanel'});
@@ -429,15 +529,15 @@ class VideoEditor {
429
529
  controlsRight.root.style.minWidth = 'fit-content';
430
530
  controlsRight.attach(this.controlsPanelRight);
431
531
 
432
- this.timebar.onChangeCurrent = this._setCurrentValue.bind(this);
433
- this.timebar.onChangeStart = this._setStartValue.bind(this);
434
- this.timebar.onChangeEnd = this._setEndValue.bind(this);
532
+ this.timebar.onChangeCurrent = this._setCurrentTime.bind(this);
533
+ this.timebar.onChangeStart = this._setStartTime.bind(this);
534
+ this.timebar.onChangeEnd = this._setEndTime.bind(this);
435
535
 
436
536
  window.addEventListener('resize', (v) => {
437
537
  if(this.onResize) {
438
538
  this.onResize([videoArea.root.clientWidth, videoArea.root.clientHeight]);
439
539
  }
440
- bottomArea.setSize([videoArea.root.clientWidth, 40]);
540
+ bottomArea.setSize([this.controlsArea.root.clientWidth, 40]);
441
541
  let availableWidth = this.controlsArea.root.clientWidth - controlsLeft.root.clientWidth - controlsRight.root.clientWidth;
442
542
  this.timebar.resize([availableWidth, timeBarArea.root.clientHeight]);
443
543
  this.dragCropArea( { clientX: -1, clientY: -1 } );
@@ -446,12 +546,12 @@ class VideoEditor {
446
546
  })
447
547
 
448
548
  this.onKeyUp = (event) => {
449
- if(this.controls && event.key == " ") {
549
+ if( this.controls && event.key == " " ) {
450
550
  event.preventDefault();
451
551
  event.stopPropagation();
452
552
 
453
553
  this.playing = !this.playing;
454
- if(this.playing) {
554
+ if( this.playing ) {
455
555
  if( this.video.currentTime + 0.000001 >= this.endTime) {
456
556
  this.video.currentTime = this.startTime;
457
557
  }
@@ -467,15 +567,18 @@ class VideoEditor {
467
567
  window.addEventListener( "keyup", this.onKeyUp);
468
568
 
469
569
  videoArea.onresize = (v) => {
470
- bottomArea.setSize([v.width, 40]);
570
+ if( bottomArea.parentArea ) {
571
+ bottomArea.setSize([bottomArea.parentArea.root.clientWidth, 40]);
572
+ }
471
573
 
472
574
  const ratio = this.video.clientHeight / this.video.videoHeight;
473
575
  this.cropArea.style.height = this.video.clientHeight + "px";
474
576
  this.cropArea.style.width = this.video.videoWidth * ratio + "px";
475
577
  }
476
578
 
579
+
477
580
  timeBarArea.onresize = (v) => {
478
- let availableWidth = this.controlsArea.root.clientWidth - controlsLeft.root.clientWidth - controlsRight.root.clientWidth;
581
+ let availableWidth = this.controlsArea.root.clientWidth - controlsLeft.root.clientWidth - controlsRight.root.clientWidth - 20;
479
582
  this.timebar.resize([availableWidth, v.height]);
480
583
  }
481
584
 
@@ -483,14 +586,14 @@ class VideoEditor {
483
586
 
484
587
  // Add canvas event listeneres
485
588
  parent.addEventListener( "mousedown", (event) => {
486
- if(this.controls) {
487
- this.timebar.onMouseDown(event);
488
- }
589
+ // if(this.controls) {
590
+ // this.timebar.onMouseDown(event);
591
+ // }
489
592
  });
490
- parent.addEventListener( "mouseup", (event) => {
491
- if(this.controls) {
492
- this.timebar.onMouseUp(event);
493
- }
593
+ parent.addEventListener( "mouseup", (event) => {
594
+ // if(this.controls) {
595
+ // this.timebar.onMouseUp(event);
596
+ // }
494
597
 
495
598
  if( ( this.isDragging || this.isResizing ) && this.onCropArea ) {
496
599
  if( this.onCropArea ) {
@@ -502,23 +605,23 @@ class VideoEditor {
502
605
 
503
606
  });
504
607
  parent.addEventListener( "mousemove", (event) => {
505
- if(this.controls) {
506
- this.timebar.onMouseMove(event);
507
- }
608
+ // if(this.controls) {
609
+ // this.timebar.onMouseMove(event);
610
+ // }
508
611
 
509
- if (this.isResizing) {
510
- this.resizeCropArea(event);
612
+ if ( this.isResizing ) {
613
+ this.resizeCropArea( event );
511
614
  }
512
615
 
513
- if(this.isDragging) {
514
- this.dragCropArea(event);
616
+ if( this.isDragging ) {
617
+ this.dragCropArea( event );
515
618
  }
516
619
  });
517
620
 
518
- this.cropArea.addEventListener('mousedown', (event) => {
621
+ this.cropArea.addEventListener( "mousedown", (event) => {
519
622
 
520
-
521
- if (event.target === this.cropArea) {
623
+
624
+ if ( event.target === this.cropArea ) {
522
625
  const rect = this.cropArea.getBoundingClientRect();
523
626
  this.isDragging = true;
524
627
 
@@ -527,9 +630,9 @@ class VideoEditor {
527
630
  }
528
631
  });
529
632
 
530
- document.querySelectorAll('.resize-handle').forEach(handle => {
633
+ document.querySelectorAll(".resize-handle" ).forEach( handle => {
531
634
 
532
- handle.addEventListener('mousedown', (e) => {
635
+ handle.addEventListener("mousedown", ( e ) => {
533
636
 
534
637
  e.stopPropagation();
535
638
  if (handle.classList[1] === 'br') {
@@ -537,23 +640,24 @@ class VideoEditor {
537
640
  }
538
641
  });
539
642
  });
540
-
643
+
541
644
  this.onChangeStart = null;
542
645
  this.onChangeEnd = null;
543
646
  }
544
647
 
545
- resizeCropArea(event) {
648
+ resizeCropArea( event ) {
546
649
 
547
650
  const mouseX = event.clientX;
548
651
  const mouseY = event.clientY;
549
-
652
+
550
653
  const isCropHidden = this.cropArea.classList.contains("hidden");
551
654
  const nodes = this.cropArea.parentElement.childNodes;
552
-
655
+
553
656
  const rectCrop = this.cropArea.getBoundingClientRect();
554
657
  const rectVideo = this.video.getBoundingClientRect();
555
658
  let width = Math.max( 0, Math.min( mouseX - rectCrop.left, rectVideo.width ) );
556
659
  let height = Math.max( 0, Math.min( mouseY - rectCrop.top, rectVideo.height ) );
660
+
557
661
  if ( (rectCrop.left + width) > rectVideo.right ){
558
662
  width = Math.min( rectVideo.width, rectVideo.right - rectCrop.left);
559
663
  }
@@ -561,9 +665,9 @@ class VideoEditor {
561
665
  height = Math.min( rectVideo.height, rectVideo.bottom - rectCrop.top);
562
666
  }
563
667
 
564
- if ( !isCropHidden ){
668
+ if ( !isCropHidden ){
565
669
  for( let i = 0; i < nodes.length; i++ ) {
566
- if( nodes[i] != this.cropArea ) {
670
+ if( nodes[i] != this.cropArea ) {
567
671
  const rectEl = nodes[i].getBoundingClientRect();
568
672
  nodes[i].style.webkitMask = `linear-gradient(#000 0 0) ${rectCrop.x - rectEl.left}px ${ rectCrop.y - rectEl.top }px / ${width}px ${height}px, linear-gradient(rgba(0, 0, 0, 0.3) 0 0)`;
569
673
  nodes[i].style.webkitMaskRepeat = 'no-repeat';
@@ -593,13 +697,13 @@ class VideoEditor {
593
697
  if( y < rectVideo.top ) {
594
698
  y = rectVideo.top;
595
699
  }
596
-
700
+
597
701
  if( y + rectCrop.height > rectVideo.bottom ) {
598
702
  y = Math.max( rectVideo.top, rectVideo.bottom - rectCrop.height );
599
703
  }
600
704
 
601
705
  if ( !this.cropArea.classList.contains("hidden") ){
602
- const nodes = this.cropArea.parentElement.childNodes;
706
+ const nodes = this.cropArea.parentElement.childNodes;
603
707
  for( let i = 0; i < nodes.length; i++ ) {
604
708
  if( nodes[i] != this.cropArea ) {
605
709
  const rectEl = nodes[i].getBoundingClientRect();
@@ -615,55 +719,59 @@ class VideoEditor {
615
719
 
616
720
  }
617
721
 
618
- async _loadVideo( options = {} ) {
722
+ async loadVideo( options = {} ) {
619
723
  this.videoReady = false;
620
- while(this.video.duration === Infinity || isNaN(this.video.duration) || !this.timebar) {
724
+ while( this.video.duration === Infinity || isNaN(this.video.duration) || !this.timebar ) {
621
725
  await new Promise(r => setTimeout(r, 1000));
622
726
  this.video.currentTime = 10000000 * Math.random();
623
727
  }
624
- this.video.currentTime = 0.01; // BUG: some videos will not play unless this line is present
625
-
728
+ this.video.currentTime = 0.01; // BUG: some videos will not play unless this line is present
729
+
626
730
  // Duration can change if the video is dynamic (stream). This function is to ensure to load all buffer data
627
- const forceLoadChunks = () => {
731
+ const forceLoadChunks = () => {
628
732
  const state = this.videoReady;
629
- if(this.video.readyState > 3) {
733
+ if( this.video.readyState > 3 ) {
630
734
  this.videoReady = true;
631
735
  }
632
- if(!state) {
736
+ if( !state ) {
633
737
  this.video.currentTime = this.video.duration;
634
738
  }
635
739
  }
636
740
 
637
- this.video.addEventListener( "canplaythrough", forceLoadChunks, {passive :true} );
741
+ this.video.addEventListener( "canplaythrough", forceLoadChunks, { passive: true } );
638
742
 
639
- this.video.ondurationchange = (v) => {
743
+ this.video.ondurationchange = ( v ) => {
640
744
  if( this.video.duration != this.endTime ) {
641
745
 
642
746
  this.video.currentTime = this.startTime;
643
747
  console.log("duration changed from", this.endTime, " to ", this.video.duration);
644
748
  this.endTime = this.video.duration;
645
- const x = this._timeToX(this.endTime);
646
- this._setEndValue(x);
749
+ this.timebar.setDuration( this.endTime );
750
+ this.timebar.setEndTime( this.endTime );
647
751
  }
648
752
  this.video.currentTime = this.startTime;
753
+ this.timebar.setCurrentTime( this.video.currentTime );
754
+
649
755
  }
650
-
756
+
651
757
  this.timebar.startX = this.timebar.position.x;
652
758
  this.timebar.endX = this.timebar.position.x + this.timebar.lineWidth;
653
-
759
+ this.startTime = 0;
654
760
  this.endTime = this.video.duration;
655
-
656
- this._setEndValue(this.timebar.endX);
657
- this._setStartValue(this.timebar.startX);
658
- this.timebar.currentX = this._timeToX(this.video.currentTime);
659
- this._setCurrentValue(this.timebar.currentX, false);
660
- this.timebar.update(this.timebar.currentX);
661
-
761
+ this.timebar.setDuration( this.endTime );
762
+ this.timebar.setEndTime( this.video.duration );
763
+ this.timebar.setStartTime( this.startTime );
764
+ this.timebar.setCurrentTime( this.startTime );
765
+ //this.timebar.setStartValue(this.timebar.startX);
766
+ //this.timebar.currentX = this._timeToX(this.video.currentTime);
767
+ //this.timebar.setCurrentValue(this.timebar.currentX);
768
+ //this.timebar.update( this.timebar.currentX );
769
+
662
770
  if ( !this.requestId ){ // only have one update on flight
663
771
  this._update();
664
- }
772
+ }
665
773
  this.controls = options.controls ?? true;
666
-
774
+
667
775
  if ( !this.controls ) {
668
776
  this.hideControls();
669
777
  }
@@ -675,26 +783,27 @@ class VideoEditor {
675
783
 
676
784
  if( this.crop ) {
677
785
  this.showCropArea();
678
- }else{
786
+ }
787
+ else {
679
788
  this.hideCropArea();
680
789
  }
681
790
 
682
791
  window.addEventListener( "keyup", this.onKeyUp);
683
792
 
684
793
  if( this.onVideoLoaded ) {
685
- this.onVideoLoaded(this.video);
794
+ this.onVideoLoaded( this.video );
686
795
  }
687
796
  }
688
797
 
689
798
  _update () {
690
799
 
691
- if(this.onDraw) {
692
- this.onDraw();
693
- }
694
- if(this.playing) {
695
- if( this.video.currentTime + 0.000001 >= this.endTime) {
800
+ // if( this.onDraw ) {
801
+ // this.onDraw();
802
+ // }
803
+ if( this.playing ) {
804
+ if( this.video.currentTime + 0.000001 >= this.endTime ) {
696
805
  this.video.pause();
697
- if(!this.loop) {
806
+ if( !this.loop ) {
698
807
  this.playing = false;
699
808
  this.controlsPanelLeft.refresh();
700
809
  }
@@ -703,29 +812,15 @@ class VideoEditor {
703
812
  this.video.play();
704
813
  }
705
814
  }
706
- const x = this._timeToX(this.video.currentTime);
707
- this._setCurrentValue(x, false);
708
- this.timebar.update(x);
815
+ this._updateTime = false;
816
+ this.timebar.setCurrentTime( this.video.currentTime );
817
+ this._updateTime = true;
709
818
  }
710
819
 
711
- this.requestId = requestAnimationFrame(this._update.bind(this));
712
- }
713
-
714
- _xToTime (x) {
715
- return ((x - this.timebar.offset) / (this.timebar.lineWidth)) * this.video.duration;
716
- }
717
-
718
- _timeToX (time) {
719
- return (time / this.video.duration) * (this.timebar.lineWidth) + this.timebar.offset;
820
+ this.requestId = requestAnimationFrame( this._update.bind(this) );
720
821
  }
721
822
 
722
- _setCurrentValue ( x, updateTime = true ) {
723
- const t = this._xToTime(x);
724
-
725
- if(updateTime) {
726
- this.video.currentTime = t;
727
- }
728
- //console.log( "Computed: " + t)
823
+ timeToString( t ) {
729
824
  let mzminutes = Math.floor(t / 60);
730
825
  let mzseconds = Math.floor(t - (mzminutes * 60));
731
826
  let mzmiliseconds = Math.floor((t - mzseconds)*100);
@@ -733,56 +828,51 @@ class VideoEditor {
733
828
  mzmiliseconds = mzmiliseconds < 10 ? ('0' + mzmiliseconds) : mzmiliseconds;
734
829
  mzseconds = mzseconds < 10 ? ('0' + mzseconds) : mzseconds;
735
830
  mzminutes = mzminutes < 10 ? ('0' + mzminutes) : mzminutes;
736
- this.currentTimeString = mzminutes+':'+mzseconds+'.'+mzmiliseconds;
831
+ return mzminutes + ':' + mzseconds + '.' + mzmiliseconds;
832
+ }
833
+
834
+ _setCurrentTime( t ) {
835
+
836
+ if( this.video.currentTime != t && this._updateTime ) {
837
+ this.video.currentTime = t;
838
+ }
839
+
840
+ this.currentTimeString = this.timeToString( t );
737
841
  this.controlsCurrentPanel.refresh();
738
842
 
739
- if(this.onSetTime) {
843
+ if( this.onSetTime ) {
740
844
  this.onSetTime(t);
741
845
  }
846
+ if( this.onChangeCurrent ) {
847
+ this.onChangeCurrent( t );
848
+ }
742
849
  }
743
850
 
744
- _setStartValue ( x ) {
745
- const t = this._xToTime(x);
851
+ _setStartTime( t ) {
746
852
  this.startTime = this.video.currentTime = t;
747
853
 
748
- let mzminutes = Math.floor(t / 60);
749
- let mzseconds = Math.floor(t - (mzminutes * 60));
750
- let mzmiliseconds = Math.floor((t - mzseconds)*100);
751
-
752
- mzmiliseconds = mzmiliseconds < 10 ? ('0' + mzmiliseconds) : mzmiliseconds;
753
- mzseconds = mzseconds < 10 ? ('0' + mzseconds) : mzseconds;
754
- mzminutes = mzminutes < 10 ? ('0' + mzminutes) : mzminutes;
755
- this.startTimeString = mzminutes+':'+mzseconds+'.'+mzmiliseconds;
854
+ this.startTimeString = this.timeToString( t );
756
855
  this.controlsPanelLeft.refresh();
757
- if(this.onSetTime) {
758
- this.onSetTime(t);
856
+
857
+ if( this.onSetTime ) {
858
+ this.onSetTime( t );
759
859
  }
760
-
761
- if(this.onChangeStart) {
762
- this.onChangeStart(t);
860
+ if( this.onChangeStart ) {
861
+ this.onChangeStart ( t );
763
862
  }
764
863
  }
765
864
 
766
- _setEndValue ( x ) {
767
- const t = this._xToTime(x);
865
+ _setEndTime( t ) {
768
866
  this.endTime = this.video.currentTime = t;
769
867
 
770
- let mzminutes = Math.floor(t / 60);
771
- let mzseconds = Math.floor(t - (mzminutes * 60));
772
- let mzmiliseconds = Math.floor((t - mzseconds)*100);
773
-
774
- mzmiliseconds = mzmiliseconds < 10 ? ('0' + mzmiliseconds) : mzmiliseconds;
775
- mzseconds = mzseconds < 10 ? ('0' + mzseconds) : mzseconds;
776
- mzminutes = mzminutes < 10 ? ('0' + mzminutes) : mzminutes;
777
-
778
- this.endTimeString = mzminutes+':'+mzseconds+'.'+mzmiliseconds;
868
+ this.endTimeString = this.timeToString( t)
779
869
  this.controlsPanelRight.refresh();
780
- if(this.onSetTime) {
870
+
871
+ if( this.onSetTime ) {
781
872
  this.onSetTime(t);
782
873
  }
783
-
784
- if(this.onChangeEnd) {
785
- this.onChangeEnd(t);
874
+ if( this.onChangeEnd ) {
875
+ this.onChangeEnd( t );
786
876
  }
787
877
  }
788
878
 
@@ -821,7 +911,7 @@ class VideoEditor {
821
911
 
822
912
  const nodes = this.cropArea.parentElement.childNodes;
823
913
  for( let i = 0; i < nodes.length; i++ ) {
824
- if( nodes[i] != this.cropArea ) {
914
+ if( nodes[i] != this.cropArea ) {
825
915
  nodes[i].style.webkitMask = "";
826
916
  nodes[i].style.webkitMaskRepeat = 'no-repeat';
827
917
  }
@@ -848,7 +938,7 @@ class VideoEditor {
848
938
 
849
939
  unbind ( ) {
850
940
  this.stopUpdates();
851
-
941
+
852
942
  this.video.pause();
853
943
  this.playing = false;
854
944
  this.controlsPanelLeft.refresh();