فهرست منبع

Merge branch 'master' into local-deploy

任一存 3 سال پیش
والد
کامیت
ed68dc641e
49فایلهای تغییر یافته به همراه597 افزوده شده و 215 حذف شده
  1. 1 1
      .eslintrc.js
  2. 40 0
      README.md
  3. 11 0
      package-lock.json
  4. 1 0
      package.json
  5. 9 0
      public/index.html
  6. 9 7
      src/App.vue
  7. BIN
      src/assets/image/fruits/万水千山.png
  8. BIN
      src/assets/image/fruits/世界巨匠.png
  9. BIN
      src/assets/image/fruits/从毕加索.png
  10. BIN
      src/assets/image/fruits/仰之弥高.png
  11. BIN
      src/assets/image/fruits/兄弟王.png
  12. BIN
      src/assets/image/fruits/南腔北调.png
  13. BIN
      src/assets/image/fruits/呼吸.png
  14. BIN
      src/assets/image/fruits/和合.png
  15. BIN
      src/assets/image/fruits/回家过年.png
  16. BIN
      src/assets/image/fruits/在此.png
  17. BIN
      src/assets/image/fruits/宋韵.png
  18. BIN
      src/assets/image/fruits/家国.png
  19. BIN
      src/assets/image/fruits/帝国盛世.png
  20. BIN
      src/assets/image/fruits/晶华.png
  21. BIN
      src/assets/image/fruits/暑期.png
  22. BIN
      src/assets/image/fruits/法老王.png
  23. BIN
      src/assets/image/fruits/浮世绘.png
  24. BIN
      src/assets/image/fruits/温婉.png
  25. BIN
      src/assets/image/fruits/百花呈瑞.png
  26. BIN
      src/assets/image/fruits/称霸侏罗纪.png
  27. BIN
      src/assets/image/fruits/穆夏.png
  28. BIN
      src/assets/image/fruits/缀白裘.png
  29. BIN
      src/assets/image/fruits/考古江苏.png
  30. BIN
      src/assets/image/fruits/藏品架起沟通的桥梁.png
  31. BIN
      src/assets/image/fruits/融合.png
  32. BIN
      src/assets/image/fruits/走进.png
  33. BIN
      src/assets/image/fruits/金色中国.png
  34. BIN
      src/assets/image/fruits/金色阿富汗.png
  35. BIN
      src/assets/image/fruits/青藤.png
  36. BIN
      src/assets/image/slide-tip-hand.png
  37. BIN
      src/assets/image/tall-tree-for-computing-height.jpg
  38. BIN
      src/assets/image/tall-tree-no-fruit.png
  39. 4 0
      src/assets/style/reset.css
  40. 45 13
      src/components/SlideTip.vue
  41. 1 1
      src/main.js
  42. 10 38
      src/utils.js
  43. 8 9
      src/views/Chart.vue
  44. 7 0
      src/views/End.vue
  45. 5 9
      src/views/Home.vue
  46. 436 129
      src/views/TreeAnimation.vue
  47. 4 7
      src/views/TreeSelection.vue
  48. 1 1
      vue.config.js
  49. 5 0
      yarn.lock

+ 1 - 1
.eslintrc.js

@@ -41,7 +41,7 @@ module.exports = {
     // config: true,
     // mapGetters: true,
     // store: true,
-    // utils: true,
+    utils: true,
     Hammer: true,
   }
 }

+ 40 - 0
README.md

@@ -22,3 +22,43 @@ yarn lint
 
 ### Customize configuration
 See [Configuration Reference](https://cli.vuejs.org/config/).
+
+
+# change log
+
+## 移动端
+
+### v2.0
+* 切换页面操作改为下滑,页面间过渡动效改为由上至下,改变滑动提示视觉效果,防止下滑触发浏览器的下拉刷新机制。
+* 树长图页操作方式改为手动滑动,展览标签淡入,点击标签跳转至展览详情页,返回树生长页后回恢复上次的滚动位置。
+
+### v.1.3
+* 功能bug修复:树长图页 安卓机微信内置浏览器里位移距离异常的问题。
+* 操作优化:chart页可触发下滑翻页的范围增加到全页。
+* 代码整理:删除冗余文件。
+* 新功能:引入百度统计脚本。
+
+### v1.2
+* 功能bug修复:展览资料列表页 “缀白裘—南京博物院<br>藏品征集十年”无法展示视频封面的问题。
+* 功能bug修复:结尾页 ios15.0上视频无法播放的问题。
+* 功能bug修复:展览资料页 ios15.0上图片无法全屏显示的问题。
+* 视觉优化:展览资料列表页 页面略高于窗口导致出现滚动条的问题。
+* 视觉优化:展览资料列表页 关闭按钮太小导致手指难以点中的问题。
+* 操作优化:全局 增加一重禁止页面缩放操作的措施(只在部分设备上有效)。
+
+### v1.0.h5
+
+## 一体机端
+
+### v.1.3.local
+换一种禁用二指缩放的方案。
+
+### v1.2.local
+* 功能bug修复:展览资料列表页 “缀白裘—南京博物院<br>藏品征集十年”无法展示视频封面的问题。
+* 功能bug修复:结尾页 ios15.0上视频无法播放的问题。
+* 功能bug修复:展览资料页 ios15.0上图片无法全屏显示的问题。
+* 视觉优化:展览资料列表页 页面略高于窗口导致出现滚动条的问题。
+* 视觉优化:展览资料列表页 关闭按钮太小导致手指难以点中的问题。
+* 操作优化:全局 增加一重禁止页面缩放操作的措施(只在部分设备上有效)。
+
+### v1.0.local

+ 11 - 0
package-lock.json

@@ -14,6 +14,7 @@
         "less": "3.0.4",
         "less-loader": "^5.0.0",
         "vant": "^2.12.47",
+        "vissense": "^0.10.0",
         "vue": "^2.6.11",
         "vue-router": "^3.2.0",
         "vuex": "^3.0.0"
@@ -14859,6 +14860,11 @@
       ],
       "license": "MIT"
     },
+    "node_modules/vissense": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmmirror.com/vissense/-/vissense-0.10.0.tgz",
+      "integrity": "sha512-3q+c/45KBfrFssEsNb9eYw1Ewyw5Sj0m3W95a0kXthEx6/XVnkJ2K4CSVGjl3aprCi0rXdYjoKAoFb9Jl6HyIw=="
+    },
     "node_modules/vm-browserify": {
       "version": "1.1.2",
       "resolved": "https://registry.npmmirror.com/vm-browserify/-/vm-browserify-1.1.2.tgz",
@@ -26655,6 +26661,11 @@
         }
       }
     },
+    "vissense": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmmirror.com/vissense/-/vissense-0.10.0.tgz",
+      "integrity": "sha512-3q+c/45KBfrFssEsNb9eYw1Ewyw5Sj0m3W95a0kXthEx6/XVnkJ2K4CSVGjl3aprCi0rXdYjoKAoFb9Jl6HyIw=="
+    },
     "vm-browserify": {
       "version": "1.1.2",
       "resolved": "https://registry.npmmirror.com/vm-browserify/-/vm-browserify-1.1.2.tgz",

+ 1 - 0
package.json

@@ -14,6 +14,7 @@
     "less": "3.0.4",
     "less-loader": "^5.0.0",
     "vant": "^2.12.47",
+    "vissense": "^0.10.0",
     "vue": "^2.6.11",
     "vue-router": "^3.2.0",
     "vuex": "^3.0.0"

+ 9 - 0
public/index.html

@@ -7,6 +7,15 @@
     <link rel="icon" href="<%= BASE_URL %>icon.jpg">
     <title>5.18博物馆的力量--奔赴美好生活</title>
     <script src="<%= BASE_URL %>libs/hammer.js"></script>
+    <script>
+      var _hmt = _hmt || [];
+      (function() {
+        var hm = document.createElement("script");
+        hm.src = "https://hm.baidu.com/hm.js?6e780e50daf3be600389a15eb53860b5";
+        var s = document.getElementsByTagName("script")[0]; 
+        s.parentNode.insertBefore(hm, s);
+      })();
+      </script>
   </head>
   <body>
     <noscript>

+ 9 - 7
src/App.vue

@@ -7,7 +7,9 @@
       :name="transitionName"
       :mode="transitionMode"
     >
-      <router-view />
+      <keep-alive include="TreeAnimation">
+        <router-view />
+      </keep-alive>
     </transition>
     <img
       class="home-btn"
@@ -95,7 +97,7 @@ html,body{
 
 .slide-to-next-page-enter {
   position: fixed;
-  top: 100%;
+  bottom: 100%;
   left: 0;
   width: 100%;
   height: 100%;
@@ -103,19 +105,19 @@ html,body{
 
 .slide-to-next-page-enter-to {
   position: fixed;
-  top: 0;
+  bottom: 0;
   left: 0;
   width: 100%;
   height: 100%;
 }
 
 .slide-to-next-page-enter-active {
-  transition: top 1s;
+  transition: bottom 1s;
 }
 
 .slide-to-next-page-leave {
   position: fixed;
-  top: 0;
+  bottom: 0;
   left: 0;
   width: 100%;
   height: 100%;
@@ -123,14 +125,14 @@ html,body{
 
 .slide-to-next-page-leave-to {
   position: fixed;
-  top: -100%;
+  bottom: -100%;
   left: 0;
   width: 100%;
   height: 100%;
 }
 
 .slide-to-next-page-leave-active {
-  transition: top 1s;
+  transition: bottom 1s;
 }
 
 .fade-out-in-enter {

BIN
src/assets/image/fruits/万水千山.png


BIN
src/assets/image/fruits/世界巨匠.png


BIN
src/assets/image/fruits/从毕加索.png


BIN
src/assets/image/fruits/仰之弥高.png


BIN
src/assets/image/fruits/兄弟王.png


BIN
src/assets/image/fruits/南腔北调.png


BIN
src/assets/image/fruits/呼吸.png


BIN
src/assets/image/fruits/和合.png


BIN
src/assets/image/fruits/回家过年.png


BIN
src/assets/image/fruits/在此.png


BIN
src/assets/image/fruits/宋韵.png


BIN
src/assets/image/fruits/家国.png


BIN
src/assets/image/fruits/帝国盛世.png


BIN
src/assets/image/fruits/晶华.png


BIN
src/assets/image/fruits/暑期.png


BIN
src/assets/image/fruits/法老王.png


BIN
src/assets/image/fruits/浮世绘.png


BIN
src/assets/image/fruits/温婉.png


BIN
src/assets/image/fruits/百花呈瑞.png


BIN
src/assets/image/fruits/称霸侏罗纪.png


BIN
src/assets/image/fruits/穆夏.png


BIN
src/assets/image/fruits/缀白裘.png


BIN
src/assets/image/fruits/考古江苏.png


BIN
src/assets/image/fruits/藏品架起沟通的桥梁.png


BIN
src/assets/image/fruits/融合.png


BIN
src/assets/image/fruits/走进.png


BIN
src/assets/image/fruits/金色中国.png


BIN
src/assets/image/fruits/金色阿富汗.png


BIN
src/assets/image/fruits/青藤.png


BIN
src/assets/image/slide-tip-hand.png


BIN
src/assets/image/tall-tree-for-computing-height.jpg


BIN
src/assets/image/tall-tree-no-fruit.png


+ 4 - 0
src/assets/style/reset.css

@@ -53,4 +53,8 @@ table {
 button {
   padding: 0;
   cursor: pointer;
+}
+
+html {
+  overflow: hidden;
 }

+ 45 - 13
src/components/SlideTip.vue

@@ -1,12 +1,19 @@
 <template>
   <div class="slide-tip">
-    <div
-      class="slide-tip_text"
-      v-html="text"
-    />
+    <div class="twinkle-wrapper">
+      <div
+        class="slide-tip_text"
+        v-html="text"
+      />
+      <img
+        class="slide-tip_image"
+        src="@/assets/image/下拉.png"
+        alt=""
+      >
+    </div>
     <img
-      class="slide-tip_image"
-      src="@/assets/image/下拉.png"
+      src="@/assets/image/slide-tip-hand.png"
+      class="slide-tip_hand"
       alt=""
     >
   </div>
@@ -17,7 +24,7 @@ export default {
   props: {
     text: {
       type: String,
-      default: '文<br>脉'
+      default: ''
     }
   }
 }
@@ -29,16 +36,25 @@ export default {
   bottom: 6.17rem;
   left: 50%;
   transform: translateX(-50%);
-  animation: twinkle 2s infinite;
   font-size: 1.13rem;
   font-family: Source Han Sans CN;
   font-weight: 500;
   color: #18489D;
-  .slide-tip_image {
-    width: 0.94rem;
-    height: 2.47rem;
-    margin-top: 0.94rem;
-    transform: rotate(180deg);
+  > .twinkle-wrapper {
+    animation: twinkle 2s infinite;
+    > .slide-tip_text {
+    }
+    > .slide-tip_image {
+      width: 0.94rem;
+      height: 2.47rem;
+      margin-top: 0.94rem;
+    }
+  }
+  .slide-tip_hand {
+    position: absolute;
+    left: 50%;
+    width: 2.26rem;
+    animation: move-up-down 2.8s infinite;
   }
 }
 @keyframes twinkle {
@@ -55,4 +71,20 @@ export default {
     opacity: 0;
   }
 }
+@keyframes move-up-down {
+  0% {
+    top: 0;
+    opacity: 0;
+  }
+  25% {
+    opacity: 1;
+  }
+  60% {
+    opacity: 1;
+  }
+  100% {
+    top: 100%;
+    opacity: 0;
+  }
+}
 </style>

+ 1 - 1
src/main.js

@@ -1,4 +1,4 @@
-console.log('v1.2')
+console.log('v2.0')
 
 import Vue from 'vue'
 import App from './App.vue'

+ 10 - 38
src/utils.js

@@ -1,40 +1,12 @@
-function GetSlideDirection(startX, startY, endX, endY) {
-  var dy = startY - endY
-  //var dx = endX - startX;
-  var result = 0
-  if (dy > 0) {//向上滑动
-    result = 1
-  } else {//向下滑动
-    result = 2
-  }
-
-  return result
+function registerSlideToRoute(watchTargetRefName, routeDistName, vueCompContext) {
+  let mc = new Hammer(vueCompContext.$refs[watchTargetRefName])
+  mc.get('pan').set({ direction: Hammer.DIRECTION_ALL })
+  mc.on("pandown", function me(ev) {
+    mc.off('pandown', me)
+    vueCompContext.$router.push({ name: routeDistName })
+  })
 }
 
-//滑动处理
-var startX, startY
-document.addEventListener('touchstart',function (ev) {
-  startX = ev.touches[0].pageX
-  startY = ev.touches[0].pageY
-}, false)
-
-document.addEventListener('touchend',function (ev) {
-  var endX, endY
-  endX = ev.changedTouches[0].pageX
-  endY = ev.changedTouches[0].pageY
-  var direction = GetSlideDirection(startX, startY, endX, endY)
-  switch (direction) {
-  case 0:
-    break
-  case 1:
-    // 向上
-    alert("up")
-    break
-  case 2:
-    // 向下
-    alert("down")
-    break
-
-  default:
-  }
-}, false)
+export default {
+  registerSlideToRoute,
+}

+ 8 - 9
src/views/Chart.vue

@@ -383,13 +383,7 @@ export default {
       }
     }, 3000)
 
-    let mc = new Hammer(this.$refs['hammer-target'])
-    mc.get('pan').set({ direction: Hammer.DIRECTION_ALL })
-    const that = this
-    mc.on("panup", function me(ev) {
-      mc.off('panup', me)
-      that.$router.push({ name: 'End' })
-    })
+    utils.registerSlideToRoute('hammer-target', 'End', this)
   },
   destroyed() {
     this.chartHuodong.dispose()
@@ -690,6 +684,10 @@ export default {
   width: 100%;
   height: 100%;
   overflow: hidden;
+  .back-btn {
+    position: absolute;
+    z-index: 2;
+  }
   .picker {
     width: 7.08rem;
     height: 7.08rem;
@@ -699,6 +697,7 @@ export default {
     top: 6.92rem;
     left: calc(50% - 4.25rem);
     overflow: hidden;
+    z-index: 2;
   }
   .data-circle {
     position: absolute;
@@ -794,10 +793,10 @@ export default {
   }
   .slide-to-nav-mask {
     position: absolute;
-    width: 100%;
-    height: 65%;
+    top: 0;
     bottom: 0;
     left: 0;
+    right: 0;
     // background: red;
     z-index: 1;
   }

+ 7 - 0
src/views/End.vue

@@ -20,6 +20,13 @@ export default {
       showPlayBtn: false,
     }
   },
+  created() {
+  },
+  mounted() {
+  },
+  destroyed() {
+    clearInterval(this.intervalId)
+  },
   methods: {
     onPlay() {
       this.beganPlay = true

+ 5 - 9
src/views/Home.vue

@@ -35,7 +35,10 @@
       @load="onImgLoad(index - 1)"
       @error="onImgError(index - 1)"
     >
-    <SlideTip v-if="currentFrameIdx >= 20" />
+    <SlideTip
+      v-if="currentFrameIdx >= 20"
+      text="文<br>脉"
+    />
     <div class="bottom-wrapper">
       <img
         class="jiangsu"
@@ -71,14 +74,7 @@ export default {
     }
   },
   mounted() {
-    let mc = new Hammer(this.$refs['hammer-target'])
-    mc.get('pan').set({ direction: Hammer.DIRECTION_ALL })
-    const that = this
-    mc.on("panup", function me(ev) {
-      mc.off('panup', me)
-      console.log(ev)
-      that.$router.push({ name: 'TreeAnimation' })
-    })
+    utils.registerSlideToRoute('hammer-target', 'TreeAnimation', this)
 
     this.intervalId = setInterval(() => {
       if ((this.loadCountDown === 0)) {

+ 436 - 129
src/views/TreeAnimation.vue

@@ -5,19 +5,372 @@
   >
     <div
       v-show="showTree"
+      ref="img-wrapper"
       class="img-wrapper"
+      @scroll="onImgWrapperScroll"
     >
-      <img
-        id="tree-image"
-        src="@/assets/image/tall-tree.png"
-        alt=""
-        @load="onTreeImgLoad"
-      >
+      <div class="img-wrapper-tall">
+        <img
+          ref="tree-image"
+          class="tree-image"
+          src="@/assets/image/tall-tree-no-fruit.png"
+          alt=""
+          @load="onTreeImgLoad"
+        >
+        <!-- 各标签(果子)的代码顺序与显示顺序上下相反 -->
+        <img
+          src="@/assets/image/fruits/金色中国.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 2.5rem;
+            height: calc(10.16rem + 0.78rem);
+            left: 10.11rem;
+            top: calc(371.97rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 's')"
+        >
+        <img
+          src="@/assets/image/fruits/在此.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.89rem + 0.78rem);
+            left: 10.06rem;
+            top: calc(344.22rem - 0.78rem)
+          "
+          @click="onClickFruit('wuyiba', 'a')"
+        >
+        <img
+          src="@/assets/image/fruits/藏品架起沟通的桥梁.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.28rem + 0.78rem);
+            left: 9.52rem;
+            top: calc(323.53rem - 0.78rem)
+          "
+          @click="onClickFruit('wuyiba', 'f')"
+        >
+        <img
+          src="@/assets/image/fruits/温婉.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 2.5rem;
+            height: calc(10.28rem + 0.78rem);
+            left: 11.17rem;
+            top: calc(301.86rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'p')"
+        >
+        <img
+          src="@/assets/image/fruits/和合.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.92rem + 0.78rem);
+            left: 12.88rem;
+            top: calc(283.22rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'u')"
+        >
+        <img
+          src="@/assets/image/fruits/南腔北调.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(9.31rem + 0.78rem);
+            left: 7.14rem;
+            top: calc(282.41rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'oa')"
+        >
+        <img
+          src="@/assets/image/fruits/呼吸.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(9.89rem + 0.78rem);
+            left: 9.59rem;
+            top: calc(263.81rem - 0.78rem)
+          "
+          @click="onClickFruit('wuyiba', 'c')"
+        >
+        <img
+          src="@/assets/image/fruits/法老王.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.75rem;
+            height: calc(10.47rem + 0.78rem);
+            left: 7.34rem;
+            top: calc(244.69rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 't')"
+        >
+        <img
+          src="@/assets/image/fruits/缀白裘.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.59rem + 0.78rem);
+            left: 7.34rem;
+            top: calc(227.08rem - 0.78rem)
+          "
+          @click="onClickFruit('wuyiba', 'b')"
+        >
+        <img
+          src="@/assets/image/fruits/帝国盛世.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.59rem + 0.78rem);
+            left: 11.58rem;
+            top: calc(219.19rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'z')"
+        >
+        <img
+          src="@/assets/image/fruits/青藤.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.75rem;
+            height: calc(8.59rem + 0.78rem);
+            left: 7.69rem;
+            top: calc(206.64rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'x')"
+        >
+        <img
+          src="@/assets/image/fruits/走进.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(10.11rem + 0.78rem);
+            left: 12.7rem;
+            top: calc(202.94rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'o')"
+        >
+        <img
+          src="@/assets/image/fruits/回家过年.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.2rem + 0.78rem);
+            left: 6.58rem;
+            top: calc(188.28rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'za')"
+        >
+        <img
+          src="@/assets/image/fruits/穆夏.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(9.22rem + 0.78rem);
+            left: 10.02rem;
+            top: calc(180.03rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'd')"
+        >
+        <img
+          src="@/assets/image/fruits/称霸侏罗纪.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(9.38rem + 0.78rem);
+            left: 6.69rem;
+            top: calc(171.81rem - 0.78rem)
+          "
+          @click="onClickFruit('theme', 'j')"
+        >
+        <img
+          src="@/assets/image/fruits/世界巨匠.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(10.67rem + 0.78rem);
+            left: 10.48rem;
+            top: calc(163.45rem - 0.78rem)
+          "
+          @click="onClickFruit('theme', 'h')"
+        >
+        <img
+          src="@/assets/image/fruits/暑期.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(7.19rem + 0.78rem);
+            left: 6.94rem;
+            top: calc(149.83rem - 0.78rem)
+          "
+          @click="onClickFruit('theme', 'l')"
+        >
+        <img
+          src="@/assets/image/fruits/金色阿富汗.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(11.34rem + 0.78rem);
+            left: 10.8rem;
+            top: calc(138.52rem - 0.78rem)
+          "
+          @click="onClickFruit('theme', 'k')"
+        >
+        <img
+          src="@/assets/image/fruits/从毕加索.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.98rem + 0.78rem);
+            left: 5.84rem;
+            top: calc(132.33rem - 0.78rem)
+          "
+          @click="onClickFruit('theme', 'g')"
+        >
+        <img
+          src="@/assets/image/fruits/兄弟王.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(10.92rem + 0.78rem);
+            left: 10.67rem;
+            top: calc(120.39rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'v')"
+        >
+        <img
+          src="@/assets/image/fruits/仰之弥高.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.44rem + 0.78rem);
+            left: 6.39rem;
+            top: calc(120.5rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'y')"
+        >
+        <img
+          src="@/assets/image/fruits/融合.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.75rem;
+            height: calc(9.13rem + 0.78rem);
+            left: 11.89rem;
+            top: calc(108.2rem - 0.78rem)
+          "
+          @click="onClickFruit('wuyiba', 'e')"
+        >
+        <img
+          src="@/assets/image/fruits/晶华.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 2.5rem;
+            height: calc(7.81rem + 0.78rem);
+            left: 8.72rem;
+            top: calc(98.95rem - 0.78rem)
+          "
+          @click="onClickFruit('theme', 'm')"
+        >
+        <img
+          src="@/assets/image/fruits/百花呈瑞.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.56rem + 0.78rem);
+            left: 10.72rem;
+            top: calc(86.63rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'w')"
+        >
+        <img
+          src="@/assets/image/fruits/考古江苏.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(7.81rem + 0.78rem);
+            left: 10.23rem;
+            top: calc(68.44rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'r')"
+        >
+        <img
+          src="@/assets/image/fruits/浮世绘.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 2.5rem;
+            height: calc(5rem + 0.78rem);
+            left: 8.53rem;
+            top: calc(59.44rem - 0.78rem)
+          "
+          @click="onClickFruit('theme', 'n')"
+        >
+        <img
+          src="@/assets/image/fruits/宋韵.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(8.28rem + 0.78rem);
+            left: 9.11rem;
+            top: calc(45.75rem - 0.78rem)
+          "
+          @click="onClickFruit('traditionModern', 'q')"
+        >
+        <img
+          src="@/assets/image/fruits/万水千山.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(12.23rem + 0.78rem);
+            left: 12.3rem;
+            top: calc(26.1rem - 0.78rem)
+          "
+          @click="onClickFruit('theme', 'i')"
+        >
+        <img
+          src="@/assets/image/fruits/家国.png"
+          class="fruit"
+          alt=""
+          style="
+            width: 3.13rem;
+            height: calc(10.31rem + 0.78rem);
+            left: 3.48rem;
+            top: calc(4.83rem - 0.78rem)
+          "
+          @click="onClickFruit('wuyiba', 'aa')"
+        >
+      </div>
     </div>
     <SlideTip
-      v-show="showSlideTip"
+      v-show="showSlideTip && showTree"
       class="slide-tip"
-      text="了<br>解<br>详<br>情"
     />
     <van-loading
       v-show="!showTree"
@@ -40,99 +393,80 @@
 </template>
 
 <script>
-import TWEEN from '@tweenjs/tween.js'
+import VisSenseFactory from 'vissense'
+const VisSense = VisSenseFactory(window)
 
 export default {
+  name: 'TreeAnimation',
   data() {
     return {
       showTree: false,
       showSlideTip: false,
-      animationBottom: {
-        value: 0
-      },
-      requestAnimationId: null,
-      treeImageNode: null,
-      timeoutId: null,
+      visMonitorList: [],
+      scrollTop: 0,
     }
   },
   computed: {
 
   },
+  created() {
+  },
   mounted() {
+    const fruitNodeList = document.getElementsByClassName('fruit')
+    for (const iterator of fruitNodeList) {
+      let visMonitor = VisSense(iterator).monitor({
+        percentagechange: function (VisMon) {
+          if (VisMon._state.percentage > 0.5) {
+            iterator.style.opacity = "1"
+            visMonitor.stop()
+          }
+        }
+      })
+      this.visMonitorList.push(visMonitor)
+      visMonitor.start()
+    }
+  },
+  activated() {
+    this.$refs['img-wrapper'].scrollTop = this.scrollTop
+  },
+  deactivated() {
+    this.scrollTop = this.$refs['img-wrapper'].scrollTop
   },
   destroyed() {
-    cancelAnimationFrame(this.requestAnimationId)
-    clearTimeout(this.timeoutId)
+    for (const iterator of this.visMonitorList) {
+      iterator.stop()
+    }
   },
   methods: {
-    animate() {
-      TWEEN.update()
-      // 这个动画如果用css实现,在ios里会有图片显示不全的问题。
-      this.treeImageNode.style.bottom = this.animationBottom.value + 'px'
-      this.requestAnimationId = requestAnimationFrame(this.animate)
-    },
     onTreeImgLoad() {
       this.showTree = true
+      this.$nextTick(() => {
+        this.$refs['img-wrapper'].scrollTop = this.$refs['tree-image'].scrollHeight
+      })
 
-      this.timeoutId = setTimeout(() => {
-        this.treeImageNode = document.getElementById('tree-image')
-
-        const tween1 = new TWEEN.Tween(this.animationBottom)
-        tween1.to({
-          value: -this.treeImageNode.clientHeight * 0.305
-        }, 39344 * 2 * 0.305)
-        tween1.easing(TWEEN.Easing.Sinusoidal.InOut)
-
-        const tween2 = new TWEEN.Tween(this.animationBottom)
-        tween2.to({
-          value: -this.treeImageNode.clientHeight * 0.50
-        }, 39344 * 2 * (0.50 - 0.305))
-        tween2.easing(TWEEN.Easing.Sinusoidal.InOut)
-
-        const tween3 = new TWEEN.Tween(this.animationBottom)
-        tween3.to({
-          value: -this.treeImageNode.clientHeight * 0.59
-        }, 39344 * 2 * (0.59 - 0.50))
-        tween3.easing(TWEEN.Easing.Sinusoidal.InOut)
-
-        const tween4 = new TWEEN.Tween(this.animationBottom)
-        tween4.to({
-          value: -this.treeImageNode.clientHeight * 0.7
-        }, 39344 * 2 * (0.7 - 0.59))
-        tween4.easing(TWEEN.Easing.Sinusoidal.InOut)
-
-        const tween5 = new TWEEN.Tween(this.animationBottom)
-        tween5.to({
-          value: -this.treeImageNode.clientHeight * 0.8
-        }, 39344 * 2 * (0.8 - 0.7))
-        tween5.easing(TWEEN.Easing.Sinusoidal.InOut)
-
-        const tween6 = new TWEEN.Tween(this.animationBottom)
-        tween6.to({
-          value: window.innerHeight - this.treeImageNode.clientHeight
-        }, 39344 * 2 * (1 - 0.8) - 39344 * 2 * window.innerHeight / this.treeImageNode.clientHeight)
-        tween6.onComplete(() => {
-          this.showSlideTip = true
-
-          let mc = new Hammer(this.$refs['hammer-target'])
-          mc.get('pan').set({ direction: Hammer.DIRECTION_ALL })
-          const that = this
-          mc.on("panup", function me() {
-            mc.off('panup', me)
-            that.$router.push({ name: 'TreeSelection' })
-          })
-        })
-        tween6.easing(TWEEN.Easing.Sinusoidal.InOut)
-
-        tween1.chain(tween2)
-        tween2.chain(tween3)
-        tween3.chain(tween4)
-        tween4.chain(tween5)
-        tween5.chain(tween6)
-
-        tween1.start()
-        this.requestAnimationId = this.animate()
-      }, 1000)
+      let mc = new Hammer(this.$refs['hammer-target'])
+      mc.get('pan').set({ direction: Hammer.DIRECTION_ALL })
+      const that = this
+      mc.on("pandown", function me() {
+        if (that.$refs['img-wrapper'].scrollTop === 0) {
+          that.$router.push({ name: 'TreeSelection' })
+          mc.off('pandown', me)
+        } else {
+          return
+        }
+      })
+    },
+    onImgWrapperScroll(e) {
+      if (this.$refs['tree-image'].scrollHeight - window.innerHeight - e.target.scrollTop <= 50) {
+        this.showSlideTip = true
+      } else if ( e.target.scrollTop === 0) {
+        this.showSlideTip = true
+      } else {
+        this.showSlideTip = false
+      }
+    },
+    onClickFruit(exhibitionType, exhibitionId) {
+      this.$router.push(`/ExhibitionDetailAnimation?exhibitionType=${exhibitionType}&exhibitionId=${exhibitionId}`)
     }
   }
 }
@@ -144,23 +478,26 @@ export default {
   height: 100%;
   position: relative;
   > .img-wrapper {
-    position: absolute;
-    left: 50%;
-    transform: translateX(-50%);
-    width: 18.28rem;
-    top: 0;
-    bottom: 0;
-    overflow: hidden;
-    > img {
-      position: absolute;
-      width: 100%;
-      opacity: 0;
-      bottom: 0;
-      animation-name: emerge;
-      animation-duration: 1s;
-      animation-timing-function: linear;
-      animation-delay: 0s;
-      animation-fill-mode: forwards;
+    height: 100%;
+    widows: 100%;
+    animation: emerge 1s 0.7s linear forwards;
+    overflow: auto;
+    opacity: 0;
+    > .img-wrapper-tall {
+      margin: 0 auto;
+      width: 18.28rem;
+      position: relative;
+      > .tree-image {
+        display: block;
+        width: 100%;
+      }
+      > .fruit {
+        position: absolute;
+        bottom: 30rem;
+        left: 3rem;
+        opacity: 0;
+        transition: opacity 1s;
+      }
     }
   }
   > .loading {
@@ -189,34 +526,4 @@ export default {
     opacity: 1;
   }
 }
-@keyframes start-slide {
-  0% {
-    top: 100%;
-    transform: translateY(-100%);
-  }
-  100% {
-    top: 100%;
-    transform: translateY(-95%);
-  }
-}
-@keyframes linear-slide {
-  0% {
-    top: 100%;
-    transform: translateY(-95%);
-  }
-  100% {
-    top: 0%;
-    transform: translateY(-5%);
-  }
-}
-@keyframes end-slide {
-  0% {
-    top: 0%;
-    transform: translateY(-5%);
-  }
-  100% {
-    top: 0;
-    transform: translateY(0);
-  }
-}
 </style>

+ 4 - 7
src/views/TreeSelection.vue

@@ -201,14 +201,10 @@ export default {
       currentTab: 'selectedTreeTabIdx',
     }),
   },
+  created() {
+  },
   mounted() {
-    let mc = new Hammer(this.$refs['hammer-target'])
-    mc.get('pan').set({ direction: Hammer.DIRECTION_ALL })
-    const that = this
-    mc.on("panup", function me(ev) {
-      mc.off('panup', me)
-      that.$router.push({ name: 'Chart' })
-    })
+    utils.registerSlideToRoute('hammer-target', 'Chart', this)
     this.intervalId = setInterval(() => {
       let idxBackup = 0
       switch (this.currentTab) {
@@ -264,6 +260,7 @@ export default {
         break
       }
     }, 41)
+
   },
   destroyed() {
     clearInterval(this.intervalId)

+ 1 - 1
vue.config.js

@@ -26,7 +26,7 @@ module.exports = {
     },
     plugins: [
       new webpack.ProvidePlugin({
-        // utils: ['/src/utils.js', 'default']
+        utils: ['/src/utils.js', 'default']
         // mapGetters: ['vuex', 'mapGetters']
       }),
     ],

+ 5 - 0
yarn.lock

@@ -8633,6 +8633,11 @@
     "core-util-is" "1.0.2"
     "extsprintf" "^1.2.0"
 
+"vissense@^0.10.0":
+  "integrity" "sha512-3q+c/45KBfrFssEsNb9eYw1Ewyw5Sj0m3W95a0kXthEx6/XVnkJ2K4CSVGjl3aprCi0rXdYjoKAoFb9Jl6HyIw=="
+  "resolved" "https://registry.npmmirror.com/vissense/-/vissense-0.10.0.tgz"
+  "version" "0.10.0"
+
 "vm-browserify@^1.0.1":
   "integrity" "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
   "resolved" "https://registry.npmmirror.com/vm-browserify/-/vm-browserify-1.1.2.tgz"