lexgui 8.2.0 → 8.2.1
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/Avatar.d.ts +15 -15
- package/build/components/NodeTree.d.ts +51 -51
- package/build/components/Vector.d.ts +10 -10
- package/build/core/Event.d.ts +6 -6
- package/build/core/Namespace.js +1 -1
- package/build/core/Namespace.js.map +1 -1
- package/build/core/Panel.d.ts +538 -538
- package/build/extensions/AssetView.d.ts +137 -137
- package/build/extensions/AssetView.js +5 -6
- package/build/extensions/AssetView.js.map +1 -1
- package/build/extensions/CodeEditor.d.ts +358 -358
- package/build/extensions/CodeEditor.js +7 -7
- package/build/extensions/CodeEditor.js.map +1 -1
- package/build/extensions/DocMaker.js +1 -0
- package/build/extensions/DocMaker.js.map +1 -1
- package/build/extensions/GraphEditor.js +2754 -2754
- package/build/extensions/Timeline.d.ts +668 -668
- package/build/extensions/Timeline.js +2 -2
- package/build/extensions/Timeline.js.map +1 -1
- package/build/extensions/VideoEditor.d.ts +37 -15
- package/build/extensions/VideoEditor.js +287 -166
- package/build/extensions/VideoEditor.js.map +1 -1
- package/build/index.css.d.ts +3 -3
- package/build/index.d.ts +57 -57
- package/build/lexgui.all.js +327 -185
- package/build/lexgui.all.js.map +1 -1
- package/build/lexgui.all.min.js +1 -1
- package/build/lexgui.all.module.js +327 -185
- package/build/lexgui.all.module.js.map +1 -1
- package/build/lexgui.all.module.min.js +1 -1
- package/build/lexgui.css +213 -220
- package/build/lexgui.js +25 -4
- package/build/lexgui.js.map +1 -1
- package/build/lexgui.min.css +1 -1
- package/build/lexgui.min.js +1 -1
- package/build/lexgui.module.js +25 -4
- package/build/lexgui.module.js.map +1 -1
- package/build/lexgui.module.min.js +1 -1
- package/changelog.md +23 -1
- package/examples/all-components.html +3 -4
- package/examples/code-editor.html +11 -0
- package/examples/dialogs.html +13 -2
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ const g$2 = globalThis;
|
|
|
12
12
|
let LX = g$2.LX;
|
|
13
13
|
if (!LX) {
|
|
14
14
|
LX = {
|
|
15
|
-
version: '8.2',
|
|
15
|
+
version: '8.2.1',
|
|
16
16
|
ready: false,
|
|
17
17
|
extensions: [], // Store extensions used
|
|
18
18
|
extraCommandbarEntries: [], // User specific entries for command bar
|
|
@@ -7615,14 +7615,14 @@ class Branch {
|
|
|
7615
7615
|
if (options.id) {
|
|
7616
7616
|
root.id = options.id;
|
|
7617
7617
|
}
|
|
7618
|
-
root.className = LX.mergeClass('lexbranch w-full rounded-lg my-0 mx-auto', options.className);
|
|
7618
|
+
root.className = LX.mergeClass('lexbranch bg-secondary/50 dark:bg-card text-secondary-foreground dark:text-card-foreground w-full rounded-lg my-0 mx-auto', options.className);
|
|
7619
7619
|
var that = this;
|
|
7620
7620
|
this.closed = options.closed ?? false;
|
|
7621
7621
|
this.root = root;
|
|
7622
7622
|
this.components = [];
|
|
7623
7623
|
this.panel = null;
|
|
7624
7624
|
// Create element
|
|
7625
|
-
const title = LX.makeElement('div', 'lexbranchtitle flex cursor-pointer select-none pad-lg
|
|
7625
|
+
const title = LX.makeElement('div', 'lexbranchtitle flex cursor-pointer select-none pad-lg text-lg', '', root);
|
|
7626
7626
|
if (options.icon) {
|
|
7627
7627
|
const branchIcon = LX.makeIcon(options.icon, { iconClass: 'mr-2' });
|
|
7628
7628
|
title.appendChild(branchIcon);
|
|
@@ -7630,7 +7630,7 @@ class Branch {
|
|
|
7630
7630
|
title.innerHTML += name || 'Branch';
|
|
7631
7631
|
const collapseIcon = LX.makeIcon('Right', { iconClass: 'switch-branch-button', svgClass: 'sm' });
|
|
7632
7632
|
title.appendChild(collapseIcon);
|
|
7633
|
-
var branchContent = LX.makeElement('div', 'lexbranchcontent pad-xs
|
|
7633
|
+
var branchContent = LX.makeElement('div', 'lexbranchcontent pad-xs', '', root);
|
|
7634
7634
|
branchContent.id = name.replace(/\s/g, '');
|
|
7635
7635
|
this.content = branchContent;
|
|
7636
7636
|
this._addBranchSeparator();
|
|
@@ -13439,6 +13439,27 @@ LX.addSignal = function (name, obj, callback) {
|
|
|
13439
13439
|
}
|
|
13440
13440
|
LX.signals[name].push(obj);
|
|
13441
13441
|
};
|
|
13442
|
+
/**
|
|
13443
|
+
* @method removeSignal
|
|
13444
|
+
* @param {String} name
|
|
13445
|
+
* @param {Object} targetObj
|
|
13446
|
+
*/
|
|
13447
|
+
LX.removeSignal = function (name, targetObj) {
|
|
13448
|
+
const data = LX.signals[name];
|
|
13449
|
+
if (!data) {
|
|
13450
|
+
return;
|
|
13451
|
+
}
|
|
13452
|
+
if (!targetObj) {
|
|
13453
|
+
delete LX.signals[name];
|
|
13454
|
+
return;
|
|
13455
|
+
}
|
|
13456
|
+
for (let i = 0; i < data.length; ++i) {
|
|
13457
|
+
if (data[i] == targetObj) {
|
|
13458
|
+
data.splice(i, 1);
|
|
13459
|
+
break;
|
|
13460
|
+
}
|
|
13461
|
+
}
|
|
13462
|
+
};
|
|
13442
13463
|
/**
|
|
13443
13464
|
* @method emitSignal
|
|
13444
13465
|
* @param {String} name
|
|
@@ -14445,9 +14466,8 @@ class AssetView {
|
|
|
14445
14466
|
_subscribeTreeEvents(tree) {
|
|
14446
14467
|
// If some of these events we don't have to call "resolve" since the AV itself
|
|
14447
14468
|
// will update the data and refresh when necessary
|
|
14448
|
-
tree.on(
|
|
14449
|
-
if (event.items.length > 1) // Do nothing if multiple selection
|
|
14450
|
-
{
|
|
14469
|
+
tree.on('select', (event, resolve) => {
|
|
14470
|
+
if (event.items.length > 1) { // Do nothing if multiple selection
|
|
14451
14471
|
return;
|
|
14452
14472
|
}
|
|
14453
14473
|
const node = event.items[0];
|
|
@@ -14471,7 +14491,7 @@ class AssetView {
|
|
|
14471
14491
|
this.selectedItem = node;
|
|
14472
14492
|
}
|
|
14473
14493
|
});
|
|
14474
|
-
tree.on(
|
|
14494
|
+
tree.on('beforeMove', (event, resolve) => {
|
|
14475
14495
|
const onBeforeNodeDragged = this._callbacks['beforeNodeDragged'];
|
|
14476
14496
|
const onNodeDragged = this._callbacks['nodeDragged'];
|
|
14477
14497
|
const node = event.items[0];
|
|
@@ -14513,11 +14533,11 @@ class AssetView {
|
|
|
14513
14533
|
av_resolve();
|
|
14514
14534
|
}
|
|
14515
14535
|
});
|
|
14516
|
-
tree.on(
|
|
14536
|
+
tree.on('beforeDelete', (event, resolve) => {
|
|
14517
14537
|
const node = event.items[0];
|
|
14518
14538
|
this._requestDeleteItem(node);
|
|
14519
14539
|
});
|
|
14520
|
-
tree.on(
|
|
14540
|
+
tree.on('beforeRename', (event, resolve) => {
|
|
14521
14541
|
const node = event.items[0];
|
|
14522
14542
|
this._requestRenameItem(node, event.newName, true);
|
|
14523
14543
|
});
|
|
@@ -16006,11 +16026,11 @@ class CodeEditor {
|
|
|
16006
16026
|
rename: false,
|
|
16007
16027
|
skipDefaultIcon: true
|
|
16008
16028
|
});
|
|
16009
|
-
this.explorer.on(
|
|
16029
|
+
this.explorer.on('dblClick', (event) => {
|
|
16010
16030
|
const node = event.items[0];
|
|
16011
16031
|
this.loadTab(node.id);
|
|
16012
16032
|
});
|
|
16013
|
-
this.explorer.on(
|
|
16033
|
+
this.explorer.on('delete', (event) => {
|
|
16014
16034
|
const node = event.items[0];
|
|
16015
16035
|
this.closeTab(node.id);
|
|
16016
16036
|
});
|
|
@@ -16826,12 +16846,12 @@ class CodeEditor {
|
|
|
16826
16846
|
this.codeArea.root.style.height = `calc(100% - ${this._fullVerticalOffset}px)`;
|
|
16827
16847
|
// Process lines on finish computing final sizes
|
|
16828
16848
|
this.processLines();
|
|
16849
|
+
this._preparedAt = performance.now();
|
|
16850
|
+
if (this.onReady) {
|
|
16851
|
+
this.onReady(this);
|
|
16852
|
+
}
|
|
16853
|
+
console.log(`[LX.CodeEditor] Ready! (font size: ${this.fontSize}px)`);
|
|
16829
16854
|
}, 50);
|
|
16830
|
-
if (this.onReady) {
|
|
16831
|
-
this.onReady(this);
|
|
16832
|
-
}
|
|
16833
|
-
this._preparedAt = performance.now();
|
|
16834
|
-
console.log(`[LX.CodeEditor] Ready! (font size: ${this.fontSize}px)`);
|
|
16835
16855
|
}
|
|
16836
16856
|
// Clear signals
|
|
16837
16857
|
clear() {
|
|
@@ -20825,6 +20845,7 @@ class DocMaker {
|
|
|
20825
20845
|
console.log('Copied!');
|
|
20826
20846
|
}
|
|
20827
20847
|
}
|
|
20848
|
+
LX.DocMaker = DocMaker;
|
|
20828
20849
|
|
|
20829
20850
|
// GraphEditor.ts @jxarco
|
|
20830
20851
|
if (!LX) {
|
|
@@ -24144,7 +24165,7 @@ class Timeline {
|
|
|
24144
24165
|
treeTracks = this.generateSelectedItemsTreeData();
|
|
24145
24166
|
}
|
|
24146
24167
|
this.trackTreesComponent = p.addTree(null, treeTracks, { filter: false, rename: false, draggable: false });
|
|
24147
|
-
this.trackTreesComponent.on(
|
|
24168
|
+
this.trackTreesComponent.on('select', (event, resolve) => {
|
|
24148
24169
|
const node = event.items[0];
|
|
24149
24170
|
if (!event.domEvent.shiftKey) {
|
|
24150
24171
|
this.deselectAllTracks(false); // no need to update left panel
|
|
@@ -24154,7 +24175,7 @@ class Timeline {
|
|
|
24154
24175
|
this.setTrackSelection(node.trackData.trackIdx, flag, false, false); // do callback, do not update left panel
|
|
24155
24176
|
}
|
|
24156
24177
|
});
|
|
24157
|
-
this.trackTreesComponent.on(
|
|
24178
|
+
this.trackTreesComponent.on('visibleChanged', (event, resolve) => {
|
|
24158
24179
|
const node = event.items[0];
|
|
24159
24180
|
if (node.trackData) {
|
|
24160
24181
|
this.setTrackState(node.trackData.trackIdx, node.visible, false, false); // do not update left panel
|
|
@@ -27771,17 +27792,22 @@ class TimeBar {
|
|
|
27771
27792
|
duration = 1.0;
|
|
27772
27793
|
canvas;
|
|
27773
27794
|
ctx;
|
|
27795
|
+
options;
|
|
27774
27796
|
markerWidth = 8;
|
|
27775
27797
|
markerHeight;
|
|
27776
27798
|
offset;
|
|
27777
27799
|
lineWidth;
|
|
27778
27800
|
lineHeight;
|
|
27779
|
-
|
|
27801
|
+
linePosition;
|
|
27780
27802
|
startX;
|
|
27781
27803
|
endX;
|
|
27782
27804
|
currentX;
|
|
27783
27805
|
hovering;
|
|
27784
27806
|
dragging;
|
|
27807
|
+
_onMouseUpListener;
|
|
27808
|
+
_onMouseMoveListener;
|
|
27809
|
+
_mouseDownCanvasRect = null;
|
|
27810
|
+
updateTheme;
|
|
27785
27811
|
onChangeCurrent;
|
|
27786
27812
|
onChangeStart;
|
|
27787
27813
|
onChangeEnd;
|
|
@@ -27789,46 +27815,65 @@ class TimeBar {
|
|
|
27789
27815
|
onMouse;
|
|
27790
27816
|
constructor(area, type, options = {}) {
|
|
27791
27817
|
this.type = type ?? TimeBar.TIMEBAR_PLAY;
|
|
27818
|
+
this.options = options ?? {};
|
|
27792
27819
|
this.duration = options.duration ?? this.duration;
|
|
27793
27820
|
// Create canvas
|
|
27794
27821
|
this.canvas = document.createElement('canvas');
|
|
27822
|
+
this.canvas.style.borderRadius = '6px';
|
|
27795
27823
|
this.canvas.width = area.size[0];
|
|
27796
27824
|
this.canvas.height = area.size[1];
|
|
27797
27825
|
area.attach(this.canvas);
|
|
27798
27826
|
this.ctx = this.canvas.getContext('2d');
|
|
27799
27827
|
this.markerWidth = options.markerWidth ?? this.markerWidth;
|
|
27800
|
-
this.markerHeight = options.markerHeight ??
|
|
27801
|
-
|
|
27828
|
+
this.markerHeight = (options.markerHeight ?? 0.5) * this.canvas.height;
|
|
27829
|
+
const defaultOffset = this.markerWidth * 0.5 + 5;
|
|
27830
|
+
if (typeof (options.offset) == 'number') {
|
|
27831
|
+
this.offset = new vec2(options.offset, options.offset);
|
|
27832
|
+
}
|
|
27833
|
+
else if (Array.isArray(options.offset)) {
|
|
27834
|
+
this.offset = new vec2(options.offset[0] ?? defaultOffset, options.offset[1] ?? defaultOffset);
|
|
27835
|
+
}
|
|
27836
|
+
else {
|
|
27837
|
+
this.offset = new vec2(defaultOffset, defaultOffset);
|
|
27838
|
+
}
|
|
27802
27839
|
// dimensions of line (not canvas)
|
|
27803
|
-
this.lineWidth = this.canvas.width - this.offset * 2;
|
|
27840
|
+
this.lineWidth = this.canvas.width - this.offset.x * 2;
|
|
27804
27841
|
this.lineHeight = options.barHeight ?? 5;
|
|
27805
|
-
this.
|
|
27806
|
-
this.startX = this.
|
|
27807
|
-
this.endX = this.
|
|
27842
|
+
this.linePosition = new vec2(this.offset.x, this.canvas.height * 0.5 - this.lineHeight * 0.5);
|
|
27843
|
+
this.startX = this.linePosition.x;
|
|
27844
|
+
this.endX = this.linePosition.x + this.lineWidth;
|
|
27808
27845
|
this.currentX = this.startX;
|
|
27809
27846
|
this._draw();
|
|
27847
|
+
function updateTheme() {
|
|
27848
|
+
TimeBar.BACKGROUND_COLOR = LX.getCSSVariable('secondary');
|
|
27849
|
+
TimeBar.COLOR = LX.getCSSVariable('accent');
|
|
27850
|
+
TimeBar.ACTIVE_COLOR = LX.getCSSVariable('color-blue-400');
|
|
27851
|
+
}
|
|
27852
|
+
this.updateTheme = updateTheme.bind(this);
|
|
27853
|
+
LX.addSignal('@on_new_color_scheme', this.updateTheme);
|
|
27810
27854
|
this.updateTheme();
|
|
27811
|
-
|
|
27812
|
-
|
|
27813
|
-
|
|
27814
|
-
});
|
|
27855
|
+
// prepare event listeners' functions
|
|
27856
|
+
this._onMouseUpListener = this.onMouseUp.bind(this);
|
|
27857
|
+
this._onMouseMoveListener = this.onMouseMove.bind(this);
|
|
27815
27858
|
this.canvas.onmousedown = (e) => this.onMouseDown(e);
|
|
27816
|
-
this.canvas.onmousemove = (e) =>
|
|
27817
|
-
|
|
27859
|
+
this.canvas.onmousemove = (e) => {
|
|
27860
|
+
if (this.dragging)
|
|
27861
|
+
return; // already handled by _onMouseMoveListener
|
|
27862
|
+
this.onMouseMove(e);
|
|
27863
|
+
};
|
|
27818
27864
|
}
|
|
27819
|
-
|
|
27820
|
-
|
|
27821
|
-
|
|
27822
|
-
TimeBar.ACTIVE_COLOR = LX.getCSSVariable('color-blue-400');
|
|
27865
|
+
unbind() {
|
|
27866
|
+
removeEventListener('mousemove', this._onMouseMoveListener);
|
|
27867
|
+
removeEventListener('mouseup', this._onMouseUpListener);
|
|
27823
27868
|
}
|
|
27824
27869
|
setDuration(duration) {
|
|
27825
27870
|
this.duration = duration;
|
|
27826
27871
|
}
|
|
27827
27872
|
xToTime(x) {
|
|
27828
|
-
return ((x - this.offset) / (this.lineWidth)) * this.duration;
|
|
27873
|
+
return ((x - this.offset.x) / (this.lineWidth)) * this.duration;
|
|
27829
27874
|
}
|
|
27830
27875
|
timeToX(time) {
|
|
27831
|
-
return (time / this.duration) * (this.lineWidth) + this.offset;
|
|
27876
|
+
return (time / this.duration) * (this.lineWidth) + this.offset.x;
|
|
27832
27877
|
}
|
|
27833
27878
|
setCurrentTime(time) {
|
|
27834
27879
|
this.currentX = this.timeToX(time);
|
|
@@ -27873,10 +27918,10 @@ class TimeBar {
|
|
|
27873
27918
|
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
27874
27919
|
// Draw background timeline
|
|
27875
27920
|
ctx.fillStyle = TimeBar.COLOR;
|
|
27876
|
-
ctx.fillRect(this.
|
|
27921
|
+
ctx.fillRect(this.linePosition.x, this.linePosition.y, this.lineWidth, this.lineHeight);
|
|
27877
27922
|
// Draw background trimed timeline
|
|
27878
27923
|
ctx.fillStyle = TimeBar.ACTIVE_COLOR;
|
|
27879
|
-
ctx.fillRect(this.startX, this.
|
|
27924
|
+
ctx.fillRect(this.startX, this.linePosition.y, this.endX - this.startX, this.lineHeight);
|
|
27880
27925
|
ctx.restore();
|
|
27881
27926
|
// Min-Max time markers
|
|
27882
27927
|
this._drawTrimMarker('start', this.startX, { color: null, fillColor: TimeBar.ACTIVE_COLOR || '#5f88c9' });
|
|
@@ -27913,9 +27958,9 @@ class TimeBar {
|
|
|
27913
27958
|
ctx.shadowBlur = 0;
|
|
27914
27959
|
}
|
|
27915
27960
|
_drawTimeMarker(name, x, options = {}) {
|
|
27916
|
-
let y = this.offset;
|
|
27961
|
+
let y = this.offset.y;
|
|
27917
27962
|
const w = options.width ? options.width : (this.dragging == name ? 6 : 4);
|
|
27918
|
-
|
|
27963
|
+
this.canvas.height - this.offset.y * 2;
|
|
27919
27964
|
let ctx = this.ctx;
|
|
27920
27965
|
if (!ctx)
|
|
27921
27966
|
return;
|
|
@@ -27930,15 +27975,14 @@ class TimeBar {
|
|
|
27930
27975
|
ctx.fillStyle = ctx.strokeStyle = 'white';
|
|
27931
27976
|
ctx.beginPath();
|
|
27932
27977
|
ctx.moveTo(x, y);
|
|
27933
|
-
ctx.lineTo(x, y +
|
|
27978
|
+
ctx.lineTo(x, this.linePosition.y + this.lineHeight * 0.5);
|
|
27934
27979
|
ctx.stroke();
|
|
27935
27980
|
ctx.closePath();
|
|
27936
27981
|
ctx.fillStyle = ctx.strokeStyle = options.fillColor || '#111'; // "#FFF";
|
|
27937
|
-
y -= this.offset + 8;
|
|
27938
27982
|
// Current time ball grab
|
|
27939
27983
|
ctx.fillStyle = options.fillColor || '#e5e5e5';
|
|
27940
27984
|
ctx.beginPath();
|
|
27941
|
-
ctx.roundRect(x - w * 0.5, y
|
|
27985
|
+
ctx.roundRect(x - w * 0.5, y - w * 0.5, w, w, 5);
|
|
27942
27986
|
ctx.fill();
|
|
27943
27987
|
ctx.shadowBlur = 0;
|
|
27944
27988
|
}
|
|
@@ -27960,13 +28004,11 @@ class TimeBar {
|
|
|
27960
28004
|
const y = e.offsetY;
|
|
27961
28005
|
// Check if some marker is clicked
|
|
27962
28006
|
const threshold = this.markerWidth;
|
|
28007
|
+
const startDist = Math.abs(this.startX - x);
|
|
28008
|
+
const endDist = Math.abs(this.endX - x);
|
|
27963
28009
|
// grab trim markers only from the bottom
|
|
27964
|
-
if (
|
|
27965
|
-
this.dragging = 'start';
|
|
27966
|
-
canvas.style.cursor = 'grabbing';
|
|
27967
|
-
}
|
|
27968
|
-
else if (Math.abs(this.endX - x) < threshold && this.position.y < y) {
|
|
27969
|
-
this.dragging = 'end';
|
|
28010
|
+
if ((startDist < threshold || endDist < threshold) && this.linePosition.y < y) {
|
|
28011
|
+
this.dragging = (startDist < endDist || x < this.startX) ? 'start' : 'end';
|
|
27970
28012
|
canvas.style.cursor = 'grabbing';
|
|
27971
28013
|
}
|
|
27972
28014
|
else {
|
|
@@ -27983,9 +28025,14 @@ class TimeBar {
|
|
|
27983
28025
|
}
|
|
27984
28026
|
this.onSetCurrentValue(this.currentX);
|
|
27985
28027
|
}
|
|
28028
|
+
this._mouseDownCanvasRect = canvas.getBoundingClientRect(); // cache this to avoid stalls during mousemove
|
|
28029
|
+
window.addEventListener('mousemove', this._onMouseMoveListener);
|
|
28030
|
+
window.addEventListener('mouseup', this._onMouseUpListener);
|
|
27986
28031
|
this._draw();
|
|
27987
28032
|
}
|
|
27988
28033
|
onMouseUp(e) {
|
|
28034
|
+
window.removeEventListener('mousemove', this._onMouseMoveListener);
|
|
28035
|
+
window.removeEventListener('mouseup', this._onMouseUpListener);
|
|
27989
28036
|
if (this.onMouse) {
|
|
27990
28037
|
this.onMouse(e);
|
|
27991
28038
|
}
|
|
@@ -28008,17 +28055,17 @@ class TimeBar {
|
|
|
28008
28055
|
e.preventDefault();
|
|
28009
28056
|
const canvas = this.canvas;
|
|
28010
28057
|
// Process mouse
|
|
28011
|
-
const x = e.target == canvas ? e.offsetX : e.clientX -
|
|
28012
|
-
e.target == canvas ? e.offsetY : e.clientY -
|
|
28058
|
+
const x = e.target == canvas ? e.offsetX : (e.clientX - this._mouseDownCanvasRect.left);
|
|
28059
|
+
e.target == canvas ? e.offsetY : (e.clientY - this._mouseDownCanvasRect.top);
|
|
28013
28060
|
if (this.dragging) {
|
|
28014
28061
|
switch (this.dragging) {
|
|
28015
28062
|
case 'start':
|
|
28016
|
-
this.startX = Math.max(this.
|
|
28063
|
+
this.startX = Math.max(this.linePosition.x, Math.min(this.endX, x));
|
|
28017
28064
|
this.currentX = this.startX;
|
|
28018
28065
|
this.onSetStartValue(this.startX);
|
|
28019
28066
|
break;
|
|
28020
28067
|
case 'end':
|
|
28021
|
-
this.endX = Math.max(this.startX, Math.min(this.
|
|
28068
|
+
this.endX = Math.max(this.startX, Math.min(this.linePosition.x + this.lineWidth, x));
|
|
28022
28069
|
this.currentX = this.endX;
|
|
28023
28070
|
this.onSetEndValue(this.endX);
|
|
28024
28071
|
break;
|
|
@@ -28052,15 +28099,18 @@ class TimeBar {
|
|
|
28052
28099
|
resize(size) {
|
|
28053
28100
|
this.canvas.width = Math.max(0, size[0]);
|
|
28054
28101
|
this.canvas.height = Math.max(0, size[1]);
|
|
28055
|
-
|
|
28102
|
+
this.markerHeight = (this.options.markerHeight ?? 0.5) * this.canvas.height;
|
|
28103
|
+
let newWidth = size[0] - this.offset.x * 2;
|
|
28056
28104
|
newWidth = newWidth < 0.00001 ? 0.00001 : newWidth; // actual width of the line = canvas.width - offsetleft - offsetRight
|
|
28057
|
-
const startRatio = (this.startX - this.offset) / this.lineWidth;
|
|
28058
|
-
const currentRatio = (this.currentX - this.offset) / this.lineWidth;
|
|
28059
|
-
const endRatio = (this.endX - this.offset) / this.lineWidth;
|
|
28105
|
+
const startRatio = (this.startX - this.offset.x) / this.lineWidth;
|
|
28106
|
+
const currentRatio = (this.currentX - this.offset.x) / this.lineWidth;
|
|
28107
|
+
const endRatio = (this.endX - this.offset.x) / this.lineWidth;
|
|
28060
28108
|
this.lineWidth = newWidth;
|
|
28061
|
-
this.
|
|
28062
|
-
this.
|
|
28063
|
-
this.
|
|
28109
|
+
this.linePosition.x = this.offset.x;
|
|
28110
|
+
this.linePosition.y = this.canvas.height * 0.5 - this.lineHeight * 0.5;
|
|
28111
|
+
this.startX = Math.min(Math.max(newWidth * startRatio, 0), newWidth) + this.offset.x;
|
|
28112
|
+
this.currentX = Math.min(Math.max(newWidth * currentRatio, 0), newWidth) + this.offset.x;
|
|
28113
|
+
this.endX = Math.min(Math.max(newWidth * endRatio, 0), newWidth) + this.offset.x;
|
|
28064
28114
|
this._draw();
|
|
28065
28115
|
}
|
|
28066
28116
|
}
|
|
@@ -28081,10 +28131,7 @@ class VideoEditor {
|
|
|
28081
28131
|
playing = false;
|
|
28082
28132
|
videoReady = false;
|
|
28083
28133
|
controls = true;
|
|
28084
|
-
startTimeString = '0:0';
|
|
28085
|
-
endTimeString = '0:0';
|
|
28086
28134
|
speed = 1.0;
|
|
28087
|
-
currentTime = 0.0;
|
|
28088
28135
|
startTime = 0.0;
|
|
28089
28136
|
endTime = 0.0;
|
|
28090
28137
|
requestId;
|
|
@@ -28095,27 +28142,29 @@ class VideoEditor {
|
|
|
28095
28142
|
crop = false;
|
|
28096
28143
|
dragOffsetX = 0.0;
|
|
28097
28144
|
dragOffsetY = 0.0;
|
|
28098
|
-
|
|
28099
|
-
timebar;
|
|
28145
|
+
timebar = null;
|
|
28100
28146
|
mainArea;
|
|
28101
28147
|
cropArea; // HTMLElement with normCoord attribute;
|
|
28148
|
+
videoArea;
|
|
28102
28149
|
controlsArea;
|
|
28103
|
-
|
|
28104
|
-
controlsPanelRight;
|
|
28105
|
-
controlsCurrentPanel;
|
|
28150
|
+
controlsComponents;
|
|
28106
28151
|
onChangeCurrent;
|
|
28107
28152
|
onChangeStart;
|
|
28108
28153
|
onChangeEnd;
|
|
28109
28154
|
onKeyUp;
|
|
28110
28155
|
onSetTime;
|
|
28111
28156
|
onVideoLoaded;
|
|
28112
|
-
onCropArea;
|
|
28113
28157
|
onResize;
|
|
28158
|
+
onCropArea;
|
|
28114
28159
|
onChangeSpeed;
|
|
28160
|
+
onChangeState;
|
|
28161
|
+
onChangeLoop;
|
|
28115
28162
|
_updateTime = true;
|
|
28116
28163
|
_onCropMouseUp;
|
|
28117
28164
|
_onCropMouseMove;
|
|
28118
|
-
resize;
|
|
28165
|
+
resize = null;
|
|
28166
|
+
resizeControls = null;
|
|
28167
|
+
resizeVideo = null;
|
|
28119
28168
|
constructor(area, options = {}) {
|
|
28120
28169
|
this.options = options ?? {};
|
|
28121
28170
|
this.speed = options.speed ?? this.speed;
|
|
@@ -28158,120 +28207,42 @@ class VideoEditor {
|
|
|
28158
28207
|
videoArea.root.classList.add('lexvideoeditor');
|
|
28159
28208
|
}
|
|
28160
28209
|
videoArea.root.style.position = 'relative';
|
|
28210
|
+
this.videoArea = videoArea;
|
|
28161
28211
|
this.controlsArea = controlsArea;
|
|
28162
|
-
|
|
28163
|
-
|
|
28164
|
-
|
|
28165
|
-
|
|
28166
|
-
|
|
28167
|
-
|
|
28168
|
-
|
|
28169
|
-
|
|
28170
|
-
|
|
28171
|
-
this.controlsCurrentPanel.clear();
|
|
28172
|
-
this.controlsCurrentPanel.addLabel(this.currentTimeString, { float: 'center' });
|
|
28173
|
-
};
|
|
28174
|
-
topArea.root.classList.add('lexflexarea');
|
|
28175
|
-
topArea.attach(this.controlsCurrentPanel);
|
|
28176
|
-
this.controlsCurrentPanel.refresh();
|
|
28177
|
-
const style = getComputedStyle(bottomArea.root);
|
|
28178
|
-
let padding = Number(style.getPropertyValue('padding').replace('px', ''));
|
|
28179
|
-
this.timebar = new TimeBar(timeBarArea, TimeBar.TIMEBAR_TRIM, { offset: padding });
|
|
28180
|
-
// Create controls panel (play/pause button and start time)
|
|
28181
|
-
this.controlsPanelLeft = new LX.Panel({ className: 'lexcontrolspanel' });
|
|
28182
|
-
this.controlsPanelLeft.refresh = () => {
|
|
28183
|
-
this.controlsPanelLeft.clear();
|
|
28184
|
-
this.controlsPanelLeft.sameLine();
|
|
28185
|
-
let playbtn = this.controlsPanelLeft.addButton(null, 'PlayButton', (v) => {
|
|
28186
|
-
this.playing = v;
|
|
28187
|
-
if (this.playing) {
|
|
28188
|
-
if (this.video.currentTime + 0.000001 >= this.endTime) {
|
|
28189
|
-
this.video.currentTime = this.startTime;
|
|
28190
|
-
}
|
|
28191
|
-
this.video.play();
|
|
28192
|
-
}
|
|
28193
|
-
else {
|
|
28194
|
-
this.video.pause();
|
|
28195
|
-
}
|
|
28196
|
-
}, { icon: 'Play@solid', swap: 'Pause@solid', hideName: true, title: 'Play', tooltip: true, className: 'justify-center' });
|
|
28197
|
-
playbtn.setState(this.playing, true);
|
|
28198
|
-
this.controlsPanelLeft.addButton(null, '', (v, e) => {
|
|
28199
|
-
const panel = new LX.Panel();
|
|
28200
|
-
panel.addRange('Speed', this.speed, (v) => {
|
|
28201
|
-
this.speed = v;
|
|
28202
|
-
this.video.playbackRate = v;
|
|
28203
|
-
if (this.onChangeSpeed) {
|
|
28204
|
-
this.onChangeSpeed(v);
|
|
28205
|
-
}
|
|
28206
|
-
}, { min: 0, max: 2.5, step: 0.01, hideName: true });
|
|
28207
|
-
new LX.Popover(e.target, [panel], { align: 'start', side: 'top', sideOffset: 12 });
|
|
28208
|
-
}, { icon: 'Timer@solid', title: 'Speed', tooltip: true, className: 'justify-center' });
|
|
28209
|
-
this.controlsPanelLeft.addButton(null, 'Loop', (v) => {
|
|
28210
|
-
this.loop = v;
|
|
28211
|
-
}, { title: 'Loop', tooltip: true, icon: ('Repeat@solid'), className: `justify-center`, selectable: true, selected: this.loop });
|
|
28212
|
-
this.controlsPanelLeft.addLabel(this.startTimeString, { width: '100px' });
|
|
28213
|
-
this.controlsPanelLeft.endLine();
|
|
28214
|
-
let availableWidth = leftArea.root.clientWidth - controlsLeft.root.clientWidth;
|
|
28215
|
-
this.timebar.resize([availableWidth, timeBarArea.root.clientHeight]);
|
|
28216
|
-
};
|
|
28217
|
-
this.controlsPanelLeft.refresh();
|
|
28218
|
-
controlsLeft.root.style.minWidth = 'fit-content';
|
|
28219
|
-
// controlsLeft.root.classList.add();
|
|
28220
|
-
controlsLeft.attach(this.controlsPanelLeft);
|
|
28221
|
-
// Create right controls panel (ens time)
|
|
28222
|
-
this.controlsPanelRight = new LX.Panel({ className: 'lexcontrolspanel' });
|
|
28223
|
-
this.controlsPanelRight.refresh = () => {
|
|
28224
|
-
this.controlsPanelRight.clear();
|
|
28225
|
-
this.controlsPanelRight.addLabel(this.endTimeString, { width: 100 });
|
|
28212
|
+
this.controlsComponents = {
|
|
28213
|
+
timebar: null,
|
|
28214
|
+
playBtn: null,
|
|
28215
|
+
speedBtn: null,
|
|
28216
|
+
loopBtn: null,
|
|
28217
|
+
trimStartText: null,
|
|
28218
|
+
trimEndText: null,
|
|
28219
|
+
curTimeText: null,
|
|
28220
|
+
resetCropBtn: null
|
|
28226
28221
|
};
|
|
28227
|
-
this.
|
|
28228
|
-
|
|
28229
|
-
controlsRight.attach(this.controlsPanelRight);
|
|
28230
|
-
this.timebar.onChangeCurrent = this._setCurrentTime.bind(this);
|
|
28231
|
-
this.timebar.onChangeStart = this._setStartTime.bind(this);
|
|
28232
|
-
this.timebar.onChangeEnd = this._setEndTime.bind(this);
|
|
28233
|
-
this.resize = () => {
|
|
28234
|
-
bottomArea.setSize([this.controlsArea.root.clientWidth, 40]);
|
|
28235
|
-
let availableWidth = this.controlsArea.root.clientWidth - controlsLeft.root.clientWidth
|
|
28236
|
-
- controlsRight.root.clientWidth;
|
|
28237
|
-
this.timebar.resize([availableWidth, timeBarArea.root.clientHeight]);
|
|
28222
|
+
this.createControls();
|
|
28223
|
+
this.resizeVideo = () => {
|
|
28238
28224
|
this.moveCropArea(this.cropArea.normCoords.x, this.cropArea.normCoords.y, true);
|
|
28239
28225
|
this.resizeCropArea(this.cropArea.normCoords.w, this.cropArea.normCoords.h, true);
|
|
28240
28226
|
if (this.onResize) {
|
|
28241
28227
|
this.onResize([videoArea.root.clientWidth, videoArea.root.clientHeight]);
|
|
28242
28228
|
}
|
|
28243
28229
|
};
|
|
28230
|
+
this.resize = () => {
|
|
28231
|
+
this.resizeVideo();
|
|
28232
|
+
this.resizeControls();
|
|
28233
|
+
};
|
|
28244
28234
|
area.onresize = this.resize.bind(this);
|
|
28245
28235
|
window.addEventListener('resize', area.onresize);
|
|
28246
28236
|
this.onKeyUp = (e) => {
|
|
28247
28237
|
if (this.controls && e.key == ' ') {
|
|
28248
28238
|
e.preventDefault();
|
|
28249
28239
|
e.stopPropagation();
|
|
28250
|
-
|
|
28251
|
-
|
|
28252
|
-
if (this.video.currentTime + 0.000001 >= this.endTime) {
|
|
28253
|
-
this.video.currentTime = this.startTime;
|
|
28254
|
-
}
|
|
28255
|
-
this.video.play();
|
|
28256
|
-
}
|
|
28257
|
-
else {
|
|
28258
|
-
this.video.pause();
|
|
28259
|
-
}
|
|
28260
|
-
this.controlsPanelLeft.refresh();
|
|
28240
|
+
// do not skip callback
|
|
28241
|
+
this.controlsComponents.playBtn?.setState(!this.playing, false);
|
|
28261
28242
|
}
|
|
28262
28243
|
};
|
|
28263
28244
|
window.addEventListener('keyup', this.onKeyUp);
|
|
28264
|
-
const parent = controlsArea.parentElement ? controlsArea.parentElement : controlsArea.root.parentElement;
|
|
28265
|
-
// Add canvas event listeneres
|
|
28266
|
-
parent.addEventListener('mousedown', (e) => {
|
|
28267
|
-
// if( this.controls) {
|
|
28268
|
-
// this.timebar.onMouseDown(e);
|
|
28269
|
-
// }
|
|
28270
|
-
});
|
|
28271
28245
|
this._onCropMouseUp = (event) => {
|
|
28272
|
-
// if(this.controls) {
|
|
28273
|
-
// this.timebar.onMouseUp(event);
|
|
28274
|
-
// }
|
|
28275
28246
|
event.preventDefault();
|
|
28276
28247
|
event.stopPropagation();
|
|
28277
28248
|
if ((this.isDragging || this.isResizing) && this.onCropArea) {
|
|
@@ -28283,9 +28254,6 @@ class VideoEditor {
|
|
|
28283
28254
|
document.removeEventListener('mousemove', this._onCropMouseMove); // self destroy. Added during mouseDown on cropArea and handles
|
|
28284
28255
|
};
|
|
28285
28256
|
this._onCropMouseMove = (event) => {
|
|
28286
|
-
// if(this.controls) {
|
|
28287
|
-
// this.timebar.onMouseMove(event);
|
|
28288
|
-
// }
|
|
28289
28257
|
window.getSelection()?.removeAllRanges();
|
|
28290
28258
|
event.preventDefault();
|
|
28291
28259
|
event.stopPropagation();
|
|
@@ -28346,6 +28314,182 @@ class VideoEditor {
|
|
|
28346
28314
|
this.onChangeStart = null;
|
|
28347
28315
|
this.onChangeEnd = null;
|
|
28348
28316
|
}
|
|
28317
|
+
createControls(options = null) {
|
|
28318
|
+
const controlsArea = this.controlsArea;
|
|
28319
|
+
options = options ?? this.options;
|
|
28320
|
+
// clear area. Signals are not cleared !!! (not a problem if there are no signals)
|
|
28321
|
+
while (controlsArea.root.children.length) {
|
|
28322
|
+
controlsArea.root.children[0].remove();
|
|
28323
|
+
}
|
|
28324
|
+
controlsArea.sections.length = 0;
|
|
28325
|
+
// start trimming text
|
|
28326
|
+
this.controlsComponents.trimStartText = new LX.TextInput(null, this.timeToString(this.startTime), null, { width: '100px',
|
|
28327
|
+
title: 'Trimmed Start Time', disabled: true, inputClass: 'bg-none' });
|
|
28328
|
+
this.controlsComponents.trimEndText = new LX.TextInput(null, this.timeToString(this.endTime), null, { width: '100px',
|
|
28329
|
+
title: 'Trimmed End Time', disabled: true, inputClass: 'bg-none' });
|
|
28330
|
+
this.controlsComponents.curTimeText = new LX.TextInput(null, this.video.currentTime, null, { title: 'Current Time', float: 'center',
|
|
28331
|
+
disabled: true, inputClass: 'bg-none' });
|
|
28332
|
+
// reset crop area
|
|
28333
|
+
this.controlsComponents.resetCropBtn = new LX.Button('ResetCrop', null, (v) => {
|
|
28334
|
+
this.moveCropArea(0, 0, true);
|
|
28335
|
+
this.resizeCropArea(1, 1, true);
|
|
28336
|
+
if (this.onCropArea) {
|
|
28337
|
+
this.onCropArea(this.getCroppedArea());
|
|
28338
|
+
}
|
|
28339
|
+
}, { width: '40px', title: 'Reset Crop Area', icon: 'Crop@solid', hideName: true,
|
|
28340
|
+
className: 'justify-center' + (this.crop ? '' : ' hidden') });
|
|
28341
|
+
// play button
|
|
28342
|
+
this.controlsComponents.playBtn = new LX.Button('Play', '', (v) => {
|
|
28343
|
+
this.playing = v;
|
|
28344
|
+
if (this.playing) {
|
|
28345
|
+
if (this.video.currentTime + 0.000001 >= this.endTime) {
|
|
28346
|
+
this.video.currentTime = this.startTime;
|
|
28347
|
+
}
|
|
28348
|
+
this.video.play();
|
|
28349
|
+
}
|
|
28350
|
+
else {
|
|
28351
|
+
this.video.pause();
|
|
28352
|
+
}
|
|
28353
|
+
if (this.onChangeState) {
|
|
28354
|
+
this.onChangeState(v);
|
|
28355
|
+
}
|
|
28356
|
+
}, { width: '40px', title: 'Play/Pause', icon: 'Play@solid', swap: 'Pause@solid', hideName: true, className: 'justify-center' });
|
|
28357
|
+
this.controlsComponents.playBtn.setState(this.playing, true);
|
|
28358
|
+
// speed button
|
|
28359
|
+
this.controlsComponents.speedBtn = new LX.Button('Speed', '', (v, e) => {
|
|
28360
|
+
const panel = new LX.Panel();
|
|
28361
|
+
panel.addRange('Speed', this.speed, (v) => {
|
|
28362
|
+
this.speed = v;
|
|
28363
|
+
this.video.playbackRate = v;
|
|
28364
|
+
if (this.onChangeSpeed) {
|
|
28365
|
+
this.onChangeSpeed(v);
|
|
28366
|
+
}
|
|
28367
|
+
}, { min: 0, max: 2.5, step: 0.01, hideName: true });
|
|
28368
|
+
new LX.Popover(e.target, [panel], { align: 'start', side: 'top', sideOffset: 12 });
|
|
28369
|
+
}, { width: '40px', title: 'Speed', hideName: true, icon: 'Timer@solid', className: 'justify-center' });
|
|
28370
|
+
// loop button
|
|
28371
|
+
this.controlsComponents.loopBtn = new LX.Button('', 'Loop', (v) => {
|
|
28372
|
+
this.loop = v;
|
|
28373
|
+
if (this.onChangeLoop) {
|
|
28374
|
+
this.onChangeLoop(v);
|
|
28375
|
+
}
|
|
28376
|
+
}, { width: '40px', hideName: true, title: 'Loop', icon: 'Repeat@solid', className: `justify-center`, selectable: true,
|
|
28377
|
+
selected: this.loop });
|
|
28378
|
+
let timeBarArea = null;
|
|
28379
|
+
if (typeof (options.controlsLayout) == 'function') {
|
|
28380
|
+
timeBarArea = options.controlsLayout;
|
|
28381
|
+
}
|
|
28382
|
+
else if (options.controlsLayout == 1) {
|
|
28383
|
+
timeBarArea = this._createControlsLayout_1();
|
|
28384
|
+
}
|
|
28385
|
+
else {
|
|
28386
|
+
timeBarArea = this._createControlsLayout_0();
|
|
28387
|
+
}
|
|
28388
|
+
if (this.timebar) {
|
|
28389
|
+
this.timebar.unbind();
|
|
28390
|
+
}
|
|
28391
|
+
this.timebar = this.controlsComponents.timebar = new TimeBar(timeBarArea, TimeBar.TIMEBAR_TRIM, { offset: [12, null] });
|
|
28392
|
+
this.timebar.onChangeCurrent = this._setCurrentTime.bind(this);
|
|
28393
|
+
this.timebar.onChangeStart = this._setStartTime.bind(this);
|
|
28394
|
+
this.timebar.onChangeEnd = this._setEndTime.bind(this);
|
|
28395
|
+
let duration = 1;
|
|
28396
|
+
if (this.video.duration !== Infinity && !isNaN(this.video.duration)) {
|
|
28397
|
+
duration = this.video.duration;
|
|
28398
|
+
}
|
|
28399
|
+
this.timebar.setDuration(duration);
|
|
28400
|
+
this.timebar.setEndTime(this.endTime);
|
|
28401
|
+
this.timebar.setStartTime(this.startTime);
|
|
28402
|
+
this.timebar.setCurrentTime(this.startTime);
|
|
28403
|
+
this.resizeControls();
|
|
28404
|
+
}
|
|
28405
|
+
/**
|
|
28406
|
+
* Creates the areas where components will be.
|
|
28407
|
+
* Attaches all (desired) components of controlsComponents except the timebar
|
|
28408
|
+
* @returns {Area} for the timebar
|
|
28409
|
+
* Layout:
|
|
28410
|
+
* |--------------------------timebar--------------------------|
|
|
28411
|
+
* play speed loop resetCrop curTime trimStart / trimEnd
|
|
28412
|
+
*/
|
|
28413
|
+
_createControlsLayout_1() {
|
|
28414
|
+
const controlsArea = this.controlsArea;
|
|
28415
|
+
// Create playing timeline area and attach panels
|
|
28416
|
+
let [timeBarArea, bottomArea] = controlsArea.split({ type: 'vertical', sizes: ['50%', null], minimizable: false, resize: false });
|
|
28417
|
+
bottomArea.root.classList.add('relative');
|
|
28418
|
+
let separator = document.createElement('p');
|
|
28419
|
+
separator.style.alignContent = 'center';
|
|
28420
|
+
separator.innerText = '/';
|
|
28421
|
+
let trimDiv = LX.makeContainer(['fit-content', '100%'], 'relative flex flex-row pb-2', null, bottomArea, { float: 'right' });
|
|
28422
|
+
trimDiv.appendChild(this.controlsComponents.trimStartText.root);
|
|
28423
|
+
trimDiv.appendChild(separator);
|
|
28424
|
+
trimDiv.appendChild(this.controlsComponents.trimEndText.root);
|
|
28425
|
+
this.controlsComponents.trimStartText.root.querySelector('input').classList.add('text-end');
|
|
28426
|
+
this.controlsComponents.trimStartText.root.classList.add('top-0', 'bottom-0');
|
|
28427
|
+
this.controlsComponents.trimEndText.root.classList.add('top-0', 'bottom-0');
|
|
28428
|
+
// current time
|
|
28429
|
+
let curTimeDiv = LX.makeContainer(['100%', '100%'], 'absolute top-0 left-0 flex flex-row justify-center items-center pb-2', null, bottomArea, {});
|
|
28430
|
+
curTimeDiv.appendChild(this.controlsComponents.curTimeText.root);
|
|
28431
|
+
// Buttons
|
|
28432
|
+
const buttonsPanel = bottomArea.addPanel({ className: 'absolute top-0 left-0 flex flex-row pl-4 pr-4 pt-1 pb-2' });
|
|
28433
|
+
buttonsPanel.root.classList.remove('pad-md');
|
|
28434
|
+
buttonsPanel._attachComponent(this.controlsComponents.playBtn);
|
|
28435
|
+
buttonsPanel._attachComponent(this.controlsComponents.speedBtn);
|
|
28436
|
+
buttonsPanel._attachComponent(this.controlsComponents.loopBtn);
|
|
28437
|
+
buttonsPanel._attachComponent(this.controlsComponents.resetCropBtn);
|
|
28438
|
+
this.controlsComponents.playBtn.root.classList.add('pl-0');
|
|
28439
|
+
this.controlsComponents.resetCropBtn.root.classList.add('pr-0');
|
|
28440
|
+
// timebar
|
|
28441
|
+
timeBarArea.root.classList.add('p-4', 'pb-0');
|
|
28442
|
+
this.resizeControls = () => {
|
|
28443
|
+
const style = getComputedStyle(timeBarArea.root);
|
|
28444
|
+
let pleft = parseFloat(style.paddingLeft);
|
|
28445
|
+
let pright = parseFloat(style.paddingRight);
|
|
28446
|
+
let ptop = parseFloat(style.paddingTop);
|
|
28447
|
+
let pbot = parseFloat(style.paddingBottom);
|
|
28448
|
+
// assuming timeBarArea will not overflow
|
|
28449
|
+
this.timebar.resize([timeBarArea.root.clientWidth - pleft - pright, timeBarArea.root.clientHeight - ptop - pbot]);
|
|
28450
|
+
};
|
|
28451
|
+
return timeBarArea;
|
|
28452
|
+
}
|
|
28453
|
+
/**
|
|
28454
|
+
* Creates the areas where components will be.
|
|
28455
|
+
* Attaches all (desired) components of controlsComponents except the timebar
|
|
28456
|
+
* @returns {Area} for the timebar
|
|
28457
|
+
* Layout:
|
|
28458
|
+
* curTime
|
|
28459
|
+
* play speed loop trimStart |---timebar---| trimend
|
|
28460
|
+
*/
|
|
28461
|
+
_createControlsLayout_0() {
|
|
28462
|
+
const controlsArea = this.controlsArea;
|
|
28463
|
+
// Create playing timeline area and attach panels
|
|
28464
|
+
let [topArea, bottomArea] = controlsArea.split({ type: 'vertical', sizes: ['50%', null], minimizable: false, resize: false });
|
|
28465
|
+
bottomArea.setSize([bottomArea.size[0], 40]);
|
|
28466
|
+
let [leftArea, controlsRight] = bottomArea.split({ type: 'horizontal', sizes: ['92%', null], minimizable: false, resize: false });
|
|
28467
|
+
let [controlsLeft, timeBarArea] = leftArea.split({ type: 'horizontal', sizes: ['10%', null], minimizable: false, resize: false });
|
|
28468
|
+
const controlsCurrentPanel = topArea.addPanel({ className: 'flex' });
|
|
28469
|
+
controlsCurrentPanel._attachComponent(this.controlsComponents.curTimeText);
|
|
28470
|
+
// Create controls panel (play/pause button and start time)
|
|
28471
|
+
controlsLeft.root.classList.add('min-w-fit');
|
|
28472
|
+
const controlsPanelLeft = controlsLeft.addPanel({ className: 'lexcontrolspanel p-0 pl-2' });
|
|
28473
|
+
controlsPanelLeft.root.classList.remove('pad-md');
|
|
28474
|
+
controlsPanelLeft.sameLine();
|
|
28475
|
+
controlsPanelLeft._attachComponent(this.controlsComponents.playBtn);
|
|
28476
|
+
controlsPanelLeft._attachComponent(this.controlsComponents.speedBtn);
|
|
28477
|
+
controlsPanelLeft._attachComponent(this.controlsComponents.loopBtn);
|
|
28478
|
+
controlsPanelLeft._attachComponent(this.controlsComponents.trimStartText);
|
|
28479
|
+
controlsPanelLeft.endLine();
|
|
28480
|
+
// Create right controls panel (end time)
|
|
28481
|
+
controlsRight.root.classList.add('min-w-fit');
|
|
28482
|
+
const controlsPanelRight = controlsRight.addPanel({ className: 'lexcontrolspanel p-0' });
|
|
28483
|
+
controlsPanelRight.root.classList.remove('pad-md');
|
|
28484
|
+
controlsPanelRight._attachComponent(this.controlsComponents.trimEndText);
|
|
28485
|
+
this.resizeControls = () => {
|
|
28486
|
+
bottomArea.setSize([this.controlsArea.root.clientWidth, 40]);
|
|
28487
|
+
let availableWidth = this.controlsArea.root.clientWidth - controlsLeft.root.clientWidth
|
|
28488
|
+
- controlsRight.root.clientWidth;
|
|
28489
|
+
this.timebar.resize([availableWidth, timeBarArea.root.clientHeight]);
|
|
28490
|
+
};
|
|
28491
|
+
return timeBarArea;
|
|
28492
|
+
}
|
|
28349
28493
|
setCropAreaHandles(flags) {
|
|
28350
28494
|
// remove existing resizer handles
|
|
28351
28495
|
const resizers = this.cropArea.getElementsByClassName('resize-handle');
|
|
@@ -28474,18 +28618,12 @@ class VideoEditor {
|
|
|
28474
28618
|
this.video.currentTime = this.startTime;
|
|
28475
28619
|
this.timebar.setCurrentTime(this.video.currentTime);
|
|
28476
28620
|
};
|
|
28477
|
-
this.timebar.startX = this.timebar.position.x;
|
|
28478
|
-
this.timebar.endX = this.timebar.position.x + this.timebar.lineWidth;
|
|
28479
28621
|
this.startTime = 0;
|
|
28480
28622
|
this.endTime = this.video.duration;
|
|
28481
28623
|
this.timebar.setDuration(this.endTime);
|
|
28482
28624
|
this.timebar.setEndTime(this.video.duration);
|
|
28483
28625
|
this.timebar.setStartTime(this.startTime);
|
|
28484
28626
|
this.timebar.setCurrentTime(this.startTime);
|
|
28485
|
-
// this.timebar.setStartValue( this.timebar.startX);
|
|
28486
|
-
// this.timebar.currentX = this._timeToX( this.video.currentTime);
|
|
28487
|
-
// this.timebar.setCurrentValue( this.timebar.currentX);
|
|
28488
|
-
// this.timebar.update( this.timebar.currentX );
|
|
28489
28627
|
// only have one update on flight
|
|
28490
28628
|
if (!this.requestId) {
|
|
28491
28629
|
this._update();
|
|
@@ -28518,7 +28656,7 @@ class VideoEditor {
|
|
|
28518
28656
|
this.video.pause();
|
|
28519
28657
|
if (!this.loop) {
|
|
28520
28658
|
this.playing = false;
|
|
28521
|
-
this.
|
|
28659
|
+
this.controlsComponents.playBtn?.setState(false, true); // skip callback
|
|
28522
28660
|
}
|
|
28523
28661
|
else {
|
|
28524
28662
|
this.video.currentTime = this.startTime;
|
|
@@ -28544,8 +28682,7 @@ class VideoEditor {
|
|
|
28544
28682
|
if (this.video.currentTime != t && this._updateTime) {
|
|
28545
28683
|
this.video.currentTime = t;
|
|
28546
28684
|
}
|
|
28547
|
-
this.
|
|
28548
|
-
this.controlsCurrentPanel.refresh();
|
|
28685
|
+
this.controlsComponents.curTimeText?.set(this.timeToString(t));
|
|
28549
28686
|
if (this.onSetTime) {
|
|
28550
28687
|
this.onSetTime(t);
|
|
28551
28688
|
}
|
|
@@ -28555,8 +28692,7 @@ class VideoEditor {
|
|
|
28555
28692
|
}
|
|
28556
28693
|
_setStartTime(t) {
|
|
28557
28694
|
this.startTime = this.video.currentTime = t;
|
|
28558
|
-
this.
|
|
28559
|
-
this.controlsPanelLeft.refresh();
|
|
28695
|
+
this.controlsComponents.trimStartText?.set(this.timeToString(t));
|
|
28560
28696
|
if (this.onSetTime) {
|
|
28561
28697
|
this.onSetTime(t);
|
|
28562
28698
|
}
|
|
@@ -28566,8 +28702,7 @@ class VideoEditor {
|
|
|
28566
28702
|
}
|
|
28567
28703
|
_setEndTime(t) {
|
|
28568
28704
|
this.endTime = this.video.currentTime = t;
|
|
28569
|
-
this.
|
|
28570
|
-
this.controlsPanelRight.refresh();
|
|
28705
|
+
this.controlsComponents.trimEndText?.set(this.timeToString(t));
|
|
28571
28706
|
if (this.onSetTime) {
|
|
28572
28707
|
this.onSetTime(t);
|
|
28573
28708
|
}
|
|
@@ -28588,7 +28723,9 @@ class VideoEditor {
|
|
|
28588
28723
|
return this.cropArea.getBoundingClientRect();
|
|
28589
28724
|
}
|
|
28590
28725
|
showCropArea() {
|
|
28726
|
+
this.crop = true;
|
|
28591
28727
|
this.cropArea.classList.remove('hidden');
|
|
28728
|
+
this.controlsComponents.resetCropBtn?.root.classList.remove('hidden');
|
|
28592
28729
|
const nodes = this.cropArea.parentElement?.childNodes ?? [];
|
|
28593
28730
|
const rect = this.cropArea.getBoundingClientRect();
|
|
28594
28731
|
for (let i = 0; i < nodes.length; i++) {
|
|
@@ -28601,7 +28738,9 @@ class VideoEditor {
|
|
|
28601
28738
|
}
|
|
28602
28739
|
}
|
|
28603
28740
|
hideCropArea() {
|
|
28741
|
+
this.crop = false;
|
|
28604
28742
|
this.cropArea.classList.add('hidden');
|
|
28743
|
+
this.controlsComponents.resetCropBtn?.root.classList.add('hidden');
|
|
28605
28744
|
const nodes = this.cropArea.parentElement?.childNodes ?? [];
|
|
28606
28745
|
for (let i = 0; i < nodes.length; i++) {
|
|
28607
28746
|
const node = nodes[i];
|
|
@@ -28629,8 +28768,11 @@ class VideoEditor {
|
|
|
28629
28768
|
this.stopUpdates();
|
|
28630
28769
|
this.video.pause();
|
|
28631
28770
|
this.playing = false;
|
|
28632
|
-
this.
|
|
28771
|
+
this.controlsComponents.playBtn?.setState(false, true); // skip callback
|
|
28633
28772
|
this.video.src = '';
|
|
28773
|
+
if (this.timebar) {
|
|
28774
|
+
this.timebar.unbind();
|
|
28775
|
+
}
|
|
28634
28776
|
window.removeEventListener('keyup', this.onKeyUp);
|
|
28635
28777
|
document.removeEventListener('mouseup', this._onCropMouseUp);
|
|
28636
28778
|
document.removeEventListener('mousemove', this._onCropMouseMove);
|