原生js+css布局实现网页版浏览器端离线视频剪辑神器剪影效果代码

代码语言:html

所属分类:多媒体

代码描述:原生js+css布局实现网页版浏览器端离线视频剪辑神器剪影效果代码,可导入切割音视频、图片、文字等素材,多轨道、可导出mp4、webm视频格式,全程离线浏览器运行。

代码标签: 原生 js css 布局 网页版 视频 离线 浏览器 剪辑 神器 剪影

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Browser Video Editor (WebCodecs)</title>
<style>
:root { --bg: #121212; --surf: #1e1e1e; --surf-2: #2c2c2c; --text: #eee; --text-mute: #aaa; --prim: #007bff; --acc: #00d26a; --err: #f44336; --font: system-ui, -apple-system, sans-serif; --g-h: 40px; }
html[data-theme="light"] { --bg: #f8f9fa; --surf: #ffffff; --surf-2: #e9ecef; --text: #212529; --text-mute: #6c757d; }
* { box-sizing: border-box; outline-color: var(--prim); }
body { margin: 0; padding: 0; font-family: var(--font); background: var(--bg); color: var(--text); height: 100vh; display: flex; flex-direction: column; overflow: hidden; transition: background 0.3s; }
button { cursor: pointer; background: var(--surf-2); color: var(--text); border: 1px solid var(--surf); padding: 6px 12px; border-radius: 4px; font-size: 0.9rem; }
button:hover { background: var(--surf); border-color: var(--text-mute); }
button:disabled { opacity: 0.5; cursor: not-allowed; }
button.prim { background: var(--prim); color: white; border: none; }
button.prim:hover { filter: brightness(1.1); }
input, select { background: var(--surf-2); border: 1px solid var(--surf); color: var(--text); padding: 6px; border-radius: 4px; }
input[type=range] { cursor: pointer; }

/* Layout */
#app { display: grid; grid-template-rows: auto 1fr auto; height: 100%; }
header { padding: 0 1rem; height: var(--g-h); display: flex; align-items: center; justify-content: space-between; background: var(--surf); border-bottom: 1px solid var(--surf-2); }
.toolbar { display: flex; gap: 8px; align-items: center; }
#main-area { display: grid; grid-template-columns: 300px 1fr 300px; overflow: hidden; }
#assets-panel, #props-panel { background: var(--surf); padding: 1rem; border-right: 1px solid var(--surf-2); border-left: 1px solid var(--surf-2); overflow-y: auto; display: flex; flex-direction: column; gap: 1rem; }
#preview-area { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 1rem; background: #000; position: relative; }
#timeline-area { height: 300px; background: var(--surf); border-top: 1px solid var(--surf-2); display: flex; flex-direction: column; }

/* Preview */
#preview-canvas { max-width: 100%; max-height: calc(100% - 40px); box-shadow: 0 0 20px rgba(0,0,0,0.5); background: #000; }
#p-controls { display: flex; gap: 10px; margin-top: 10px; align-items: center; width: 100%; justify-content: center; color: white; }
#time-display { font-family: monospace; font-variant-numeric: tabular-nums; min-width: 120px; text-align: center; }

/* Assets */
#drop-zone { border: 2px dashed var(--text-mute); padding: 20px; text-align: center; border-radius: 8px; cursor: pointer; transition: 0.2s; }
#drop-zone.dragover { border-color: var(--prim); background: rgba(0,123,255,0.1); }
.asset-item { display: flex; align-items: center; gap: 8px; padding: 6px; background: var(--surf-2); border-radius: 4px; margin-bottom: 4px; cursor: grab; font-size: 0.85rem; }
.asset-item:active { cursor: grabbing; }
.asset-icon { width: 24px; height: 24px; background: #555; border-radius: 2px; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: bold; color: white;}
.asset-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; }

/* Timeline */
.tl-toolbar { padding: 4px 1rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--surf-2); font-size: 0.8rem; }
#tl-container { flex: 1; position: relative; overflow-x: auto; overflow-y: hidden; user-select: none; }
#tl-canvas { display: block; cursor: pointer; }
/* Hardware accell for smooth playhead */
#playhead-line { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--acc); pointer-events: none; z-index: 10; transform: translateX(0); will-change: transform;}

/* Properties */
.prop-group { display: flex; flex-direction: column; gap: 6px; font-size: 0.9rem; border-bottom: 1px solid var(--surf-2); padding-bottom: 10px; }
.prop-row { display: flex; justify-content: space-between; align-items: center; }
.prop-row label { flex: 1; color: var(--text-mute); }
.prop-row > * { flex: 1.5; }
.hidden { display: none !important; }

/* Modal/Overlay */
#modal-overlay { position: fixed; top:0;left:0;right:0;bottom:0; background: rgba(0,0,0,0.7); z-index: 100; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(2px); }
.modal { background: var(--surf); padding: 20px; border-radius: 8px; width: 400px; border: 1px solid var(--surf-2); box-shadow: 0 10px 30px rgba(0,0,0,0.5); }
.progress-bar { height: 8px; background: var(--surf-2); border-radius: 4px; overflow: hidden; margin: 10px 0; }
.progress-fill { height: 100%; background: var(--acc); width: 0%; transition: width 0.2s; }
#toast-area { position: fixed; bottom: 20px; right: 20px; display: flex; flex-direction: column; gap: 10px; z-index: 200; }
.toast { padding: 10px 15px; border-radius: 4px; background: var(--surf); border-left: 4px solid var(--prim); box-shadow: 0 2px 10px rgba(0,0,0,0.3); animation: slideIn 0.3s ease; color: var(--text); max-width: 300px;}
.toast.error { border-color: var(--err); }
@keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }

/* Responsive */
@media (max-width: 768px) {
    #main-area { grid-template-columns: 1fr; grid-template-rows: auto minmax(200px, 1fr) auto; }
    #assets-panel, #props-panel { max-height: 200px; border: none; border-bottom: 1px solid var(--surf-2); }
    #props-panel { order: 3; } #preview-area { order: 1; } #assets-panel { order: 2; }
}
</style>
</head>
<body>
<div id="app">
    <header role="banner">
        <div class="toolbar">
            <strong>JSVideoEdit</strong>
            <button id="btn-theme" aria-label="Toggle Theme" title="Toggle Dark/Light Mode">🌗</button>
            <button id="btn-demo" title="Load sample assets">Demo Mode</button>
        </div>
        <div class="toolbar">
            <button id="btn-save" title="Save Project JSON">Save</button>
            <button onclick="document.getElementById('file-load').click()" title="Load Project JSON">Load</button>
            <input type="file" id="file-load" accept=".json" hidden>
            <button id="btn-export" class="prim">Export Video</button>
        </div>
    </header>

    <div id="main-area">
        <section id="assets-panel" aria-label="Assets">
            <h3>Assets</h3>
            <div id="drop-zone" tabindex="0" role="button" aria-label="Upload files">
                Drag & Drop Files<br><small>(MP4, WebM, MP3, PNG, JPG)</small>
            </div>
            <input type="file" id="file-import" multiple accept="video/*,audio/*,image/*" hidden>
            <div id="asset-list"></div>
            <div style="margin-top:auto; padding-top:10px; border-top:1px solid var(--surf-2)">
                <h3>Overlays</h3>
                <button id="btn-add-text" style="width:100%">+ Add Text</button>
            </div>
        </section>

        <section id="preview-area" aria-label="Preview">
            <canvas id="preview-canvas" width="1280" height="720"></canvas>
            <div id="p-controls">
                <button id="btn-start">⏮</button>
                <button id="btn-play" class="prim" aria-label="Play/Pause (Space)">▶</button>
                <div id="time-display">00:00 / 00:00</div>
            </div>
        </section>

        <section id="props-panel" aria-label="Properties">
            <h3>Properties</h3>
            <div id="no-selection" class="text-mute">Select a clip on timeline.</div>
            <div id=".........完整代码请登录后点击上方下载按钮下载查看

网友评论0