|
@@ -77,7 +77,7 @@
|
|
|
@dragstart.prevent
|
|
|
>
|
|
|
<HotSpot
|
|
|
- v-if="[3].includes(tourState)"
|
|
|
+ v-if="canMoveCamera"
|
|
|
class="hot-spot"
|
|
|
@click="onClickPeopleFarHotSpot"
|
|
|
/>
|
|
@@ -96,22 +96,20 @@
|
|
|
@dragstart.prevent
|
|
|
>
|
|
|
<HotSpot
|
|
|
- v-show="[3].includes(tourState)"
|
|
|
+ v-show="canMoveCamera"
|
|
|
class="hot-spot"
|
|
|
@click="onClickPeopleNearHotSpot"
|
|
|
/>
|
|
|
- <img
|
|
|
- v-if="[0, 3].includes(tourState)"
|
|
|
- ref="treasure"
|
|
|
- class="treasure"
|
|
|
- :style="{
|
|
|
- height: treasureInitialHeightPercent + '%',
|
|
|
- opacity: treasureOpacity,
|
|
|
- }"
|
|
|
- src="@/assets/treasure.png"
|
|
|
- alt=""
|
|
|
- @dragstart.prevent
|
|
|
- >
|
|
|
+ <TreasureDisplay
|
|
|
+ ref="treasure-display"
|
|
|
+ class="treasure-display"
|
|
|
+ :treasure-frame-total-num="treasureFrameTotalNum"
|
|
|
+ :treasure-initial-height-percent="treasureInitialHeightPercent"
|
|
|
+ :treasure-frame-width="treasureFrameWidth"
|
|
|
+ :treasure-frame-height="treasureFrameHeight"
|
|
|
+ @display-started="canMoveCamera = false"
|
|
|
+ @display-stopped="canMoveCamera = true"
|
|
|
+ />
|
|
|
</div>
|
|
|
<img
|
|
|
class="introduce"
|
|
@@ -122,47 +120,10 @@
|
|
|
alt=""
|
|
|
@dragstart.prevent
|
|
|
>
|
|
|
-
|
|
|
- <div
|
|
|
- v-if="[0, 1, 2].includes(tourState)"
|
|
|
- class="fade-mask"
|
|
|
- :style="{
|
|
|
- opacity: maskOpacity,
|
|
|
- }"
|
|
|
- >
|
|
|
- <img
|
|
|
- v-show="[2].includes(tourState)"
|
|
|
- src="@/assets/treasure-last-frame.jpg"
|
|
|
- alt=""
|
|
|
- >
|
|
|
- </div>
|
|
|
-
|
|
|
- <button
|
|
|
- v-if="[0, 1, 2].includes(tourState)"
|
|
|
- class="btn-stop-treasure-display"
|
|
|
- @click="onClickStopTreasureDisplay"
|
|
|
- >
|
|
|
- <img
|
|
|
- src="@/assets/button-stop.png"
|
|
|
- alt=""
|
|
|
- >
|
|
|
- </button>
|
|
|
-
|
|
|
- <SerialFrames
|
|
|
- v-show="[1].includes(tourState)"
|
|
|
- ref="treasure-serial-frames"
|
|
|
- class="treasure-serial-frames"
|
|
|
- :frame-total-num="treasureFrameTotalNum"
|
|
|
- :frame-interval="40"
|
|
|
- :image-src-func="(index) => require(`@/assets/treasure-frames/3_${(index - 1).toString().padStart(5, '0')}.jpg`)"
|
|
|
- @over="tourState=2, treasureFadeOutTween.start()"
|
|
|
- />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import TWEEN from '@tweenjs/tween.js'
|
|
|
-
|
|
|
const initialLandscapePositionLeft = '18.491%'
|
|
|
const initialCloud2PositionLeft = '35%'
|
|
|
const initialCloud1PositionLeft = '0%'
|
|
@@ -181,19 +142,23 @@ const introduceSpeedRate = 0.6
|
|
|
|
|
|
const translateLengthRightBorder = 9000 // 单位:px
|
|
|
|
|
|
-const treasureFadeInDuration = 3000 // 单位:ms
|
|
|
-const treasureFadeOutDuration = 2000 // 单位:ms
|
|
|
-
|
|
|
-const treasureFrameTotalNum = 196
|
|
|
-
|
|
|
-const treasureInitialHeightPercent = 8 // 0~100
|
|
|
-const treasureFrameWidth = 1366 // 单位:px
|
|
|
-const treasureFrameHeight = 768 // 单位:px
|
|
|
+// 文物展示相关
|
|
|
+const treasureDisplayConfigMixins = {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ treasureFrameTotalNum: 196,
|
|
|
+ treasureInitialHeightPercent: 8,
|
|
|
+ treasureFrameWidth: 1366,
|
|
|
+ treasureFrameHeight: 768,
|
|
|
+ }
|
|
|
+ },
|
|
|
+}
|
|
|
|
|
|
export default {
|
|
|
name: 'HomeView',
|
|
|
components: {
|
|
|
},
|
|
|
+ mixins: [treasureDisplayConfigMixins],
|
|
|
data() {
|
|
|
return {
|
|
|
// 鼠标拖拽相关
|
|
@@ -205,7 +170,7 @@ export default {
|
|
|
lastAnimationTimeStamp: 0,
|
|
|
animationFrameId: null,
|
|
|
|
|
|
- tourState: 3, // 0:文物淡入过渡阶段;1:文物三维展示阶段;2:文物渐出过渡阶段;3:镜头平移阶段
|
|
|
+ canMoveCamera: true,
|
|
|
|
|
|
// 镜头平移相关
|
|
|
translateLength: 0,
|
|
@@ -218,80 +183,12 @@ export default {
|
|
|
peopleNearPositionLeft: initialPeopleNearPositionLeft,
|
|
|
introducePositionLeft: initialIntroducePositionLeft,
|
|
|
|
|
|
- // 文物淡入相关
|
|
|
- treasureFadeInProgress: {
|
|
|
- value: 0, // 0~100
|
|
|
- },
|
|
|
- treasureFadeInInitialLeft: 0,
|
|
|
- treasureFadeInInitialTop: 0,
|
|
|
- treasureFadeInFinalLeft: 0,
|
|
|
- treasureFadeInFinalTop: 0,
|
|
|
- treasureInitialHeightPercent,
|
|
|
- treasureFinalHeightPercent: 0, // 0~100
|
|
|
- treasureFadeInTween: null,
|
|
|
-
|
|
|
- // 文物展示相关
|
|
|
- treasureFrameTotalNum,
|
|
|
-
|
|
|
- // 文物淡出相关
|
|
|
- treasureFadeOutProgress: {
|
|
|
- value: 0, // 0~100
|
|
|
- },
|
|
|
- treasureFadeOutTween: null,
|
|
|
-
|
|
|
// 远处人物变色相关
|
|
|
peopleFarColorStatus: 'no-color', // 'no-color', 'color'
|
|
|
isPeopleFarColorChanging: false,
|
|
|
}
|
|
|
},
|
|
|
- computed: {
|
|
|
- treasureOpacity() {
|
|
|
- if (this.tourState === 0) {
|
|
|
- if (this.treasureFadeInProgress.value > 50) {
|
|
|
- return 1
|
|
|
- } else {
|
|
|
- return this.treasureFadeInProgress.value / 50
|
|
|
- }
|
|
|
- } else if (this.tourState === 2) {
|
|
|
- if (this.treasureFadeOutProgress.value < 50) {
|
|
|
- return 1
|
|
|
- } else {
|
|
|
- return 1 - (this.treasureFadeOutProgress.value - 50) / 50
|
|
|
- }
|
|
|
- } else {
|
|
|
- return 0
|
|
|
- }
|
|
|
- },
|
|
|
- maskOpacity() {
|
|
|
- if (this.tourState === 0) {
|
|
|
- if (this.treasureFadeInProgress.value > 50) {
|
|
|
- return 1
|
|
|
- } else {
|
|
|
- return this.treasureFadeInProgress.value / 50
|
|
|
- }
|
|
|
- } else if (this.tourState === 1) {
|
|
|
- return 1
|
|
|
- } else if (this.tourState === 2) {
|
|
|
- return (100 - this.treasureFadeOutProgress.value) / 100
|
|
|
- } else {
|
|
|
- return 0
|
|
|
- }
|
|
|
- },
|
|
|
- },
|
|
|
watch: {
|
|
|
- 'treasureFadeInProgress.value': {
|
|
|
- handler(vNew, vOld) {
|
|
|
- if (this.treasureFadeInProgress.value > 50) {
|
|
|
- this.$refs.treasure.style.left = this.treasureFadeInInitialLeft + (this.treasureFadeInProgress.value - 50) / 50 * (this.treasureFadeInFinalLeft - this.treasureFadeInInitialLeft) + 'px'
|
|
|
- this.$refs.treasure.style.top = this.treasureFadeInInitialTop + (this.treasureFadeInProgress.value - 50) / 50 * (this.treasureFadeInFinalTop - this.treasureFadeInInitialTop) + 'px'
|
|
|
- this.$refs.treasure.style.transform = `translate(-50%, -50%) scale(${1 + (this.treasureFadeInProgress.value - 50) / 50 * (this.treasureFinalHeightPercent / this.treasureInitialHeightPercent - 1)})`
|
|
|
- } else {
|
|
|
- this.$refs.treasure.style.left = this.treasureFadeInInitialLeft + 'px'
|
|
|
- this.$refs.treasure.style.top = this.treasureFadeInInitialTop + 'px'
|
|
|
- this.$refs.treasure.style.transform = `translate(-50%, -50%) scale(1)`
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
translateLength: {
|
|
|
handler(vNew, vOld) {
|
|
|
this.paperPositionLeft = `${vNew * landscapeSpeedRate}px`
|
|
@@ -306,33 +203,10 @@ export default {
|
|
|
},
|
|
|
},
|
|
|
mounted() {
|
|
|
- const that = this
|
|
|
this.animationFrameId = requestAnimationFrame(this.animationFrameTask)
|
|
|
-
|
|
|
- this.treasureFadeInTween = new TWEEN.Tween(that.treasureFadeInProgress)
|
|
|
- this.treasureFadeInTween.to({
|
|
|
- value: 100,
|
|
|
- }, treasureFadeInDuration)
|
|
|
- this.treasureFadeInTween.onComplete(() => {
|
|
|
- this.tourState = 1
|
|
|
- this.$refs['treasure-serial-frames'].play()
|
|
|
- })
|
|
|
- this.treasureFadeInTween.easing(TWEEN.Easing.Linear.None)
|
|
|
-
|
|
|
- this.treasureFadeOutTween = new TWEEN.Tween(that.treasureFadeOutProgress)
|
|
|
- this.treasureFadeOutTween.to({
|
|
|
- value: 100,
|
|
|
- }, treasureFadeOutDuration)
|
|
|
- this.treasureFadeOutTween.onComplete(() => {
|
|
|
- this.tourState = 3
|
|
|
- })
|
|
|
- this.treasureFadeOutTween.easing(TWEEN.Easing.Linear.None)
|
|
|
-
|
|
|
},
|
|
|
unmounted() {
|
|
|
cancelAnimationFrame(this.animationFrameId)
|
|
|
- this.treasureFadeInTween.stop()
|
|
|
- this.treasureFadeOutTween.stop()
|
|
|
clearInterval(this.treasureFrameIntervalId)
|
|
|
},
|
|
|
methods: {
|
|
@@ -359,7 +233,7 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
onWheel(e) {
|
|
|
- if (this.tourState === 3) {
|
|
|
+ if (this.canMoveCamera) {
|
|
|
this.translateLength -= e.deltaY
|
|
|
if (this.translateLength > 0) {
|
|
|
this.translateLength = 0
|
|
@@ -387,7 +261,7 @@ export default {
|
|
|
}
|
|
|
|
|
|
// 根据速度更新距离
|
|
|
- if (this.tourState === 3) {
|
|
|
+ if (this.canMoveCamera) {
|
|
|
this.translateLength += this.moveSpeed * timeElapsed
|
|
|
if (this.translateLength > 0) {
|
|
|
this.translateLength = 0
|
|
@@ -397,8 +271,6 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- TWEEN.update()
|
|
|
-
|
|
|
this.lastAnimationTimeStamp = timeStamp
|
|
|
this.animationFrameId = requestAnimationFrame(this.animationFrameTask)
|
|
|
},
|
|
@@ -418,45 +290,7 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
onClickPeopleNearHotSpot() {
|
|
|
- if (this.tourState !== 3) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 计算淡入过渡的起始终止位置
|
|
|
- this.treasureFadeInInitialLeft = this.$refs.treasure.offsetLeft
|
|
|
- this.treasureFadeInInitialTop = this.$refs.treasure.offsetTop
|
|
|
- this.treasureFadeInFinalLeft = window.innerWidth / 2 - this.$refs['people-near-wrap'].offsetLeft
|
|
|
- this.treasureFadeInFinalTop = window.innerHeight / 2 - this.$refs['people-near-wrap'].offsetTop
|
|
|
-
|
|
|
- // 计算淡入过渡终止时文物需要放大的倍数
|
|
|
- const viewportRatio = window.innerWidth / window.innerHeight
|
|
|
- const frameRatio = treasureFrameWidth / treasureFrameHeight
|
|
|
- if (viewportRatio >= frameRatio) { // 视口比序列帧扁,序列帧高度会缩放到和视口相同,所以序列帧的第一帧作为淡入时的文物图片,也缩放到和视口等高即可。
|
|
|
- this.treasureFinalHeightPercent = 100
|
|
|
- } else { // 视口比序列帧窄,序列帧宽度会缩放到和视口相同,所以序列帧的第一帧作为淡入时的文物图片,也缩放到和视口等宽即可。
|
|
|
- const treasureFinalHeight = treasureFrameHeight / treasureFrameWidth * window.innerWidth
|
|
|
- this.treasureFinalHeightPercent = treasureFinalHeight / window.innerHeight * 100
|
|
|
- }
|
|
|
-
|
|
|
- this.tourState = 0
|
|
|
- this.treasureFadeInTween.start()
|
|
|
- },
|
|
|
- onClickStopTreasureDisplay() {
|
|
|
- this.tourState = 3
|
|
|
- this.treasureFadeInTween.stop()
|
|
|
- this.treasureFadeOutTween.stop()
|
|
|
- this.$refs['treasure-serial-frames'].stop()
|
|
|
- if (this.$refs.treasure) {
|
|
|
- this.$refs.treasure.style.left = this.treasureFadeInInitialLeft + 'px'
|
|
|
- this.$refs.treasure.style.top = this.treasureFadeInInitialTop + 'px'
|
|
|
- this.$refs.treasure.style.transform = `translate(-50%, -50%) scale(1)`
|
|
|
- }
|
|
|
- },
|
|
|
- onTreasureFrameLoad(idx) {
|
|
|
- this.treasureFrameStateList[idx] = true
|
|
|
- },
|
|
|
- onTreasureFrameError(idx) {
|
|
|
- this.treasureFrameStateList[idx] = false
|
|
|
+ this.$refs['treasure-display'].startDisplay()
|
|
|
},
|
|
|
}
|
|
|
}
|
|
@@ -540,12 +374,7 @@ export default {
|
|
|
top: 29.5%;
|
|
|
z-index: 3;
|
|
|
}
|
|
|
- > .treasure {
|
|
|
- position: absolute;
|
|
|
- left: 49%;
|
|
|
- top: 32.5%;
|
|
|
- z-index: 2;
|
|
|
- transform: translate(-50%, -50%);
|
|
|
+ > .treasure-display {
|
|
|
}
|
|
|
}
|
|
|
.introduce {
|
|
@@ -553,35 +382,6 @@ export default {
|
|
|
top: 5%;
|
|
|
width: 13.727%;
|
|
|
}
|
|
|
- .fade-mask {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- background-color: #bfbfa7;
|
|
|
- z-index: 1;
|
|
|
- img {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- object-fit: contain;
|
|
|
- }
|
|
|
- }
|
|
|
- .btn-stop-treasure-display {
|
|
|
- position: absolute;
|
|
|
- top: 20px;
|
|
|
- right: 20px;
|
|
|
- z-index: 4;
|
|
|
- border: none;
|
|
|
- }
|
|
|
- .treasure-serial-frames {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- z-index: 3;
|
|
|
- }
|
|
|
@media screen and (max-height: 810px) {
|
|
|
.people-far-wrap {
|
|
|
height: 600px;
|