|
@@ -1,15 +1,16 @@
|
|
<template>
|
|
<template>
|
|
<div
|
|
<div
|
|
class="history-view"
|
|
class="history-view"
|
|
- @touchstart.passive="onTouchStart"
|
|
|
|
- @touchmove.passive="onTouchMove"
|
|
|
|
- @touchend="onTouchEnd"
|
|
|
|
- @touchcancel="onTouchCancel"
|
|
|
|
|
|
+ @mousedown.passive="onMouseDown"
|
|
|
|
+ @mousemove.passive="onMouseMove"
|
|
|
|
+ @mouseup="onMouseUp"
|
|
|
|
+ @mouseleave="onMouseLeave"
|
|
>
|
|
>
|
|
<video
|
|
<video
|
|
src="@/assets/videos/bg-history.mp4"
|
|
src="@/assets/videos/bg-history.mp4"
|
|
class="bg"
|
|
class="bg"
|
|
autoplay
|
|
autoplay
|
|
|
|
+ loop
|
|
/>
|
|
/>
|
|
<div
|
|
<div
|
|
class="gear-wrap"
|
|
class="gear-wrap"
|
|
@@ -22,7 +23,10 @@
|
|
draggable="false"
|
|
draggable="false"
|
|
>
|
|
>
|
|
</div>
|
|
</div>
|
|
- <div class="current-stage-name">
|
|
|
|
|
|
+ <div
|
|
|
|
+ v-if="currentTimeIdx !== null"
|
|
|
|
+ class="current-stage-name"
|
|
|
|
+ >
|
|
<h1>{{ stageList[currentTimeIdx].name }}</h1>
|
|
<h1>{{ stageList[currentTimeIdx].name }}</h1>
|
|
<img
|
|
<img
|
|
class="underline"
|
|
class="underline"
|
|
@@ -66,12 +70,12 @@
|
|
left: stageLabel.left + 'px',
|
|
left: stageLabel.left + 'px',
|
|
}"
|
|
}"
|
|
>
|
|
>
|
|
- {{ stageLabel.name }}
|
|
|
|
|
|
+ {{ stageLabel.startTime }}
|
|
<img
|
|
<img
|
|
draggable="false"
|
|
draggable="false"
|
|
src="@/assets/images/star.png"
|
|
src="@/assets/images/star.png"
|
|
alt=""
|
|
alt=""
|
|
- class="star"
|
|
|
|
|
|
+ class="star animation-show-hide"
|
|
>
|
|
>
|
|
</div>
|
|
</div>
|
|
<HistoryPersonCard
|
|
<HistoryPersonCard
|
|
@@ -86,6 +90,7 @@
|
|
left: item.left + 'px',
|
|
left: item.left + 'px',
|
|
top: item.top + 'px',
|
|
top: item.top + 'px',
|
|
zIndex: item.zIndex,
|
|
zIndex: item.zIndex,
|
|
|
|
+ filter: item.filter,
|
|
}"
|
|
}"
|
|
/>
|
|
/>
|
|
</div>
|
|
</div>
|
|
@@ -109,64 +114,64 @@ export default {
|
|
name: '开埠通商',
|
|
name: '开埠通商',
|
|
startTime: '1843',
|
|
startTime: '1843',
|
|
endTime: '1894',
|
|
endTime: '1894',
|
|
- startTimeFriendly: '十九世纪四十年代',
|
|
|
|
- endTimeFriendly: '十九世纪九十年代',
|
|
|
|
|
|
+ startTimeFriendly: '19世纪40年代',
|
|
|
|
+ endTimeFriendly: '19世纪90年代',
|
|
components: '上海近代工业蹒跚起步',
|
|
components: '上海近代工业蹒跚起步',
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: '曲折发展',
|
|
name: '曲折发展',
|
|
startTime: '1895',
|
|
startTime: '1895',
|
|
endTime: '1936',
|
|
endTime: '1936',
|
|
- startTimeFriendly: '十九世纪九十年代',
|
|
|
|
- endTimeFriendly: '二十世纪三十年代',
|
|
|
|
|
|
+ startTimeFriendly: '19世纪90年代',
|
|
|
|
+ endTimeFriendly: '20世纪30年代',
|
|
components: '上海近代工业起起伏伏',
|
|
components: '上海近代工业起起伏伏',
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: '步履维艰',
|
|
name: '步履维艰',
|
|
startTime: '1937',
|
|
startTime: '1937',
|
|
endTime: '1949',
|
|
endTime: '1949',
|
|
- startTimeFriendly: '二十世纪三十年代',
|
|
|
|
- endTimeFriendly: '二十世纪五十年代',
|
|
|
|
|
|
+ startTimeFriendly: '20世纪30年代',
|
|
|
|
+ endTimeFriendly: '20世纪50年代',
|
|
components: '上海民族工业几经崩溃',
|
|
components: '上海民族工业几经崩溃',
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: '筚路蓝缕',
|
|
name: '筚路蓝缕',
|
|
startTime: '1950',
|
|
startTime: '1950',
|
|
endTime: '1978',
|
|
endTime: '1978',
|
|
- startTimeFriendly: '二十世纪五十年代',
|
|
|
|
- endTimeFriendly: '二十世纪七十年代',
|
|
|
|
|
|
+ startTimeFriendly: '20世纪50年代',
|
|
|
|
+ endTimeFriendly: '20世纪70年代',
|
|
components: '上海现代工业扬帆起航',
|
|
components: '上海现代工业扬帆起航',
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: '改革开放',
|
|
name: '改革开放',
|
|
startTime: '1979',
|
|
startTime: '1979',
|
|
endTime: '1996',
|
|
endTime: '1996',
|
|
- startTimeFriendly: '二十世纪七十年代',
|
|
|
|
- endTimeFriendly: '二十世纪九十年代',
|
|
|
|
|
|
+ startTimeFriendly: '20世纪70年代',
|
|
|
|
+ endTimeFriendly: '20世纪90年代',
|
|
components: '上海工业凤凰涅槃',
|
|
components: '上海工业凤凰涅槃',
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: '战略负重',
|
|
name: '战略负重',
|
|
startTime: '1997',
|
|
startTime: '1997',
|
|
endTime: '2011',
|
|
endTime: '2011',
|
|
- startTimeFriendly: '二十世纪九十年代',
|
|
|
|
- endTimeFriendly: '本世纪一十年代',
|
|
|
|
|
|
+ startTimeFriendly: '20世纪90年代',
|
|
|
|
+ endTimeFriendly: '本世纪10年代',
|
|
components: '上海工业筑梦前行',
|
|
components: '上海工业筑梦前行',
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: '创新驱动',
|
|
name: '创新驱动',
|
|
startTime: '2012',
|
|
startTime: '2012',
|
|
endTime: '2020',
|
|
endTime: '2020',
|
|
- startTimeFriendly: '本世纪一十年代',
|
|
|
|
- endTimeFriendly: '本世纪二十年代',
|
|
|
|
|
|
+ startTimeFriendly: '本世纪10年代',
|
|
|
|
+ endTimeFriendly: '本世纪20年代',
|
|
components: '上海工业转型升级',
|
|
components: '上海工业转型升级',
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: '追梦未来',
|
|
name: '追梦未来',
|
|
startTime: '2021',
|
|
startTime: '2021',
|
|
endTime: '2035',
|
|
endTime: '2035',
|
|
- startTimeFriendly: '本世纪二十年代',
|
|
|
|
- endTimeFriendly: '本世纪三十年代',
|
|
|
|
|
|
+ startTimeFriendly: '本世纪20年代',
|
|
|
|
+ endTimeFriendly: '本世纪30年代',
|
|
components: '上海工业再创辉煌',
|
|
components: '上海工业再创辉煌',
|
|
},
|
|
},
|
|
])
|
|
])
|
|
@@ -194,7 +199,6 @@ export default {
|
|
api.getHistoryDetail(personItem.id).then((res) => {
|
|
api.getHistoryDetail(personItem.id).then((res) => {
|
|
try {
|
|
try {
|
|
personItem.img = process.env.VUE_APP_API_ORIGIN + res.file[0].filePath
|
|
personItem.img = process.env.VUE_APP_API_ORIGIN + res.file[0].filePath
|
|
- console.log(personItem.img)
|
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
console.log(e)
|
|
console.log(e)
|
|
}
|
|
}
|
|
@@ -202,7 +206,6 @@ export default {
|
|
}
|
|
}
|
|
})
|
|
})
|
|
})).then((res) => {
|
|
})).then((res) => {
|
|
- console.log(stageList)
|
|
|
|
// 计算各个时代的起始终止位置
|
|
// 计算各个时代的起始终止位置
|
|
let temp = 0
|
|
let temp = 0
|
|
for (const stageItem of stageList) {
|
|
for (const stageItem of stageList) {
|
|
@@ -210,13 +213,13 @@ export default {
|
|
stageItem.endPos = temp + stageItem.width
|
|
stageItem.endPos = temp + stageItem.width
|
|
temp = stageItem.endPos
|
|
temp = stageItem.endPos
|
|
}
|
|
}
|
|
- maxTranslateLength.value = stageList[stageList.length - 1].endPos - window.innerWidth / 2
|
|
|
|
|
|
+ maxTranslateLength.value = stageList[stageList.length - 1].endPos + window.innerWidth / 5
|
|
})
|
|
})
|
|
|
|
|
|
// 用户操作相关
|
|
// 用户操作相关
|
|
const isMouseDown = ref(false)
|
|
const isMouseDown = ref(false)
|
|
const lastMoveEventTimeStamp = ref(0)
|
|
const lastMoveEventTimeStamp = ref(0)
|
|
- const lastTouchPos = ref(0)
|
|
|
|
|
|
+ const lastCursorPos = ref(0)
|
|
|
|
|
|
// 镜头平移相关
|
|
// 镜头平移相关
|
|
const moveSpeed = ref(0)
|
|
const moveSpeed = ref(0)
|
|
@@ -224,33 +227,61 @@ export default {
|
|
const maxTranslateLength = ref(0)
|
|
const maxTranslateLength = ref(0)
|
|
|
|
|
|
// 用户操作改变镜头平移速度
|
|
// 用户操作改变镜头平移速度
|
|
- function onTouchStart(e) {
|
|
|
|
|
|
+ function onMouseDown(e) {
|
|
isMouseDown.value = true
|
|
isMouseDown.value = true
|
|
moveSpeed.value = 0
|
|
moveSpeed.value = 0
|
|
lastMoveEventTimeStamp.value = 0
|
|
lastMoveEventTimeStamp.value = 0
|
|
lastAnimationTimeStamp = Date.now()
|
|
lastAnimationTimeStamp = Date.now()
|
|
- lastTouchPos.value = e.changedTouches[0].clientX
|
|
|
|
|
|
+ lastCursorPos.value = e.clientX
|
|
|
|
+ if (beginAutoMoveIntervalId) {
|
|
|
|
+ clearInterval(beginAutoMoveIntervalId)
|
|
|
|
+ beginAutoMoveIntervalId = null
|
|
|
|
+ }
|
|
|
|
+ if (isAutoMoving.value) {
|
|
|
|
+ isAutoMoving.value = false
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- function onTouchEnd(e) {
|
|
|
|
|
|
+ function onMouseUp(e) {
|
|
isMouseDown.value = false
|
|
isMouseDown.value = false
|
|
|
|
+ beginAutoMoveIntervalId = setInterval(() => {
|
|
|
|
+ if (moveSpeed.value === 0) {
|
|
|
|
+ isAutoMoving.value = true
|
|
|
|
+ }
|
|
|
|
+ }, 2000)
|
|
}
|
|
}
|
|
- function onTouchCancel() {
|
|
|
|
|
|
+ function onMouseLeave() {
|
|
isMouseDown.value = false
|
|
isMouseDown.value = false
|
|
}
|
|
}
|
|
- function onTouchMove(e) {
|
|
|
|
- if (isMouseDown.value && e.changedTouches.length === 1) {
|
|
|
|
|
|
+ function onMouseMove(e) {
|
|
|
|
+ if (isMouseDown.value) {
|
|
// 疯狂操作的极端情况下两个时间戳之间的时差会不合理,甚至为0
|
|
// 疯狂操作的极端情况下两个时间戳之间的时差会不合理,甚至为0
|
|
if (lastMoveEventTimeStamp.value && (e.timeStamp - lastMoveEventTimeStamp.value > 1)) {
|
|
if (lastMoveEventTimeStamp.value && (e.timeStamp - lastMoveEventTimeStamp.value > 1)) {
|
|
// 更新speed
|
|
// 更新speed
|
|
- const currentMoveSpeed = - (e.changedTouches[0].clientX - lastTouchPos.value) / (e.timeStamp - lastMoveEventTimeStamp.value) * 1
|
|
|
|
|
|
+ const currentMoveSpeed = - (e.clientX - lastCursorPos.value) / (e.timeStamp - lastMoveEventTimeStamp.value) * 1
|
|
moveSpeed.value = moveSpeed.value * 0.9 + currentMoveSpeed * 0.1
|
|
moveSpeed.value = moveSpeed.value * 0.9 + currentMoveSpeed * 0.1
|
|
- lastTouchPos.value = e.changedTouches[0].clientX
|
|
|
|
|
|
+ lastCursorPos.value = e.clientX
|
|
}
|
|
}
|
|
lastMoveEventTimeStamp.value = e.timeStamp
|
|
lastMoveEventTimeStamp.value = e.timeStamp
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * 镜头自动平移
|
|
|
|
+ */
|
|
|
|
+ let isAutoMoving = ref(false)
|
|
|
|
+ let beginAutoMoveIntervalId = null
|
|
|
|
+ watch(isAutoMoving, (vNew) => {
|
|
|
|
+ if (vNew) {
|
|
|
|
+ moveSpeed.value = 0.03
|
|
|
|
+ } else {
|
|
|
|
+ moveSpeed.value = 0
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ onBeforeUnmount(() => {
|
|
|
|
+ clearInterval(beginAutoMoveIntervalId)
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ /**
|
|
* 动画帧相关
|
|
* 动画帧相关
|
|
*/
|
|
*/
|
|
let lastAnimationTimeStamp = 0
|
|
let lastAnimationTimeStamp = 0
|
|
@@ -259,28 +290,33 @@ export default {
|
|
function animationFrameTask() {
|
|
function animationFrameTask() {
|
|
const timeStamp = Date.now()
|
|
const timeStamp = Date.now()
|
|
const timeElapsed = timeStamp - lastAnimationTimeStamp
|
|
const timeElapsed = timeStamp - lastAnimationTimeStamp
|
|
-
|
|
|
|
- // 速度减慢
|
|
|
|
- if (moveSpeed.value > 0) {
|
|
|
|
- moveSpeed.value -= ($.valueisMobile ? 0.001 : 0.003) * timeElapsed
|
|
|
|
- if (moveSpeed.value < 0) {
|
|
|
|
- moveSpeed.value = 0
|
|
|
|
- }
|
|
|
|
- } else if (moveSpeed.value < 0) {
|
|
|
|
- moveSpeed.value += ($.valueisMobile ? 0.001 : 0.003) * timeElapsed
|
|
|
|
|
|
+ if (!isAutoMoving.value) {
|
|
|
|
+ // 速度减慢
|
|
if (moveSpeed.value > 0) {
|
|
if (moveSpeed.value > 0) {
|
|
- moveSpeed.value = 0
|
|
|
|
|
|
+ moveSpeed.value -= ($.valueisMobile ? 0.001 : 0.003) * timeElapsed
|
|
|
|
+ if (moveSpeed.value < 0) {
|
|
|
|
+ moveSpeed.value = 0
|
|
|
|
+ }
|
|
|
|
+ } else if (moveSpeed.value < 0) {
|
|
|
|
+ moveSpeed.value += ($.valueisMobile ? 0.001 : 0.003) * timeElapsed
|
|
|
|
+ if (moveSpeed.value > 0) {
|
|
|
|
+ moveSpeed.value = 0
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// 根据速度更新位置
|
|
// 根据速度更新位置
|
|
translateLength.value += moveSpeed.value * timeElapsed
|
|
translateLength.value += moveSpeed.value * timeElapsed
|
|
- if (translateLength.value < 0) {
|
|
|
|
- translateLength.value = 0
|
|
|
|
|
|
+ if (translateLength.value < - window.innerWidth / 2) {
|
|
|
|
+ translateLength.value = - window.innerWidth / 2
|
|
moveSpeed.value = 0
|
|
moveSpeed.value = 0
|
|
} else if (translateLength.value > maxTranslateLength.value) {
|
|
} else if (translateLength.value > maxTranslateLength.value) {
|
|
- translateLength.value = maxTranslateLength.value
|
|
|
|
- moveSpeed.value = 0
|
|
|
|
|
|
+ if (isAutoMoving.value) {
|
|
|
|
+ translateLength.value = -window.innerWidth / 2
|
|
|
|
+ } else {
|
|
|
|
+ translateLength.value = maxTranslateLength.value
|
|
|
|
+ moveSpeed.value = 0
|
|
|
|
+ }
|
|
}
|
|
}
|
|
lastAnimationTimeStamp = timeStamp
|
|
lastAnimationTimeStamp = timeStamp
|
|
animationFrameId = requestAnimationFrame(animationFrameTask)
|
|
animationFrameId = requestAnimationFrame(animationFrameTask)
|
|
@@ -309,6 +345,8 @@ export default {
|
|
if (vNew >= (stageItem.startPos - window.innerWidth / 7) && vNew <= (stageItem.endPos - window.innerWidth / 7)) {
|
|
if (vNew >= (stageItem.startPos - window.innerWidth / 7) && vNew <= (stageItem.endPos - window.innerWidth / 7)) {
|
|
currentTimeIdx.value = index
|
|
currentTimeIdx.value = index
|
|
break
|
|
break
|
|
|
|
+ } else {
|
|
|
|
+ currentTimeIdx.value = null
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
})
|
|
@@ -334,7 +372,11 @@ export default {
|
|
const translateLengthPerGrearFrame = (timeAxisScaleWidth + timeAxisScaleMargin) / gearFrameNumberPerScale
|
|
const translateLengthPerGrearFrame = (timeAxisScaleWidth + timeAxisScaleMargin) / gearFrameNumberPerScale
|
|
watch(translateLength, (vNew) => {
|
|
watch(translateLength, (vNew) => {
|
|
const framePassed = Math.round(translateLength.value / translateLengthPerGrearFrame)
|
|
const framePassed = Math.round(translateLength.value / translateLengthPerGrearFrame)
|
|
- gearFrameIdx.value = framePassed % gearFrameNumberTotal
|
|
|
|
|
|
+ if (framePassed >= 0) {
|
|
|
|
+ gearFrameIdx.value = framePassed % gearFrameNumberTotal
|
|
|
|
+ } else {
|
|
|
|
+ gearFrameIdx.value = gearFrameNumberTotal + framePassed % gearFrameNumberTotal - 1
|
|
|
|
+ }
|
|
})
|
|
})
|
|
|
|
|
|
// 各个时代标签
|
|
// 各个时代标签
|
|
@@ -345,6 +387,7 @@ export default {
|
|
name: item.name,
|
|
name: item.name,
|
|
initialLeft: (item.startPos + 10) * 3,
|
|
initialLeft: (item.startPos + 10) * 3,
|
|
left: (item.startPos + 10) * 3,
|
|
left: (item.startPos + 10) * 3,
|
|
|
|
+ startTime: item.startTime + '年',
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
return undefined
|
|
return undefined
|
|
@@ -373,6 +416,7 @@ export default {
|
|
top: Math.random() * 70 + (tallOrFat === 'tall' ? 200 : 350),
|
|
top: Math.random() * 70 + (tallOrFat === 'tall' ? 200 : 350),
|
|
tallOrFat,
|
|
tallOrFat,
|
|
zIndex: tallOrFat === 'tall' ? 5 : 4,
|
|
zIndex: tallOrFat === 'tall' ? 5 : 4,
|
|
|
|
+ filter: `brightness(${tallOrFat === 'tall' ? '1' : '0.75'})`,
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -387,10 +431,10 @@ export default {
|
|
|
|
|
|
|
|
|
|
return {
|
|
return {
|
|
- onTouchStart,
|
|
|
|
- onTouchEnd,
|
|
|
|
- onTouchCancel,
|
|
|
|
- onTouchMove,
|
|
|
|
|
|
+ onMouseDown,
|
|
|
|
+ onMouseMove,
|
|
|
|
+ onMouseUp,
|
|
|
|
+ onMouseLeave,
|
|
timeAxisLeft,
|
|
timeAxisLeft,
|
|
timeAxisScaleWidth,
|
|
timeAxisScaleWidth,
|
|
timeAxisScaleMargin,
|
|
timeAxisScaleMargin,
|
|
@@ -413,6 +457,7 @@ export default {
|
|
top: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
width: 100%;
|
|
height: 100%;
|
|
height: 100%;
|
|
|
|
+ user-select: none;
|
|
>video.bg{
|
|
>video.bg{
|
|
position: absolute;
|
|
position: absolute;
|
|
left: 0;
|
|
left: 0;
|
|
@@ -434,7 +479,7 @@ export default {
|
|
>.current-stage-name {
|
|
>.current-stage-name {
|
|
position: absolute;
|
|
position: absolute;
|
|
left: 50%;
|
|
left: 50%;
|
|
- top: 150px;
|
|
|
|
|
|
+ top: 10.5vw;
|
|
transform: translateX(-50%);
|
|
transform: translateX(-50%);
|
|
width: 250px;
|
|
width: 250px;
|
|
text-align: center;
|
|
text-align: center;
|
|
@@ -467,9 +512,10 @@ export default {
|
|
font-weight: bold;
|
|
font-weight: bold;
|
|
color: #FFFFFF;
|
|
color: #FFFFFF;
|
|
line-height: 97px;
|
|
line-height: 97px;
|
|
- white-space: pre;
|
|
|
|
text-shadow: 10px 0px 0 black;
|
|
text-shadow: 10px 0px 0 black;
|
|
z-index: 10;
|
|
z-index: 10;
|
|
|
|
+ width: 407px;
|
|
|
|
+ text-align: left;
|
|
>img.star{
|
|
>img.star{
|
|
position: absolute;
|
|
position: absolute;
|
|
left: 0;
|
|
left: 0;
|