blessing-skin-server/resources/assets/src/components/Previewer.vue
2019-12-24 19:33:35 +08:00

179 lines
4.5 KiB
Vue

<template>
<div class="card">
<div class="card-header">
<div class="d-flex justify-content-between">
<h3 class="card-title">
<span v-html="$t(title)" /> <!-- eslint-disable-line vue/no-v-html -->
<span class="badge bg-olive">{{ indicator }}</span>
</h3>
<div class="operations">
<i
data-toggle="tooltip"
data-placement="bottom"
:title="$t('general.walk') + ' / ' + $t('general.run')"
class="fas fa-forward"
@click="toggleRun"
/>
<i
data-toggle="tooltip"
data-placement="bottom"
:title="$t('general.rotation')"
class="fas fa-redo-alt"
@click="toggleRotate"
/>
<i
data-toggle="tooltip"
data-placement="bottom"
:title="$t('general.pause')"
class="fas"
:class="{ 'fa-pause': !paused, 'fa-play': paused }"
@click="togglePause"
/>
<i
data-toggle="tooltip"
data-placement="bottom"
:title="$t('general.reset')"
class="fas fa-stop"
@click="reset"
/>
</div>
</div>
</div>
<div class="card-body">
<div ref="previewer" class="previewer-3d">
<!-- Container for 3D Preview -->
</div>
</div>
<div v-if="$slots.footer" class="card-footer">
<slot name="footer" />
</div>
</div>
</template>
<script>
import * as skinview3d from 'skinview3d'
import { emit } from '../scripts/event'
import SkinSteve from '../images/textures/steve.png'
export default {
name: 'Previewer',
props: {
skin: String,
cape: String,
model: {
type: String,
default: 'steve',
},
closetMode: Boolean,
title: {
type: String,
default: 'general.texturePreview',
},
initPositionZ: {
type: Number,
default: 70,
},
},
data: () => ({
paused: false,
}),
computed: {
indicator() {
if (!this.closetMode) {
return ''
}
if (this.skin && this.cape) {
return `${this.$t('general.skin')} & ${this.$t('general.cape')}`
} else if (this.skin) {
return this.$t('general.skin')
} else if (this.cape) {
return this.$t('general.cape')
}
return ''
},
},
watch: {
skin(url) {
this.viewer.skinUrl = url || SkinSteve
},
cape(url) {
if (!url) {
this.viewer.playerObject.cape.visible = false
return
}
this.viewer.capeUrl = url
},
model(value) {
this.viewer.playerObject.skin.slim = value === 'alex'
},
},
mounted() {
this.initPreviewer()
emit('skinViewerMounted', this.$refs.previewer)
},
beforeDestroy() {
this.viewer.dispose()
},
methods: {
initPreviewer() {
this.viewer = new skinview3d.SkinViewer({
domElement: this.$refs.previewer,
width: this.$refs.previewer.clientWidth,
height: this.$refs.previewer.clientHeight,
detectModel: false,
skinUrl: this.skin || SkinSteve,
capeUrl: this.cape,
})
this.viewer.camera.position.z = this.initPositionZ
this.viewer.animation = new skinview3d.CompositeAnimation()
this.handles = {
walk: this.viewer.animation.add(skinview3d.WalkingAnimation),
run: this.viewer.animation.add(skinview3d.RunningAnimation),
rotate: this.viewer.animation.add(skinview3d.RotatingAnimation),
}
this.handles.run.paused = true
this.control = skinview3d.createOrbitControls(this.viewer)
},
togglePause() {
this.paused = !this.paused
this.viewer.animationPaused = !this.viewer.animationPaused
},
toggleRun() {
this.handles.run.paused = !this.handles.run.paused
this.handles.walk.paused = false
},
toggleRotate() {
this.handles.rotate.paused = !this.handles.rotate.paused
},
reset() {
this.viewer.dispose()
this.initPreviewer()
this.handles.walk.paused = true
this.handles.run.paused = true
this.handles.rotate.paused = true
this.viewer.camera.position.z = 70
this.viewer.playerObject.skin.slim = this.model === 'alex'
},
},
}
</script>
<style lang="stylus">
@media (min-width: 992px)
.previewer-3d
min-height 500px
.previewer-3d canvas
cursor move
.operations
i
padding .5em .5em
display inline
&:hover
color #555
cursor pointer
</style>