feat(video-ui): 拼接滑块改为删除段灰色斜纹警戒线
This commit is contained in:
1 parent
fc669c91d8
commit
2ae6448ebf
3 files changed
+53
-14
No files matched your search
@@ -675,15 +675,25 @@ body {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.slider-direction-mark {
|
||||
margin-bottom: 6px;
|
||||
font-size: 12px;
|
||||
color: var(--accents-6);
|
||||
line-height: 1.4;
|
||||
.timeline-delete-zone {
|
||||
width: 100%;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
--timeline-track-bg: linear-gradient(90deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.95) 100%);
|
||||
}
|
||||
|
||||
#editTimeline {
|
||||
width: 100%;
|
||||
.timeline-delete-zone::-webkit-slider-runnable-track {
|
||||
height: 8px;
|
||||
border-radius: 999px;
|
||||
background: var(--timeline-track-bg);
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
}
|
||||
|
||||
.timeline-delete-zone::-moz-range-track {
|
||||
height: 8px;
|
||||
border-radius: 999px;
|
||||
background: var(--timeline-track-bg);
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
}
|
||||
|
||||
.edit-meta-grid {
|
||||
|
||||
@@ -194,6 +194,31 @@
|
||||
return Math.max(0, Math.min(safe, maxMs));
|
||||
}
|
||||
|
||||
function updateDeleteZoneTrack(inputEl) {
|
||||
if (!inputEl) return;
|
||||
const maxRaw = Number(inputEl.max || EDIT_TIMELINE_MAX);
|
||||
const max = Number.isFinite(maxRaw) && maxRaw > 0 ? maxRaw : EDIT_TIMELINE_MAX;
|
||||
const valueRaw = Number(inputEl.value || 0);
|
||||
const value = Math.max(0, Math.min(max, Number.isFinite(valueRaw) ? valueRaw : 0));
|
||||
const pct = (value / max) * 100;
|
||||
const side = String(inputEl.dataset.deleteSide || 'right');
|
||||
const warnPattern = 'repeating-linear-gradient(135deg, rgba(148,163,184,0.38) 0 7px, rgba(100,116,139,0.58) 7px 14px)';
|
||||
const keep = 'rgba(255,255,255,0.95)';
|
||||
let bg = '';
|
||||
if (side === 'left') {
|
||||
bg = `linear-gradient(90deg, transparent 0%, transparent ${pct}%, ${keep} ${pct}%, ${keep} 100%), ${warnPattern}`;
|
||||
} else {
|
||||
bg = `linear-gradient(90deg, ${keep} 0%, ${keep} ${pct}%, transparent ${pct}%, transparent 100%), ${warnPattern}`;
|
||||
}
|
||||
inputEl.style.setProperty('--timeline-track-bg', bg);
|
||||
}
|
||||
|
||||
function refreshAllDeleteZoneTracks() {
|
||||
updateDeleteZoneTrack(editTimeline);
|
||||
updateDeleteZoneTrack(mergeTimelineA);
|
||||
updateDeleteZoneTrack(mergeTimelineB);
|
||||
}
|
||||
|
||||
function setSpliceButtonState(state) {
|
||||
if (!spliceBtn) return;
|
||||
const iconSplice = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H6a2 2 0 0 0-2 2v5"/><path d="M13 20h5a2 2 0 0 0 2-2v-5"/><path d="M20 6l-8 8"/><path d="M4 18l8-8"/></svg>';
|
||||
@@ -1446,6 +1471,7 @@
|
||||
const current = Number(editVideo.currentTime || 0);
|
||||
const ratio = Math.max(0, Math.min(1, current / duration));
|
||||
editTimeline.value = String(Math.round(ratio * EDIT_TIMELINE_MAX));
|
||||
updateDeleteZoneTrack(editTimeline);
|
||||
lockedTimestampMs = clampEditTimestampMs(Math.round(current * 1000));
|
||||
if (editTimeText) editTimeText.textContent = formatMs(lockedTimestampMs);
|
||||
}
|
||||
@@ -2494,6 +2520,7 @@
|
||||
const ratio = Number(editTimeline.value || 0) / EDIT_TIMELINE_MAX;
|
||||
const nextTime = Math.max(0, Math.min(duration, duration * ratio));
|
||||
editVideo.currentTime = nextTime;
|
||||
updateDeleteZoneTrack(editTimeline);
|
||||
lockedTimestampMs = clampEditTimestampMs(Math.round(nextTime * 1000));
|
||||
if (editTimeText) editTimeText.textContent = formatMs(lockedTimestampMs);
|
||||
lockFrameByCurrentTime();
|
||||
@@ -2533,6 +2560,7 @@
|
||||
mergeCutMsA = 0;
|
||||
if (mergeTimeTextA) mergeTimeTextA.textContent = formatMs(0);
|
||||
if (mergeTimelineA) mergeTimelineA.value = '0';
|
||||
updateDeleteZoneTrack(mergeTimelineA);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2545,6 +2573,7 @@
|
||||
mergeCutMsB = 0;
|
||||
if (mergeTimeTextB) mergeTimeTextB.textContent = formatMs(0);
|
||||
if (mergeTimelineB) mergeTimelineB.value = '0';
|
||||
updateDeleteZoneTrack(mergeTimelineB);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2556,6 +2585,7 @@
|
||||
const ratio = Number(mergeTimelineA.value || 0) / EDIT_TIMELINE_MAX;
|
||||
const nextTime = Math.max(0, Math.min(duration, duration * ratio));
|
||||
mergeVideoPreviewA.currentTime = nextTime;
|
||||
updateDeleteZoneTrack(mergeTimelineA);
|
||||
mergeCutMsA = Math.round(nextTime * 1000);
|
||||
if (mergeTimeTextA) mergeTimeTextA.textContent = formatMs(mergeCutMsA);
|
||||
});
|
||||
@@ -2569,6 +2599,7 @@
|
||||
const ratio = Number(mergeTimelineB.value || 0) / EDIT_TIMELINE_MAX;
|
||||
const nextTime = Math.max(0, Math.min(duration, duration * ratio));
|
||||
mergeVideoPreviewB.currentTime = nextTime;
|
||||
updateDeleteZoneTrack(mergeTimelineB);
|
||||
mergeCutMsB = Math.round(nextTime * 1000);
|
||||
if (mergeTimeTextB) mergeTimeTextB.textContent = formatMs(mergeCutMsB);
|
||||
});
|
||||
@@ -2960,6 +2991,7 @@
|
||||
updateMergeLabels();
|
||||
updateHistoryCount();
|
||||
updateManualActionsVisibility();
|
||||
refreshAllDeleteZoneTracks();
|
||||
setSpliceButtonState('idle');
|
||||
if (imageUrlInput && imageUrlInput.value.trim()) {
|
||||
const resolved = resolveReferenceByText(imageUrlInput.value.trim());
|
||||
|
||||
@@ -154,8 +154,7 @@
|
||||
<video id="editVideo" controls preload="metadata"></video>
|
||||
</div>
|
||||
<div class="edit-slider-wrap">
|
||||
<div class="slider-direction-mark">从这里开始拼接,右侧将由新视频接续</div>
|
||||
<input id="editTimeline" type="range" min="0" max="100000" step="1" value="0">
|
||||
<input id="editTimeline" class="timeline-delete-zone" data-delete-side="right" type="range" min="0" max="100000" step="1" value="0">
|
||||
<div class="progress-meta">
|
||||
<span id="editTimeText">00:00.000</span>
|
||||
<span id="editDurationText">总时长 -</span>
|
||||
@@ -198,8 +197,7 @@
|
||||
<video id="mergeVideoPreviewA" controls preload="metadata"></video>
|
||||
</div>
|
||||
<div class="edit-slider-wrap">
|
||||
<div class="slider-direction-mark">方向:保留左侧(起点 -> 当前帧)</div>
|
||||
<input id="mergeTimelineA" type="range" min="0" max="100000" step="1" value="0">
|
||||
<input id="mergeTimelineA" class="timeline-delete-zone" data-delete-side="right" type="range" min="0" max="100000" step="1" value="0">
|
||||
<div class="progress-meta">
|
||||
<span id="mergeTimeTextA">00:00.000</span>
|
||||
<span id="mergeDurationA">总时长 -</span>
|
||||
@@ -212,8 +210,7 @@
|
||||
<video id="mergeVideoPreviewB" controls preload="metadata"></video>
|
||||
</div>
|
||||
<div class="edit-slider-wrap">
|
||||
<div class="slider-direction-mark">方向:保留右侧(当前帧 -> 结尾)</div>
|
||||
<input id="mergeTimelineB" type="range" min="0" max="100000" step="1" value="0">
|
||||
<input id="mergeTimelineB" class="timeline-delete-zone" data-delete-side="left" type="range" min="0" max="100000" step="1" value="0">
|
||||
<div class="progress-meta">
|
||||
<span id="mergeTimeTextB">00:00.000</span>
|
||||
<span id="mergeDurationB">总时长 -</span>
|
||||
@@ -321,7 +318,7 @@
|
||||
<script src="/static/common/js/pwa.js?v=0.1.1"></script>
|
||||
<script src="/static/vendor/ffmpeg/ffmpeg.js?v=0.1.0"></script>
|
||||
<script src="/static/vendor/ffmpeg/ffmpeg-util.js?v=0.1.0"></script>
|
||||
<script src="/static/public/js/video.js?v=0.5.37"></script>
|
||||
<script src="/static/public/js/video.js?v=0.5.38"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in new issue
Block a user