原生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