/*online-demo*/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
[v-cloak] {
display: none;
}
ul,
li {
padding: 0;
margin: 0;
list-style: none;
}
html,
body {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
.scene {
width: 100%;
height: 100%;
}
#app {
position: absolute;
pointer-events: none;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 100;
}
.progress {
display: none;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 4px;
}
.progress div {
height: 100%;
width: 0;
background-color: #f60;
}
#parts ul,
#frames ul {
display: flex;
}
#parts li {
position: relative;
color: #fff;
padding: 5px;
margin-right: 10px;
cursor: pointer;
}
#parts li span {
display: none;
position: absolute;
right: -10px;
top: -10px;
}
#parts li:hover,
#parts li.active {
color: #f60;
}
#parts li.active .progress {
display: block;
}
#parts li.active span {
display: block;
}
#frames li {
position: relative;
margin-left: 5px;
border: solid 1px transparent;
cursor: pointer;
}
#frames li span {
display: none;
position: absolute;
right: 0px;
top: 0px;
width: 16px;
height: 16px;
background-color: #fff;
text-align: center;
}
#frames li.active {
border: solid 1px #f60;
}
#frames li.active .progress {
display: block;
}
#frames li.active span {
display: block;
}
.toolbar {
pointer-events: all;
position: absolute;
left: 50%;
top: 0;
transform: translateX(-50%);
}
.bottom {
pointer-events: all;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 200px;
background-color: rgba(0, 0, 0, 0.5);
}
.bottom.disable {
pointer-events: none;
opacity: 0.5;
}
</style>
</head>
<body>
<div id="scene" class="scene"></div>
<div id="app" v-cloak>
<div class="toolbar">
<button :disabled="playing" @click="addFrame">添加画面</button>
<button :disabled="playing" @click="addPart">添加片段</button>
<button :disabled="playing" @click="clear">清空</button>
<button @click="play">{{ playing?'暂停':'播放' }}</button>
</div>
<div class="bottom" :class="{disable:disable}">
<div id="parts">
<ul>
<li v-for="(part,index) in tours" :class="{active:index == partId}" @click="selectPart(index)">
{{part.name || '片段_'+index}}
<span @click.stop="deletePart(index)">X</span>
<div class="progress"><div :style="{width:progressPart+'%'}"></div></div>
</li>
</ul>
</div>
<div id="frames" :partid="partId" :frameid="frameId">
<div v-for="(part,index) in tours" v-show="partId == index" :length="part.list.length">
<ul>
<li v-for="(frame,index) in part.list" :class="{active:index == frameId}" @click="selectFrame(index)">
<img style="width: 200px; height: 140px" :src="frame.enter.cover" />
<span @click.stop="deleteFrame(index)">X</span>
<div class="progress"><div :style="{width:progress+'%'}"></div></div>
</li>
</ul>
</div>
</div>
</div>
</div>
<script src="//4dkk.4dage.com/v4/sdk/4.2.2/kankan-sdk-deps.js"></script>
<script src="//4dkk.4dage.com/v4/sdk/4.2.2/kankan-sdk.js"></script>
<script src="../../libs/vue.min.js"></script>
<script>
var app = null
new Vue({
el: '#app',
data() {
return {
tours: [],
partId: 0,
frameId: 0,
progress: 0,
progressPart: 0,
disable: false,
playing: false,
}
},
mounted() {
app = new KanKan({
dom: '#scene',
num:'KJ-JYo2ZZyKKJ'
})
app.use('TourRecorder').then(recorder => {
recorder.on('change', e => {
if (e.type == 'clear') {
this.$forceUpdate()
}
else if (e.action == 'add') {
this.partId = recorder.partId
this.frameId = recorder.frameId
} else if (e.action == 'delete') {
this.partId = recorder.partId
this.frameId = recorder.frameId
}
})
})
app.use('TourPlayer').then(player => {
player.on('play', ({ partId, frameId }) => (this.playing = true))
player.on('pause', ({ partId, frameId }) => (this.playing = false))
player.on('end', () => {
this.playing = false
// 兼容最后一个画面没有进度的问题
this.progressPart = 100
})
var currPartId
var currFrames
var currProgress
player.on('progress', ({ partId, frameId, progress }) => {
// 画面进度
this.partId = partId
this.frameId = frameId
this.progress = Number(progress * 100).toFixed(5)
// 片段进度
if (this.tours.length == 1) {
this.progressPart = this.progress
} else {
if (currPartId != partId) {
currPartId = partId
currFrames = this.tours[partId].list.length
this.progressPart = 0
}
this.progressPart += progress / currFrames
}
})
})
// 需要双向绑定时,重新设置数据
app.TourManager.on('loaded', tours => {
this.tours = tours
app.TourManager.load(this.tours)
})
app.render()
},
methods: {
async selectPart(partId) {
if (this.disable) {
return
}
this.partId = partId
this.frameId = 0
this.disable = true
this.progress = 0
this.progressPart = 0
var recorder = await app.TourManager.recorder
await recorder.selectPart(partId)
this.disable = false
},
async selectFrame(frameId) {
if (this.disable) {
return
}
this.frameId = frameId
this.disable = true
this.progress = 0
this.progressPart = 0
var recorder = await app.TourManager.recorder
await recorder.selectFrame(frameId)
this.disable = false
},
async play() {
var player = await app.TourManager.player
this.progress = 0
if (this.playing) {
player.pause()
} else {
player.play()
}
},
async clear() {
;(await app.TourManager.recorder).clear()
},
async addPart() {
;(await app.TourManager.recorder).addPart()
},
async addFrame() {
;(await app.TourManager.recorder).addFrame()
},
async deletePart(partId) {
this.partId = partId
;(await app.TourManager.recorder).deletePart(partId)
},
async deleteFrame(frameId) {
this.frameId = frameId
;(await app.TourManager.recorder).deleteFrame(frameId)
},
},
})
</script>
</body>
</html>