|
@@ -46,7 +46,7 @@
|
|
|
query: $route.query,
|
|
|
})"
|
|
|
/>
|
|
|
- <transition name="fade-in">
|
|
|
+ <transition name="fade-in-out">
|
|
|
<div
|
|
|
v-show="isShowLion"
|
|
|
class="lion-wrapper"
|
|
@@ -54,27 +54,38 @@
|
|
|
<img
|
|
|
v-click-audio
|
|
|
class="lion"
|
|
|
- :src="require(`@/assets/images/lion-${sceneInfo.lionGender}-speaking.gif`)"
|
|
|
+ :src="require(`@/assets/images/lion-${sceneInfo.lionGender}-${isLionSpeeking ? 'speaking' : 'idle'}.gif`)"
|
|
|
alt=""
|
|
|
draggable="false"
|
|
|
@click="onClickLion"
|
|
|
>
|
|
|
- <transition name="fade-in">
|
|
|
+ <transition name="fade-in-out">
|
|
|
<div
|
|
|
v-show="isLionSpeeking"
|
|
|
class="speach-text-wrapper"
|
|
|
>
|
|
|
- <div class="speach-text">
|
|
|
- {{ lionSpeachText }}
|
|
|
+ <div
|
|
|
+ class="speach-text"
|
|
|
+ >
|
|
|
+ {{ lionSpeachTextList[currentSpeachTextIdx]?.content }}
|
|
|
+ <div
|
|
|
+ v-show="isSpeachTextChanging"
|
|
|
+ class="mask"
|
|
|
+ :class="{
|
|
|
+ active: isSpeachTextChanging,
|
|
|
+ }"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
</transition>
|
|
|
</div>
|
|
|
</transition>
|
|
|
<audio
|
|
|
- v-if="lionSpeachText"
|
|
|
- ref="lionSpeachEl"
|
|
|
+ v-if="lionSpeachTextList"
|
|
|
+ ref="lionSpeachAudio"
|
|
|
:src="require(`@/assets/audios/lionSpeach-${$route.query.sceneIdxLevel2}-${$route.query.sceneIdxLevel3}.mp3`)"
|
|
|
+ @ended="onAudioEnd"
|
|
|
+ @timeupdate="onAudioTimeUpdate"
|
|
|
/>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -85,6 +96,7 @@ import {
|
|
|
onBeforeUnmount,
|
|
|
onMounted,
|
|
|
onUnmounted,
|
|
|
+ reactive,
|
|
|
ref,
|
|
|
watch,
|
|
|
} from 'vue'
|
|
@@ -125,26 +137,61 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const lionSpeachEl = ref(null)
|
|
|
+ const lionSpeachAudio = ref(null)
|
|
|
watch(isLionSpeeking, (vNew) => {
|
|
|
if (vNew) {
|
|
|
- lionSpeachEl.value && lionSpeachEl.value.play()
|
|
|
+ lionSpeachAudio.value && lionSpeachAudio.value.play()
|
|
|
}
|
|
|
})
|
|
|
onBeforeUnmount(() => {
|
|
|
- lionSpeachEl.value && lionSpeachEl.value.pause()
|
|
|
+ lionSpeachAudio.value && lionSpeachAudio.value.pause()
|
|
|
})
|
|
|
|
|
|
- const lionSpeachText = config.sceneTree[route.query.sceneIdxLevel2].children[route.query.sceneIdxLevel3].lionSpeach
|
|
|
+ const lionSpeachTextList = reactive([
|
|
|
+ {
|
|
|
+ startTime: 0,
|
|
|
+ endTime: 9,
|
|
|
+ content: '当我们来到徽州,总能看见许许多多门洞形状的建筑物,它就是“徽州三绝”之一的牌坊。',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ startTime: 9,
|
|
|
+ endTime: Infinity,
|
|
|
+ content: '徽州因为拥有的牌坊数量众多,样式精美,也被誉为“牌坊之乡”。',
|
|
|
+ },
|
|
|
+ ])
|
|
|
+ const currentSpeachTextIdx = ref(null)
|
|
|
+ function onAudioEnd() {
|
|
|
+ isLionSpeeking.value = false
|
|
|
+ }
|
|
|
+ const isSpeachTextChanging = ref(false)
|
|
|
+ watch(currentSpeachTextIdx, (vNew) => {
|
|
|
+ isSpeachTextChanging.value = true
|
|
|
+ setTimeout(() => {
|
|
|
+ isSpeachTextChanging.value = false
|
|
|
+ }, 3000, { immediate: true })
|
|
|
+ })
|
|
|
+ const onAudioTimeUpdate = utils.throttle(() => {
|
|
|
+ console.log(lionSpeachAudio.value.currentTime)
|
|
|
+ for (let index = 0; index < lionSpeachTextList.length; index++) {
|
|
|
+ const lionSpeachTextItem = lionSpeachTextList[index]
|
|
|
+ if (lionSpeachTextItem.startTime <= lionSpeachAudio.value.currentTime && lionSpeachTextItem.endTime >= lionSpeachAudio.value.currentTime) {
|
|
|
+ currentSpeachTextIdx.value = index
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, 1000)
|
|
|
|
|
|
return {
|
|
|
isLionSpeeking,
|
|
|
isShowLion,
|
|
|
- lionSpeachEl,
|
|
|
- lionSpeachText,
|
|
|
+ lionSpeachAudio,
|
|
|
+ lionSpeachTextList,
|
|
|
onClickLion,
|
|
|
unit,
|
|
|
windowSizeWhenDesign,
|
|
|
+ onAudioEnd,
|
|
|
+ onAudioTimeUpdate,
|
|
|
+ currentSpeachTextIdx,
|
|
|
+ isSpeachTextChanging,
|
|
|
}
|
|
|
},
|
|
|
data() {
|
|
@@ -304,15 +351,36 @@ export default {
|
|
|
padding-bottom: calc(210 / v-bind('windowSizeWhenDesign') * v-bind('unit'));
|
|
|
>.speach-text {
|
|
|
height: 100%;
|
|
|
- font-size: calc(16 / v-bind('windowSizeWhenDesign') * v-bind('unit'));
|
|
|
+ font-size: calc(20 / v-bind('windowSizeWhenDesign') * v-bind('unit'));
|
|
|
line-height: 1.3;
|
|
|
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
|
|
|
font-weight: 400;
|
|
|
color: #2D241D;
|
|
|
- overflow: auto;
|
|
|
+ overflow-y: auto;
|
|
|
padding-right: calc(8 / v-bind('windowSizeWhenDesign') * v-bind('unit'));
|
|
|
+ position: relative;
|
|
|
+ overflow-x: hidden;
|
|
|
+ >.mask{
|
|
|
+ position: absolute;
|
|
|
+ left: -100%;
|
|
|
+ top: 0;
|
|
|
+ width: 200%;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 30%);
|
|
|
+ &.active {
|
|
|
+ animation: changeSpeachText 2s linear forwards;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+@keyframes changeSpeachText {
|
|
|
+ 0% {
|
|
|
+ left: -100%;
|
|
|
+ }
|
|
|
+ 100% {
|
|
|
+ left: 100%;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|