vue实现多轨道时间线拖拽显示效果代码
代码语言:html
所属分类:拖放
代码描述:vue实现多轨道时间线拖拽显示效果代码,类似于视频剪辑多个轨道裁剪拼筹,每个轨道都可以自定义,还可以新增轨道。
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/normalize.5.0.css">
<style>
.column {
float: left;
display: inline-block;
padding: 3px 6px 3px 0;
}
body {
font-family: 'Source Code Pro', monospace;
font-size: 11px;
color: #c9c9c9;
background-color: #3d3d3d;
overflow: hidden;
-webkit-user-select: none;
}
button {
border: none;
font-family: 'Source Code Pro', monospace;
text-transform: uppercase;
background-color: #393939;
color: #ddd;
margin: 1px;
}
button.submit {
background-color: #546E7A;
}
button.delete {
background-color: #8c3636;
}
button:focus {
outline: 0;
}
button:hover {
background-color: rgba(20, 20, 20, 0.2);
}
button:active {
background-color: #5d5d5d;
}
#content {
width: 100%;
overflow-y: scroll;
position: absolute;
top: 0;
bottom: 0;
}
.dragscroll {
cursor: -webkit-grab;
}
#switch-header {
height: 35px;
border-right: solid 1px #707070;
top: 0;
left: 0;
position: absolute;
background-color: #545454;
z-index: 10;
}
#switch-header .av-features {
float: left;
display: inline-block;
padding: 3px 6px 3px 0;
padding-top: 18px;
margin-left: 7px;
}
#switch-header .icon-ref {
vertical-align: bottom;
float: left;
display: inline-block;
padding: 3px 6px 3px 0;
width: 13px;
height: 13px;
}
#switches {
height: auto;
margin-top: 35px;
border-right: solid 1px #707070;
left: 0%;
position: absolute;
z-index: 2;
box-shadow: -2px 0px 6px black;
}
#switches .layer-info {
height: 20px;
border-bottom: solid 1px rgba(0, 0, 0, 0.1);
margin: 0;
margin-top: -2px;
padding-bottom: 2px;
font-size: 10px;
padding-left: 6px;
overflow: hidden;
line-height: 20px;
}
#switches .layer-info.group-selected {
background-color: #46575c;
}
#switches .layer-info button {
font-size: 11px;
width: 13px;
height: 13px;
margin: 0;
padding: 0;
vertical-align: text-bottom;
border-radius: 2px;
}
#switches .layer-info .av-features {
float: left;
display: inline-block;
padding: 3px 6px 3px 0;
}
#switches .layer-info .index {
float: left;
display: inline-block;
padding: 3px 6px 3px 0;
width: 16px;
text-align: right;
}
#switches .layer-info .label-color {
float: left;
display: inline-block;
padding: 3px 6px 3px 0;
}
#switches .layer-info .layer-name {
float: left;
display: inline-block;
padding: 3px 6px 3px 0;
padding-left: 4px;
padding: 2px 0;
overflow: hidden;
}
.label-popup {
position: absolute;
background-color: #494949;
width: 10%;
z-index: 50;
}
.label-popup .label-picker {
float: left;
display: inline-block;
padding: 3px 6px 3px 0;
height: 18px;
}
.label-popup button {
font-size: 11px;
width: 13px;
height: 13px;
margin: 0;
padding: 0;
vertical-align: text-bottom;
border-radius: 2px;
}
#timeline-scroll {
padding-left: 4px;
overflow-x: scroll;
height: auto;
top: 0;
position: absolute;
display: inline-block;
}
#timeline-header {
height: 35px;
background-color: #444;
top: 0%;
position: absolute;
z-index: 4;
width: 100%;
}
#timeline {
height: 100%;
}
#playhead-handle {
width: 20px;
height: 20px;
opacity: 0.5;
margin-left: -10px;
margin-top: -35px;
position: relative;
cursor: col-resize;
z-index: 101;
}
#playhead-icon {
width: 20px;
height: 20px;
border-left: solid 1px #4FC3F7;
margin-top: -20px;
position: relative;
z-index: 100;
}
#playhead-icon svg {
-webkit-transform: translate(-5.5px, -31px);
}
#playhead {
border-left: solid 1px #4FC3F7;
background-color: rgba(255, 255, 255, 0.1);
box-sizing: border-box;
height: 5000px;
margin-top: -5000px;
position: relative;
}
#play-region {
height: 15px;
}
#timetick {
height: 35px;
width: 100%;
z-index: 100;
position: relative;
}
#timetick .seconds {
height: 35px;
border-left: solid 1px #737272;
box-sizing: border-box;
padding-top: 10px;
padding-left: 2px;
float: left;
}
.layer {
height: 20px;
overflow: hidden;
margin-bottom: 1px;
}
.frame {
height: 20px;
border-right: dotted 1px rgba(0, 0, 0, 0.6);
display: inline-block;
box-sizing: border-box;
vertical-align: top;
border-radius: 2px;
border-bottom: 1px solid rgba(0, 0, 0, 0.3);
}
.frame-selected {
border-bottom: 4px solid rgba(255, 255, 255, 0.8);
}
.frame-button {
width: 20px;
height: 20px;
margin-left: 1px;
display: inline-block;
vertical-align: top;
border-radius: 20px;
text-align: center;
fill: rgba(255, 255, 255, 0.5);
}
.layer-disabled {
opacity: 0.5;
}
.dur-handle,
.roll-handle {
width: 10px;
height: 10px;
cursor: col-resize;
fill: rgba(255, 255, 255, 0.5);
z-index: 100;
/* opacity: 0; */
}
.dur-handle {
float: right;
cursor: ew-resize;
}
.dur-handle:first-of-type {
margin-top: 10px;
}
.new-frame {
width: 20px;
height: 20px;
fill: rgba(255, 255, 255, 0.5);
z-index: 101;
position: relative;
padding-top: 5px;
box-sizing: border-box;
cursor: copy;
}
#timeline-settings {
width: 80px;
text-align: center;
float: left;
}
#timecode {
background-color: transparent;
border: 0px solid;
font-family: 'Source Code Pro', monospace;
font-size: 14px;
color: #3bc6de;
margin: 2px;
width: 70px;
text-align: center;
}
#timecode:hover {
color: #dfdfdf;
}
#timecode:focus {
background-color: #e9e9e9;
color: #6a6a6a;
}
textarea:focus,
input:focus {
outline: none;
}
#frame-rate {
width: 80px;
font-size: 10px;
text-align: center;
color: #3bc6de;
}
.gridlines {
background-color: transparent;
height: 10000px;
margin-top: -10000px;
background-size: 100% 100%;
}
</style>
</head>
<body translate="no">
<div id="app">
<div id="timeline-header"></div>
<div id="switch-header" v-bind:style="{width : switchWidth + 'px'}">
<!-- <button v-on:click="spaceDown()">drag</button>
<button v-on:click="spaceUp()">release</button> -->
<div class="av-features">
<div class="icon-ref">👁</div>
<div class="icon-ref">⚪</div>
<div class="icon-ref">🔒</div>
</div>
<div id="timeline-settings">
<input id="timecode" v-model.number="frameTime" @focus="$event.target.select()">
{{frameRate}}fps
</div>
<button v-on:click="newLayer()">New Layer</button>
<!--
<button v-on:click="timelineZoomIn()">+</button>
<button v-on:click="timelineZoomOut()">-</button> -->
</div>
<div id="content" v-bind:class="{ dragscroll : spaceDrag }">
<div id="switches" v-bind:style="{width : switchWidth + 'px'}">
<!-- <div class="layer-info" v-for="num in 100">
{{num}}
</div> -->
<!-- <draggable v-model="timeline.layers" :options="{}" @start="drag=true"> -->
<draggable v-model="timeline.layers" :options="{}" @start="drag=true" @end="reorderLayer">
<div class="layer-info" v-for="(layer, layerIndex) in timeline.layers" v-on:click="sel_group(layerIndex)" v-bind:class="{'group-selected' : layerIndex == selectedLayerGroup, 'unlocked' : !layer.locked}" v-bind:id="layerIndex">
<div class="av-features">
<button v-on:click="toggleLayerVisibility(layer, layerIndex)"> {{!layer.visible ? ' ' : '👁'}}</button>
<button v-on:click="toggleLayerSolo(layer, layerIndex)"> {{!layer.solo ? ' ' : '⚪'}}</button>
<button v-on:click="toggleLayerLock(layer, layerIndex)"> {{!layer.locked ? ' ' : '🔒'}}</button>
</div>
<div class="index">{{layerIndex + 1}}</div>
<div class="label-color">
<button v-bind:style="{ 'background-color': labelColors[layer.label]}"></button>
</div>
<div class="layer-name">{{layer.name}}</div>
<!-- <input type="text" v-model="layer.name"> -->
<!-- <div class="layer-name" @dblclick = "layer.edit = true">{{layer.name}}</div>
<input v-show = "layer.edit == true" v-model = "layer.name"
v-on:blur= "layer.edit=false; $emit('update')"
@keyup.enter = "layer.edit=false; $emit('update')"> -->
</div>
</draggable>
<!-- <div class="layer-info">
<div class="label-color" v-for="(label, labelIndex) in labelColors">
<button v-on:click="layer_label(selectedLayerGroup, labelIndex)" v-bind:style="{ 'background-color': labelColors[labelIndex]}"></button>
</div>
</div> -->
<div class="layer-filler" v-bind:style="{'padding-left' : '4px', 'height': (timelineHeight - timeline.layers.length*21) + 'px'}">
- : zoom out <br>
+ : zoom in <br>
→ : forward 1 frame <br>
← : back 1 frame <br>
⇪→ : forward 10 frames <br>
⇪← : back 10 frames <br>
↓ : n.........完整代码请登录后点击上方下载按钮下载查看
网友评论0