HomeView.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <div
  3. class="home"
  4. draggable="false"
  5. @mousedown="onMouseDown"
  6. @mousemove="onMouseMove"
  7. @mouseup="onMouseUp"
  8. @wheel.passive="onWheel"
  9. >
  10. <img
  11. class="landscape"
  12. src="@/assets/landscape.png"
  13. alt=""
  14. draggable="false"
  15. >
  16. <div
  17. class="people-far"
  18. :style="{
  19. right: peopleFarPositionRight,
  20. }"
  21. >
  22. <img
  23. src="@/assets/people-far.png"
  24. alt=""
  25. draggable="false"
  26. >
  27. </div>
  28. <div
  29. class="people-near"
  30. :style="{
  31. right: peopleNearPositionRight,
  32. }"
  33. >
  34. <img
  35. class="peopleNearSerialFrames"
  36. :class="peopleNearColorStatus"
  37. src="@/assets/people-near-serial-frame.png"
  38. alt=""
  39. draggable="false"
  40. >
  41. <HotSpot
  42. class="hot-spot"
  43. @click="onClickPeopleNearHotSpot"
  44. />
  45. </div>
  46. <img
  47. class="introduce"
  48. :style="{
  49. left: introducePositionLeft,
  50. }"
  51. src="@/assets/introduce.png"
  52. alt=""
  53. draggable="false"
  54. >
  55. </div>
  56. </template>
  57. <script>
  58. export default {
  59. name: 'HomeView',
  60. components: {
  61. },
  62. data() {
  63. return {
  64. landscapePositionRight: '-50%',
  65. peopleFarPositionRight: '0px',
  66. peopleNearPositionRight: '-30%',
  67. introducePositionLeft: '2%',
  68. translateLength: 0,
  69. isMouseDown: false,
  70. moveSpeed: 0,
  71. lastMoveEventTimeStamp: 0,
  72. lastAnimationTimeStamp: 0,
  73. animationFrameId: null,
  74. peopleNearColorStatus: 'no-color', // 'no-color', 'color'
  75. isPeopleNearColorChanging: false,
  76. }
  77. },
  78. watch: {
  79. translateLength: {
  80. handler(v) {
  81. console.log(v)
  82. if (v > 0) {
  83. v = 0
  84. this.translateLength = v
  85. this.moveSpeed = 0
  86. } else if (v < -window.innerWidth * 2) {
  87. v = -window.innerWidth * 2
  88. this.translateLength = v
  89. this.moveSpeed = 0
  90. }
  91. this.peopleFarPositionRight = `calc(0px - ${v * 0.2}px)`
  92. this.peopleNearPositionRight = `calc(-30% - ${v * 0.8}px)`
  93. this.introducePositionLeft = `calc(2% + ${v * 1}px)`
  94. }
  95. }
  96. },
  97. mounted() {
  98. this.animationFrameId = requestAnimationFrame(this.inertanceEffect)
  99. },
  100. unmounted() {
  101. cancelAnimationFrame(this.animationFrameId)
  102. },
  103. methods: {
  104. onMouseDown(e) {
  105. this.isMouseDown = true
  106. this.moveSpeed = 0
  107. this.lastMoveEventTimeStamp = 0
  108. this.lastAnimationTimeStamp = Date.now()
  109. },
  110. onMouseUp(e) {
  111. this.isMouseDown = false
  112. },
  113. onMouseMove(e) {
  114. if (this.isMouseDown) {
  115. if (this.lastMoveEventTimeStamp) {
  116. const currentMoveSpeed = e.movementX / (e.timeStamp - this.lastMoveEventTimeStamp)
  117. this.moveSpeed = this.moveSpeed * 0.9 + currentMoveSpeed * 0.1
  118. }
  119. this.lastMoveEventTimeStamp = e.timeStamp
  120. }
  121. },
  122. onWheel(e) {
  123. this.translateLength -= e.deltaY
  124. },
  125. inertanceEffect() {
  126. const timeStamp = Date.now()
  127. const timeElapsed = timeStamp - this.lastAnimationTimeStamp
  128. if (this.moveSpeed > 0) {
  129. this.moveSpeed -= 0.003 * timeElapsed
  130. if (this.moveSpeed < 0) {
  131. this.moveSpeed = 0
  132. }
  133. } else if (this.moveSpeed < 0) {
  134. this.moveSpeed += 0.003 * timeElapsed
  135. if (this.moveSpeed > 0) {
  136. this.moveSpeed = 0
  137. }
  138. }
  139. this.translateLength += this.moveSpeed * timeElapsed
  140. this.lastAnimationTimeStamp = timeStamp
  141. this.animationFrameId = requestAnimationFrame(this.inertanceEffect)
  142. },
  143. onClickPeopleNearHotSpot() {
  144. if (this.isPeopleNearColorChanging) {
  145. return
  146. } else {
  147. if (this.peopleNearColorStatus === 'no-color') {
  148. this.peopleNearColorStatus = 'color'
  149. } else {
  150. this.peopleNearColorStatus = 'no-color'
  151. }
  152. this.isPeopleNearColorChanging = true
  153. setTimeout(() => {
  154. this.isPeopleNearColorChanging = false
  155. }, 2500)
  156. }
  157. }
  158. }
  159. }
  160. </script>
  161. <style lang="less" scoped>
  162. .home {
  163. width: 100%;
  164. height: 100%;
  165. background-image: url(@/assets/background.jpg);
  166. background-repeat: repeat;
  167. background-size: contain;
  168. position: relative;
  169. overflow: hidden;
  170. .landscape {
  171. height: 30%;
  172. position: absolute;
  173. top: 0;
  174. right: 0;
  175. }
  176. .people-far {
  177. position: absolute;
  178. top: 20%;
  179. height: 60%;
  180. > img {
  181. height: 100%;
  182. }
  183. }
  184. .people-near {
  185. position: absolute;
  186. bottom: 0;
  187. width: 600px;
  188. height: 800px;
  189. transform: scale(calc(90vh / 800px));
  190. overflow: hidden;
  191. > .hot-spot {
  192. position: absolute;
  193. left: 50%;
  194. transform: translateX(-50%);
  195. top: 15%;
  196. }
  197. > .peopleNearSerialFrames {
  198. position: absolute;
  199. height: 100%;
  200. transition-property: left;
  201. transition-duration: 2.5s;
  202. transition-timing-function: steps(59, jump-end);
  203. &.no-color {
  204. left: 0;
  205. }
  206. &.color {
  207. left: calc(-100% * 59)
  208. }
  209. }
  210. }
  211. .introduce {
  212. position: absolute;
  213. top: 5%;
  214. }
  215. }
  216. </style>