You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
720 lines
38 KiB
720 lines
38 KiB
<template>
|
|
<v-container>
|
|
<v-row class="fill-height">
|
|
<v-col cols="24" md="1">
|
|
<v-card width="100%" dark class="fill-height">
|
|
<v-card-text>
|
|
<v-row>
|
|
<v-col>
|
|
<v-icon @click="addItemStart('text')">mdi-format-color-text</v-icon>
|
|
</v-col>
|
|
<v-col>
|
|
<v-icon @mousedown="addItemStart('rect')" @mouseup="clearStart()">
|
|
mdi-rectangle-outline
|
|
</v-icon>
|
|
</v-col>
|
|
<v-col>
|
|
<v-icon @mousedown="addItemStart('image')" @mouseup="clearStart()">mdi-image</v-icon>
|
|
</v-col>
|
|
</v-row>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
<v-col cols="24" md="9">
|
|
<v-card width="100%" min-height="600" dark class="fill-height">
|
|
<v-card-text color="white">
|
|
<div ref="vid" @click="handleAction" style="width: 100%;background: #fff;position: relative">
|
|
<div v-for="(track, index) in mainTracks" :key="index">
|
|
<div v-for="(keyframe, index) in track.keyframes" :key="index">
|
|
<div @click="selectTrack(track)"
|
|
v-if="keyframe.start <= currentTime && keyframe.end >=currentTime && track.type === 'text'"
|
|
@mouseenter="colorBorder(track)"
|
|
@mouseleave="colorBorderClear(track)" @mousedown="itemMoveStart"
|
|
@mouseup="itemMoveEnd" :ref="'item'+track.id" @dblclick="editText(track)"
|
|
:style="`padding:4px;color:${track.color};position:absolute;opacity:${vidTracks[track.id].opacity};top:${vidTracks[track.id].y-4}px;left:${vidTracks[track.id].x-4}px;font-size:${track.size};font-family:${track.font};border: 1px solid ${selectedTrack?(selectedTrack.id === track.id?'#ff0000':'transparent'):'transparent'}`"
|
|
>
|
|
<span :style="`line-height:${vidTracks[track.id].lineHeight}!important;letter-spacing:${vidTracks[track.id].letterSpacing}!important;`" v-html="track.text.replace(/\n/g, '<br>')"></span>
|
|
<div></div>
|
|
</div>
|
|
<div @click="selectTrack(track)" @mouseenter="colorBorder(track)"
|
|
v-if="keyframe.start <= currentTime && keyframe.end >=currentTime && track.type === 'image'"
|
|
@mouseleave="colorBorderClear(track)" @mousedown="itemMoveStart"
|
|
@mouseup="itemMoveEnd" :ref="'item'+track.id" @dblclick="editText(track)"
|
|
:style="`padding:4px;color:${track.color};position:absolute;opacity:${vidTracks[track.id].opacity};top:${vidTracks[track.id].y-4}px;left:${vidTracks[track.id].x-4}px;font-size:${track.size};font-family:${track.font};border: 1px solid ${selectedTrack?(selectedTrack.id === track.id?'#ff0000':'transparent'):'transparent'}`"
|
|
>
|
|
<img :src="track.image_data"
|
|
:width="vidTracks[track.id].width>0?vidTracks[track.id].width+'px':''"
|
|
:height="vidTracks[track.id].height>0?vidTracks[track.id].height+'px':''">
|
|
<div></div>
|
|
</div>
|
|
<div @click="selectTrack(track)" @mouseenter="colorBorder(track)"
|
|
v-if="keyframe.start <= currentTime && keyframe.end >=currentTime && track.type === 'rect'"
|
|
@mouseleave="colorBorderClear(track)" @mousedown="itemMoveStart"
|
|
@mouseup="itemMoveEnd" :ref="'item'+track.id" @dblclick="editText(track)"
|
|
:style="`padding:4px;color:${track.color};position:absolute;opacity:${vidTracks[track.id].opacity};top:${vidTracks[track.id].y-4}px;left:${vidTracks[track.id].x-4}px;font-size:${track.size};font-family:${track.font};border: 1px solid ${selectedTrack?(selectedTrack.id === track.id?'#ff0000':'transparent'):'transparent'}`"
|
|
>
|
|
<div :style="`width:${vidTracks[track.id].width}px;height:${vidTracks[track.id].height}px;background-color:${track.color}`"></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
<v-col cols="24" md="2">
|
|
<v-card width="100%" dark class="fill-height">
|
|
<v-card-text>
|
|
<v-row>
|
|
<v-col v-if="selectedTrack">
|
|
<v-text-field v-if="selectedTrack.type === 'text'" label="Font Size"
|
|
placeholder="Font Size"
|
|
v-model="mainTracks[currentKeyTrack.track].size"
|
|
@keyup="mainTracks.__ob__.dep.notify()"></v-text-field>
|
|
<v-textarea v-if="selectedTrack.type === 'text'" label="Text"
|
|
@keyup="mainTracks.__ob__.dep.notify()" placeholder="Text"
|
|
v-model="mainTracks[currentKeyTrack.track].text"></v-textarea>
|
|
<v-text-field v-if="selectedTrack.type !== 'text'" label="Name"
|
|
@keyup="mainTracks.__ob__.dep.notify()" placeholder="Name"
|
|
v-model="mainTracks[currentKeyTrack.track].text"></v-text-field>
|
|
|
|
<v-menu
|
|
ref="menu"
|
|
v-model="colorMenu"
|
|
:close-on-content-click="false"
|
|
|
|
transition="scale-transition"
|
|
offset-y
|
|
min-width="290px"
|
|
v-if="selectedTrack.type !== 'image'"
|
|
>
|
|
<template v-slot:activator="{ on }">
|
|
<v-text-field
|
|
v-model="mainTracks[currentKeyTrack.track].color"
|
|
label="Color"
|
|
readonly
|
|
v-on="on"
|
|
></v-text-field>
|
|
</template>
|
|
<v-color-picker v-model="mainTracks[currentKeyTrack.track].color" no-title
|
|
scrollable show-swatches>
|
|
<v-spacer></v-spacer>
|
|
</v-color-picker>
|
|
</v-menu>
|
|
<v-text-field v-if="selectedTrack.type !== 'text'" label="Width"
|
|
@keyup="mainTracks.__ob__.dep.notify()" placeholder="Width"
|
|
v-model="mainTracks[currentKeyTrack.track].keyframes[currentKeyTrack.keyframe].width"></v-text-field>
|
|
|
|
<v-text-field v-if="selectedTrack.type === 'text'" label="Line Height"
|
|
@keyup="mainTracks.__ob__.dep.notify()" placeholder="Line Height"
|
|
v-model="mainTracks[currentKeyTrack.track].keyframes[currentKeyTrack.keyframe].lineHeight"></v-text-field>
|
|
<v-text-field v-if="selectedTrack.type === 'text'" label="Letter Spacing"
|
|
@keyup="mainTracks.__ob__.dep.notify()" placeholder="Letter Spacing"
|
|
v-model="mainTracks[currentKeyTrack.track].keyframes[currentKeyTrack.keyframe].letterSpacing"></v-text-field>
|
|
<v-text-field v-if="selectedTrack.type !== 'text'" label="Height"
|
|
@keyup="mainTracks.__ob__.dep.notify()" placeholder="Height"
|
|
v-model="mainTracks[currentKeyTrack.track].keyframes[currentKeyTrack.keyframe].height"></v-text-field>
|
|
<v-text-field v-if="selectedTrack.type === 'text'" label="Font"
|
|
@keyup="mainTracks.__ob__.dep.notify()" placeholder="Text"
|
|
v-model="mainTracks[currentKeyTrack.track].font"></v-text-field>
|
|
<v-text-field label="X" @keyup="mainTracks.__ob__.dep.notify()" placeholder="X"
|
|
v-model="mainTracks[currentKeyTrack.track].keyframes[currentKeyTrack.keyframe].x"></v-text-field>
|
|
<v-text-field label="Y" @keyup="mainTracks.__ob__.dep.notify()" placeholder="Y"
|
|
v-model="mainTracks[currentKeyTrack.track].keyframes[currentKeyTrack.keyframe].y"></v-text-field>
|
|
<v-text-field label="Opacity" @keyup="mainTracks.__ob__.dep.notify()"
|
|
placeholder="Opacity"
|
|
v-model="mainTracks[currentKeyTrack.track].keyframes[currentKeyTrack.keyframe].opacity"></v-text-field>
|
|
<v-btn small text @click="newKeyFrame">new keyframe</v-btn>
|
|
<v-btn small text @click="newMask">new mask</v-btn>
|
|
|
|
</v-col>
|
|
</v-row>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
<v-col cols="12" md="12">
|
|
<v-card width="100%" min-height="100" dark>
|
|
<v-card-text ref="videoPanel">
|
|
<div id="video_tracks" ref="vidPanelTracks" @mouseleave="allmoveend">
|
|
<div :ref="'vidtrack'+track.id" v-for="(track, index) in mainTracks" :key="index"
|
|
style="position: relative;padding: 3px">
|
|
<div @click="selectTrack(track)" @mousedown="startPositionTrack" @mouseup="allmoveend"
|
|
|
|
:style="`border:1px solid ${selectedTrack?(selectedTrack.id===track.id?'#f00':'#ccc'):'#ccc'};position: absolute;height:23px;top:${(index*23)}px;left:${((track.start/timeLength)*100)}%;width:${((track.end-track.start)/timeLength)*100}%`">
|
|
<div style="background: #ededed;right: 0px;top:0px;position: absolute;height: 22px;width: 5px;"
|
|
@mousedown="startChangeSizeTrack" @mouseup="allmoveend()"></div>
|
|
<div>{{ track.text }} ({{ (track.end - track.start).toFixed(2) }} sec)</div>
|
|
<div v-for="(keyframe , index) in track.keyframes" :key="index"
|
|
:style="`position:absolute;height:8px;width:8px;background:red;top:6px;margin-left:-4px;left:${(((keyframe.start - track.start)/track.end)*100)}%`"></div>
|
|
</div>
|
|
</div>
|
|
<div style="position: absolute;width: 5px; background: #aa00ff;height: 120px;top:3px;"
|
|
ref="currentTime" @mousedown="moveStartTime=true" @mouseup="moveStartTime=false">
|
|
</div>
|
|
</div>
|
|
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-text-field label="Total Secs" v-model="timeLength"></v-text-field>
|
|
<v-text-field label="Current" v-model="currentTime"></v-text-field>
|
|
<v-btn @click="preview">Start</v-btn>
|
|
<v-btn @click="previewStop">Stop</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
<div ref="vm">
|
|
<v-icon color="primary" :style="'position: absolute;left:' + moveX + 'px;top:'+ moveY + 'px'"
|
|
v-if="create==='text'">mdi-format-color-text
|
|
</v-icon>
|
|
<v-icon color="primary" :style="'position: absolute;left:' + moveX + 'px;top:'+ moveY + 'px'"
|
|
v-if="create==='image'">mdi-image
|
|
</v-icon>
|
|
<v-icon color="primary" :style="'position: absolute;left:' + moveX + 'px;top:'+ moveY + 'px'"
|
|
v-if="create==='rect'">mdi-rectangle-outline
|
|
</v-icon>
|
|
<div :style="`position: absolute;border:1px solid #ff0000;width:${width}px;height:${height}px;left:${moveX}px;top:${moveY}px`"
|
|
ref="rectcreate" v-if="create==='rect' && action==='paint'"></div>
|
|
<div :style="`position: absolute;border:1px solid #ff0000;width:${width}px;height:${height}px;left:${moveX}px;top:${moveY}px`"
|
|
ref="mask" v-if="oncreateMask && action==='paint'"></div>
|
|
</div>
|
|
</v-container>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: "Animator",
|
|
data: () => ({
|
|
currentKeyTrack: {
|
|
keyframe: 0,
|
|
track: 0
|
|
},
|
|
vidTracks: {},
|
|
action: null,
|
|
item: null,
|
|
create: null,
|
|
index: 1,
|
|
colorPick: '',
|
|
timeLength: 60,
|
|
moveStartTime: false,
|
|
currentTime: 0,
|
|
oncreateMask: false,
|
|
pinterval: 0,
|
|
width: 0,
|
|
colorMenu: false,
|
|
heigth: 0,
|
|
clickOffset: {
|
|
x: 0,
|
|
y: 0
|
|
},
|
|
moveX: 0,
|
|
mainTracks: localStorage.getItem('animator')?JSON.parse(localStorage.getItem('animator')):[],
|
|
moveItem: false,
|
|
moveY: 0,
|
|
selectedTrack: null,
|
|
sizeChangeStart: false,
|
|
positionChangeStart: false,
|
|
editingItem: null
|
|
}),
|
|
mounted() {
|
|
this.$refs.vid.style.height = (this.$refs.vid.offsetWidth / (16 / 9)) + "px"
|
|
window.onmousemove = (event) => {
|
|
this.itemMove(event)
|
|
var bodyRect = document.body.getBoundingClientRect()
|
|
if (this.moveItem && this.currentKeyTrack) {
|
|
var elemRect = this.$refs.vid.getBoundingClientRect(),
|
|
offsetY = elemRect.top - bodyRect.top,
|
|
offsetX = elemRect.left - bodyRect.left
|
|
this.mainTracks[this.currentKeyTrack.track].y = (event.clientY - offsetY) - this.clickOffset.y
|
|
this.mainTracks[this.currentKeyTrack.track].x = (event.clientX - offsetX) - this.clickOffset.x
|
|
this.mainTracks[this.currentKeyTrack.track].keyframes[this.currentKeyTrack.keyframe].x = (event.clientX - offsetX) - this.clickOffset.x
|
|
this.mainTracks[this.currentKeyTrack.track].keyframes[this.currentKeyTrack.keyframe].y = (event.clientY - offsetY) - this.clickOffset.y
|
|
this.mainTracks.__ob__.dep.notify()
|
|
}
|
|
if (this.moveStartTime) {
|
|
console.log('')
|
|
|
|
var vidtrack = this.$refs.vidPanelTracks.getBoundingClientRect()
|
|
var offsetXVid = vidtrack.left - bodyRect.left
|
|
var pos = (event.clientX - offsetXVid + 12)
|
|
if (pos >= 15 && pos <= vidtrack.width + 15) {
|
|
this.$refs.currentTime.style.left = pos + "px"
|
|
console.log(offsetXVid, pos, vidtrack.width)
|
|
this.currentTime = (this.timeLength / vidtrack.width) * (pos - 15)
|
|
}
|
|
}
|
|
if (this.selectedTrack && this.positionChangeStart) {
|
|
var bodyRect3 = document.body.getBoundingClientRect(),
|
|
elemRect3 = this.$refs['vidtrack' + this.selectedTrack.id][0].getBoundingClientRect(),
|
|
offsetX3 = elemRect3.left - bodyRect3.left
|
|
var length2 = this.timeLength / 100
|
|
|
|
var totalLength2 = (((((event.clientX - this.clickOffset.x) - offsetX3)) / elemRect3.width) * length2) * 100
|
|
this.mainTracks.forEach(track => {
|
|
var tn = track.end - track.start
|
|
var originalstart = track.start
|
|
if (track.id === this.selectedTrack.id) {
|
|
track.start = totalLength2
|
|
track.end = track.start + tn
|
|
track.keyframes.forEach(keyframe => {
|
|
var tnx = track.end - track.start
|
|
keyframe.start = track.start + (originalstart - track.start)
|
|
keyframe.end = track.start + tnx
|
|
})
|
|
}
|
|
})
|
|
}
|
|
if (this.selectedTrack && this.sizeChangeStart) {
|
|
var bodyRect2 = document.body.getBoundingClientRect(),
|
|
elemRect2 = this.$refs['vidtrack' + this.selectedTrack.id][0].getBoundingClientRect(),
|
|
offsetX2 = elemRect2.left - bodyRect2.left
|
|
var length = this.timeLength / 100
|
|
|
|
var totalLength = ((((event.clientX - offsetX2) + 2) / elemRect2.width) * length) * 100
|
|
this.mainTracks.forEach(track => {
|
|
if (track.id === this.selectedTrack.id) track.end = totalLength
|
|
})
|
|
}
|
|
}
|
|
window.onkeyup = (event) => {
|
|
console.log(event.key)
|
|
if (event.target === document.body) {
|
|
if (event.key === 'ArrowDown' && this.selectedTrack) this.mainTracks[this.currentKeyTrack.track].keyframes[this.currentKeyTrack.keyframe].y++
|
|
if (event.key === 'ArrowUp' && this.selectedTrack) this.mainTracks[this.currentKeyTrack.track].keyframes[this.currentKeyTrack.keyframe].y--
|
|
if (event.key === 'ArrowLeft' && this.selectedTrack) this.mainTracks[this.currentKeyTrack.track].keyframes[this.currentKeyTrack.keyframe].x--
|
|
if (event.key === 'ArrowRight' && this.selectedTrack) this.mainTracks[this.currentKeyTrack.track].keyframes[this.currentKeyTrack.keyframe].x++
|
|
if (event.key === "Escape") {
|
|
this.selectedTrack = null
|
|
this.action = null
|
|
this.create = null
|
|
this.moveItem = false
|
|
this.sizeChangeStart = false
|
|
this.positionChangeStart = false
|
|
this.moveStartTime = false
|
|
this.previewStop()
|
|
}
|
|
}
|
|
}
|
|
},
|
|
watch: {
|
|
|
|
editingItem(newval, oldval) {
|
|
console.log(newval)
|
|
console.log('old', oldval)
|
|
// if (oldval !== null) {
|
|
// this.vidTracks.forEach(item => {
|
|
// if (item.id === newval.id) item = newval
|
|
// })
|
|
// }
|
|
},
|
|
mainTracks (newval) {
|
|
console.log('maintrack change')
|
|
localStorage.setItem('animator', JSON.stringify(newval))
|
|
},
|
|
currentTime(newval) {
|
|
if (newval) {
|
|
var videoPanel = this.$refs.vidPanelTracks.getBoundingClientRect()
|
|
var left = videoPanel.width / this.timeLength
|
|
if (!this.moveStartTime) this.$refs.currentTime.style.left = ((left * newval) + 15) + "px"
|
|
this.vidTracks = []
|
|
this.mainTracks.forEach((track, tindex) => {
|
|
|
|
if (track.start <= newval && newval <= track.end) {
|
|
var ttrack = track
|
|
var keyframe = null
|
|
var nextframe = null
|
|
track.keyframes.forEach((kvarey, index) => {
|
|
if (kvarey.start <= newval && newval <= kvarey.end) {
|
|
keyframe = kvarey
|
|
|
|
if (this.selectedTrack) {
|
|
if (this.selectedTrack.id === track.id) {
|
|
this.currentKeyTrack.keyframe = index
|
|
this.currentKeyTrack.track = tindex
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
ttrack.x = keyframe.x
|
|
ttrack.y = keyframe.y
|
|
ttrack.width = keyframe.width
|
|
ttrack.height = keyframe.height
|
|
ttrack.opacity = keyframe.opacity
|
|
|
|
var starter = null
|
|
track.keyframes.forEach((kvarey, index) => {
|
|
if (keyframe.end <= kvarey.start) {
|
|
if (kvarey.start < starter || starter === null) nextframe = index
|
|
if (starter === null) starter = kvarey.start
|
|
}
|
|
})
|
|
if (nextframe !== null) {
|
|
console.log(nextframe)
|
|
if (track.type === 'text') {
|
|
ttrack.letterSpacing = keyframe.letterSpacing
|
|
ttrack.lineHeight = keyframe.lineHeight
|
|
if (track.keyframes[nextframe].lineHeight !== ttrack.lineHeight) {
|
|
var difflineHeight = (track.keyframes[nextframe].lineHeight - ttrack.lineHeight)
|
|
difflineHeight = difflineHeight / (keyframe.end - keyframe.start)
|
|
difflineHeight = (newval - keyframe.start) * difflineHeight
|
|
ttrack.lineHeight = parseFloat(ttrack.lineHeight) + parseFloat(difflineHeight)
|
|
}
|
|
if (track.keyframes[nextframe].letterSpacing !== ttrack.letterSpacing) {
|
|
var diffletterSpacing = (track.keyframes[nextframe].letterSpacing - ttrack.letterSpacing)
|
|
diffletterSpacing = diffletterSpacing / (keyframe.end - keyframe.start)
|
|
diffletterSpacing = (newval - keyframe.start) * diffletterSpacing
|
|
ttrack.lineHeight = parseFloat(ttrack.letterSpacing) + parseFloat(diffletterSpacing)
|
|
}
|
|
}
|
|
if (track.keyframes[nextframe].x !== ttrack.x) {
|
|
var diffx = (track.keyframes[nextframe].x - ttrack.x)
|
|
diffx = diffx / (keyframe.end - keyframe.start)
|
|
diffx = (newval - keyframe.start) * diffx
|
|
ttrack.x = parseFloat(ttrack.x) + parseFloat(diffx)
|
|
}
|
|
if (track.keyframes[nextframe].width !== ttrack.width) {
|
|
var diffwidth = (track.keyframes[nextframe].width - ttrack.width)
|
|
diffwidth = diffwidth / (keyframe.end - keyframe.start)
|
|
diffwidth = (newval - keyframe.start) * diffwidth
|
|
ttrack.width = parseFloat(ttrack.width) + parseFloat(diffwidth)
|
|
}
|
|
if (track.keyframes[nextframe].height !== ttrack.height) {
|
|
|
|
console.log('heig', track.keyframes[nextframe].height, ttrack.height)
|
|
var diffheight = (track.keyframes[nextframe].height - ttrack.height)
|
|
diffheight = diffheight / (keyframe.end - keyframe.start)
|
|
diffheight = (newval - keyframe.start) * diffheight
|
|
ttrack.height = parseFloat(ttrack.height) + parseFloat(diffheight)
|
|
console.log(ttrack.height)
|
|
|
|
}
|
|
if (track.keyframes[nextframe].opacity !== ttrack.opacity) {
|
|
console.log('opa', track.keyframes[nextframe].opacity, ttrack.opacity)
|
|
var diffopacity = (track.keyframes[nextframe].opacity - ttrack.opacity)
|
|
diffopacity = parseFloat(diffopacity) / parseFloat(keyframe.end - keyframe.start)
|
|
console.log(diffopacity)
|
|
diffopacity = (newval - keyframe.start) * diffopacity
|
|
ttrack.opacity = parseFloat(ttrack.opacity) + parseFloat(diffopacity)
|
|
console.log(ttrack.opacity)
|
|
}
|
|
|
|
if (track.keyframes[nextframe].y !== ttrack.y) {
|
|
var diffy = (track.keyframes[nextframe].y - ttrack.y)
|
|
diffy = diffy / (keyframe.end - keyframe.start)
|
|
diffy = (newval - keyframe.start) * diffy
|
|
ttrack.y = parseFloat(ttrack.y) + parseFloat(diffy)
|
|
}
|
|
}
|
|
this.vidTracks[track.id] = ttrack
|
|
}
|
|
})
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
newMask() {
|
|
this.oncreateMask = true
|
|
this.create = 'mask'
|
|
this.action = "create"
|
|
},
|
|
itemMoveStart(event) {
|
|
console.log(event)
|
|
this.moveItem = true
|
|
this.clickOffset.x = event.offsetX
|
|
this.clickOffset.y = event.offsetY
|
|
},
|
|
preview() {
|
|
this.pinterval = setInterval(() => {
|
|
this.currentTime += 1 / 60
|
|
if (this.currentTime >= 60) this.currentTime = 0
|
|
}, 1000 / 60)
|
|
},
|
|
previewStop() {
|
|
if (this.pinterval) clearInterval(this.pinterval)
|
|
},
|
|
newKeyFrame() {
|
|
this.mainTracks.forEach(track => {
|
|
if (track.id === this.selectedTrack.id) {
|
|
var pushFrame = null
|
|
var newFrames = []
|
|
var endTime = null
|
|
track.keyframes.forEach(keyframe => {
|
|
if (keyframe.start <= this.currentTime && keyframe.end >= this.currentTime) {
|
|
pushFrame = {
|
|
start: keyframe.start,
|
|
x: keyframe.x,
|
|
y: keyframe.y,
|
|
width: keyframe.width,
|
|
opacity: keyframe.opacity,
|
|
height: keyframe.height,
|
|
}
|
|
pushFrame.start = this.currentTime
|
|
keyframe.end = this.currentTime
|
|
}
|
|
if (pushFrame && pushFrame.start < keyframe.start) {
|
|
endTime = keyframe.start
|
|
}
|
|
newFrames.push(keyframe)
|
|
})
|
|
pushFrame.end = endTime
|
|
if (!pushFrame.end) pushFrame.end = track.end
|
|
newFrames.push(pushFrame)
|
|
track.keyframes = newFrames
|
|
}
|
|
})
|
|
},
|
|
selectTrack(track) {
|
|
if (this.selectedTrack === track) {
|
|
this.selectedTrack = null
|
|
return
|
|
}
|
|
this.selectedTrack = track
|
|
console.log(this.selectedTrack)
|
|
this.mainTracks.forEach((track, tindex) => {
|
|
|
|
if (this.selectedTrack.id === track.id) {
|
|
|
|
track.keyframes.forEach((kvarey, index) => {
|
|
if (kvarey.start <= this.currentTime && this.currentTime <= kvarey.end) {
|
|
this.currentKeyTrack.keyframe = index
|
|
this.currentKeyTrack.track = tindex
|
|
|
|
}
|
|
})
|
|
}
|
|
})
|
|
},
|
|
startChangeSizeTrack() {
|
|
this.sizeChangeStart = true
|
|
console.log("start size")
|
|
}
|
|
, startPositionTrack(event) {
|
|
|
|
if (!this.sizeChangeStart) this.positionChangeStart = true
|
|
console.log("start pos", event)
|
|
this.clickOffset.x = event.offsetX
|
|
},
|
|
deselectTrack() {
|
|
this.selectedTrack = null
|
|
this.sizeChangeStart = false
|
|
this.positionChangeStart = false
|
|
},
|
|
allmoveend() {
|
|
this.sizeChangeStart = false
|
|
this.positionChangeStart = false
|
|
},
|
|
colorBorderClear(track) {
|
|
var refItem = this.$refs['item' + track.id][0]
|
|
var id = ""
|
|
if (this.selectedTrack !== null) {
|
|
id = this.selectedTrack.id
|
|
}
|
|
if (id !== track.id) {
|
|
refItem.style.border = "1px solid transparent"
|
|
}
|
|
|
|
},
|
|
colorBorder(track) {
|
|
|
|
var refItem = this.$refs['item' + track.id][0]
|
|
var id = ""
|
|
if (this.selectedTrack !== null) {
|
|
id = this.selectedTrack.id
|
|
}
|
|
if (id !== track.id) {
|
|
refItem.style.border = "1px solid #ededed"
|
|
}
|
|
|
|
},
|
|
itemMoveEnd() {
|
|
this.moveItem = false
|
|
},
|
|
newTrack() {
|
|
this.tracks.push({})
|
|
},
|
|
editItem(item) {
|
|
console.log(item)
|
|
this.editingItem = item
|
|
var ref = this.$refs['item' + item.id][0]
|
|
console.log(ref)
|
|
// this.vidTracks.forEach(item => {
|
|
// var refItem = this.$refs['item' + item.id][0]
|
|
// refItem.style.border = "1px solid transparent"
|
|
//
|
|
// })
|
|
ref.style.border = "1px solid #000"
|
|
},
|
|
itemMove(event) {
|
|
|
|
if (this.action) {
|
|
if (this.action === 'create') {
|
|
this.moveX = event.clientX - 30
|
|
this.moveY = event.clientY - 30
|
|
}
|
|
|
|
if (this.action === 'paint') {
|
|
this.width = event.clientX - this.moveX
|
|
this.height = event.clientY - this.moveY
|
|
|
|
}
|
|
}
|
|
},
|
|
handleAction() {
|
|
console.log(this.action)
|
|
if (this.action === "create" || this.action === 'paint') {
|
|
var bodyRect = document.body.getBoundingClientRect(),
|
|
elemRect = this.$refs.vid.getBoundingClientRect(),
|
|
offsetY = elemRect.top - bodyRect.top,
|
|
offsetX = elemRect.left - bodyRect.left
|
|
if ((this.create === 'rect' || this.create === 'mask') && this.action === 'create') {
|
|
this.action = 'paint'
|
|
return
|
|
}
|
|
if (this.create === 'mask') {
|
|
|
|
|
|
this.mainTracks[this.currentKeyTrack.track].mask = {
|
|
x: this.moveX - offsetX,
|
|
y: this.moveY - offsetY,
|
|
width: this.width,
|
|
height: this.height,
|
|
}
|
|
this.mainTracks.__ob__.dep.notify()
|
|
this.oncreateMask = false
|
|
return
|
|
}
|
|
console.log(offsetY, offsetX)
|
|
var item = {
|
|
x: this.moveX - offsetX,
|
|
y: this.moveY - offsetY,
|
|
width: 0,
|
|
height: 0,
|
|
type: this.create,
|
|
opacity: 1,
|
|
index: this.index,
|
|
id: new Date().getTime(),
|
|
color: "#000",
|
|
mask: null
|
|
}
|
|
if (this.create === 'image') {
|
|
var upload = document.createElement('input')
|
|
upload.type = 'file'
|
|
upload.click()
|
|
upload.onchange = () => {
|
|
const reader = new FileReader();
|
|
reader.readAsDataURL(upload.files[0]);
|
|
reader.onloadend = () => {
|
|
item.image_data = reader.result
|
|
var image = new Image();
|
|
image.src = reader.result
|
|
image.onload = () => {
|
|
console.log(item)
|
|
this.index++
|
|
|
|
var maintrack = item
|
|
maintrack.keyframes = [{
|
|
x: item.x,
|
|
y: item.y,
|
|
width: image.width,
|
|
opacity: 1,
|
|
height: image.height,
|
|
start: this.currentTime,
|
|
end: this.timeLength,
|
|
lineHeight: 'default',
|
|
letterSpacing: 'default'
|
|
}]
|
|
maintrack.start = this.currentTime
|
|
maintrack.end = this.timeLength
|
|
this.mainTracks.push(maintrack)
|
|
this.vidTracks[item.id] = item
|
|
this.action = null
|
|
this.create = null
|
|
}
|
|
|
|
|
|
}
|
|
console.log(item)
|
|
|
|
console.log(upload.files)
|
|
}
|
|
} else {
|
|
|
|
|
|
console.log(item)
|
|
this.index++
|
|
|
|
var maintrack = item
|
|
maintrack.keyframes = [{
|
|
x: item.x,
|
|
y: item.y,
|
|
width: 0,
|
|
height: 0,
|
|
opacity: 1,
|
|
lineHeight: 'initial',
|
|
letterSpacing: 'initial',
|
|
start: this.currentTime,
|
|
end: this.timeLength
|
|
}]
|
|
if (this.create === 'rect') {
|
|
maintrack.keyframes[0].width = this.width
|
|
maintrack.keyframes[0].height = this.height
|
|
}
|
|
maintrack.start = this.currentTime
|
|
maintrack.end = this.timeLength
|
|
this.mainTracks.push(maintrack)
|
|
|
|
if (this.create === 'text') {
|
|
item.text = "Text"
|
|
item.font = "Arial"
|
|
item.size = '24px'
|
|
item.color = '#000'
|
|
item.align = 'left'
|
|
item.lineHeight = 'initial'
|
|
item.letterSpacing = 'initial'
|
|
|
|
}
|
|
|
|
this.vidTracks[item.id] = item
|
|
this.action = null
|
|
this.create = null
|
|
}
|
|
this.currentTime += 0.01
|
|
this.selectTrack(maintrack)
|
|
|
|
}
|
|
},
|
|
addItemStart(type) {
|
|
console.log(type)
|
|
this.create = type
|
|
this.action = 'create'
|
|
},
|
|
clearStart() {
|
|
this.create = null
|
|
},
|
|
getTracks() {
|
|
this.tracks.forEach(item => {
|
|
console.log(item)
|
|
})
|
|
}
|
|
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
#video_edit {
|
|
width: 1280px;
|
|
height: 720px;
|
|
border: 1px solid #ccc;
|
|
}
|
|
|
|
#video_tracks {
|
|
min-height: 100px;
|
|
padding: 2px;
|
|
width: 100%;
|
|
border: 1px solid #ccc;
|
|
overflow-y: auto;
|
|
}
|
|
</style>
|
|
|